communication fix
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
import { Grid, createElement, setTooltip, createIcon, createCheckbox, createRadiobox, createPopup, showAlert, showConfirm } from "../../ui";
|
||||
import { Grid, createElement, setTooltip, setTooltipNext, createIcon, createCheckbox, createRadiobox, createPopup, showAlert, showConfirm } from "../../ui";
|
||||
import { r, nullOrEmpty, formatUrl, isEmail, isPhone } from "../../utility";
|
||||
import { createBox } from "./lib";
|
||||
import Contact from "./contact";
|
||||
@ -13,11 +13,11 @@ class NoteCol extends Grid.GridColumn {
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
static setValue(element, _val, item) {
|
||||
static setValue(element, _val, item, _col, grid) {
|
||||
const name = element.querySelector('.contact-name');
|
||||
name.innerText = item.Name;
|
||||
if (name.scrollWidth > name.offsetWidth) {
|
||||
setTooltip(name, item.Name);
|
||||
setTooltip(name, item.Name, false, grid.element);
|
||||
}
|
||||
element.querySelector('.contact-note').innerText = item.Notes;
|
||||
}
|
||||
@ -28,6 +28,7 @@ class CustomerCommunication {
|
||||
#option;
|
||||
#contacts;
|
||||
#followers;
|
||||
#buttonFollower;
|
||||
#enter;
|
||||
#message;
|
||||
#data = {};
|
||||
@ -115,20 +116,42 @@ class CustomerCommunication {
|
||||
const mp = String(c.MobilePhone).trim();
|
||||
const email = String(c.Email).trim();
|
||||
const pref = String(c.ContactPreference);
|
||||
if ((pref === '0' || pref === '2') && !isPhone(mp) ||
|
||||
if ((pref !== '1') && !isPhone(mp) ||
|
||||
pref === '1' && !isEmail(email)) {
|
||||
continue;
|
||||
}
|
||||
const to = pref === '0' || pref === '2' ? mp : email;
|
||||
const to = pref === '1' ? email : mp;
|
||||
let icon;
|
||||
let method;
|
||||
switch (pref) {
|
||||
case '0':
|
||||
icon = 'comment-lines';
|
||||
method = r('textsToColon', 'Texts to:');
|
||||
break;
|
||||
case '2':
|
||||
icon = 'mobile';
|
||||
method = r('callsToColon', 'Calls to:');
|
||||
break;
|
||||
default:
|
||||
icon = 'envelope';
|
||||
method = r('emailsToColon', 'Emails to:');
|
||||
break;
|
||||
}
|
||||
const span = createElement('span', span => {
|
||||
span.dataset.to = to;
|
||||
span.dataset.name = c.Name;
|
||||
span.innerText = c.Name;
|
||||
});
|
||||
const item = createElement('div', 'contact-item',
|
||||
createIcon('fa-light', pref === '0' ? 'comment-lines' : pref === '2' ? 'mobile' : 'envelope'),
|
||||
setTooltip(createElement('span', span => {
|
||||
span.dataset.to = to;
|
||||
span.dataset.name = c.Name;
|
||||
span.innerText = nullOrEmpty(to) ? c.Name : to;
|
||||
}), to, true)
|
||||
createIcon('fa-light', icon),
|
||||
span
|
||||
);
|
||||
this.#contacts.appendChild(item);
|
||||
let tip = `${method} ${to}`;
|
||||
if (span.scrollWidth > span.offsetWidth) {
|
||||
tip = r('nameColon', 'Name:') + ` ${c.Name}\n${tip}`;
|
||||
}
|
||||
setTooltip(span, tip);
|
||||
}
|
||||
this.#message.scrollTop = this.#message.scrollHeight
|
||||
}
|
||||
@ -145,6 +168,7 @@ class CustomerCommunication {
|
||||
this.#container.querySelector('.button-edit-contacts').style.display = flag === true ? 'none' : '';
|
||||
this.#container.querySelector('.button-edit-followers').style.display = flag === true ? 'none' : '';
|
||||
this.#enter.disabled = flag === true;
|
||||
this.#container.querySelector('.button-send-message').style.display = flag === true ? 'none' : '';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -156,6 +180,21 @@ class CustomerCommunication {
|
||||
return;
|
||||
}
|
||||
this.#container.querySelector('.button-edit-contacts').style.display = flag === true ? 'none' : '';
|
||||
this.#container.querySelector('.button-edit-followers').style.display = flag === true ? 'none' : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} name
|
||||
*/
|
||||
set companyName(name) {
|
||||
this.#option.companyName = name;
|
||||
const div = this.#container.querySelector('.title-company');
|
||||
if (nullOrEmpty(name)) {
|
||||
div.style.display = 'none';
|
||||
} else {
|
||||
div.innerText = name;
|
||||
div.style.display = '';
|
||||
}
|
||||
}
|
||||
|
||||
get followers() {
|
||||
@ -169,6 +208,7 @@ class CustomerCommunication {
|
||||
this.#followers.replaceChildren();
|
||||
if (followers?.length > 0) {
|
||||
this.#container.querySelector('.follower-bar').style.display = '';
|
||||
this.#container.querySelector('.follower-bar>.bar-list').appendChild(this.#buttonFollower);
|
||||
for (let f of followers) {
|
||||
if (f.OptOut) {
|
||||
continue;
|
||||
@ -177,28 +217,40 @@ class CustomerCommunication {
|
||||
const email = String(f.Email).trim();
|
||||
const tips = [];
|
||||
if (f.SendEmail) {
|
||||
tips.push(r('emailColon', 'Email:') + ` ${email}`);
|
||||
tips.push(r('emailsToColon', 'Emails to:') + ` ${email}`);
|
||||
}
|
||||
if (f.SendText) {
|
||||
tips.push(r('phoneColon', 'Mobile Phone:' + ` ${mp}`));
|
||||
tips.push(r('textsToColon', 'Texts to:' + ` ${mp}`));
|
||||
}
|
||||
let icon;
|
||||
if (f.SendText && f.SendEmail) {
|
||||
icon = 'at';
|
||||
} else {
|
||||
icon = f.SendText ? 'comment-lines' : 'envelope';
|
||||
}
|
||||
const span = createElement('span', span => {
|
||||
if (f.SendEmail) {
|
||||
span.dataset.email = email;
|
||||
}
|
||||
if (f.SendText) {
|
||||
span.dataset.mp = mp;
|
||||
}
|
||||
span.dataset.name = f.Name;
|
||||
span.innerText = f.Name;
|
||||
});
|
||||
const item = createElement('div', 'contact-item',
|
||||
createIcon('fa-light', f.SendText ? 'comment-lines' : 'envelope'),
|
||||
setTooltip(createElement('span', span => {
|
||||
if (f.SendEmail) {
|
||||
span.dataset.email = email;
|
||||
}
|
||||
if (f.SendText) {
|
||||
span.dataset.mp = mp;
|
||||
}
|
||||
span.dataset.name = f.Name;
|
||||
span.innerText = f.SendText ? mp : email;
|
||||
}), tips.join('\n'), true)
|
||||
createIcon('fa-light', icon),
|
||||
span
|
||||
);
|
||||
this.#followers.appendChild(item);
|
||||
if (span.scrollWidth > span.offsetWidth) {
|
||||
tips.splice(0, 0, r('nameColon', 'Name:') + ` ${c.Name}`);
|
||||
}
|
||||
setTooltip(span, tips.join('\n'));
|
||||
}
|
||||
} else {
|
||||
this.#container.querySelector('.follower-bar').style.display = 'none';
|
||||
this.#container.querySelector('.button-edit-contacts').insertAdjacentElement('beforebegin', this.#buttonFollower)
|
||||
}
|
||||
this.#message.scrollTop = this.#message.scrollHeight
|
||||
}
|
||||
@ -251,6 +303,7 @@ class CustomerCommunication {
|
||||
);
|
||||
// contacts
|
||||
const readonly = option.readonly;
|
||||
const recordReadonly = option.recordReadonly;
|
||||
const contacts = createElement('div');
|
||||
container.append(
|
||||
createElement('div', 'contact-bar',
|
||||
@ -264,7 +317,7 @@ class CustomerCommunication {
|
||||
createElement('button', button => {
|
||||
button.className = 'roundbtn button-edit-contacts';
|
||||
button.style.backgroundColor = 'rgb(1, 199, 172)';
|
||||
if (readonly === true || option.recordReadonly) {
|
||||
if (readonly === true) {
|
||||
button.style.display = 'none';
|
||||
}
|
||||
button.appendChild(createIcon('fa-solid', 'user-edit'));
|
||||
@ -273,6 +326,7 @@ class CustomerCommunication {
|
||||
const pop = createPopup(
|
||||
createElement('div', div => {
|
||||
div.style.display = 'flex';
|
||||
div.style.alignItems = 'center';
|
||||
div.append(
|
||||
createElement('div', div => {
|
||||
div.className = 'popup-move';
|
||||
@ -293,12 +347,16 @@ class CustomerCommunication {
|
||||
button.style.backgroundColor = 'rgb(1, 199, 172)';
|
||||
button.style.marginRight = '10px';
|
||||
button.className = 'roundbtn button-add-contact';
|
||||
if (recordReadonly) {
|
||||
button.style.display = 'none';
|
||||
}
|
||||
button.appendChild(createIcon('fa-solid', 'user-plus', {
|
||||
width: '16px',
|
||||
height: '16px'
|
||||
}));
|
||||
button.addEventListener('click', () => {
|
||||
const add = new Contact({
|
||||
company: !nullOrEmpty(this.#data.companyCode),
|
||||
onSave: (item) => {
|
||||
const exists = this.#gridContact.source.some(s => s.Name === item.Name && s.MobilePhone === item.MobilePhone);
|
||||
if (exists) {
|
||||
@ -326,10 +384,16 @@ class CustomerCommunication {
|
||||
}),
|
||||
createElement('div', null,
|
||||
createElement('div', div => {
|
||||
if (nullOrEmpty(this.#data.companyCode)) {
|
||||
div.style.display = 'none';
|
||||
}
|
||||
div.style.fontWeight = 'bold';
|
||||
div.innerText = r('contactFromRecord', 'Contacts from Customer Record');
|
||||
}),
|
||||
createElement('div', div => {
|
||||
if (nullOrEmpty(this.#data.companyCode)) {
|
||||
div.style.display = 'none';
|
||||
}
|
||||
div.className = 'contacts-record';
|
||||
div.style.maxHeight = '400px';
|
||||
div.style.width = '660px';
|
||||
@ -377,6 +441,7 @@ class CustomerCommunication {
|
||||
const buttonCol = {
|
||||
type: Grid.ColumnTypes.Icon,
|
||||
width: 40,
|
||||
visible: !recordReadonly,
|
||||
align: 'center',
|
||||
iconType: 'fa-light'
|
||||
};
|
||||
@ -390,6 +455,7 @@ class CustomerCommunication {
|
||||
onclick: function () {
|
||||
const edit = new Contact({
|
||||
contact: this,
|
||||
company: !nullOrEmpty(This.#data.companyCode),
|
||||
onSave: item => {
|
||||
const exists =
|
||||
This.#gridContact.source.some(s => s !== this && s.Name === item.Name && s.MobilePhone === item.MobilePhone) ||
|
||||
@ -427,7 +493,7 @@ class CustomerCommunication {
|
||||
nameCol,
|
||||
{ key: 'Email', width: 180 },
|
||||
{ key: 'MobilePhone', width: 130 },
|
||||
createEditCol(grid),
|
||||
createEditCol(this),
|
||||
{
|
||||
key: 'delete',
|
||||
...buttonCol,
|
||||
@ -490,6 +556,11 @@ class CustomerCommunication {
|
||||
});
|
||||
grid.extraRows = customerRecords.filter(c => !nullOrEmpty(c.Notes)).length;
|
||||
grid.source = customerRecords;
|
||||
grid.selectedRowChanged = index => {
|
||||
if (index >= 0 && this.#gridWo.selectedIndexes?.length > 0) {
|
||||
this.#gridWo.selectedIndexes = [];
|
||||
}
|
||||
};
|
||||
this.#gridContact = grid;
|
||||
|
||||
// contacts from work order only
|
||||
@ -503,14 +574,14 @@ class CustomerCommunication {
|
||||
nameCol,
|
||||
{ key: 'Email', width: 180 },
|
||||
{ key: 'MobilePhone', width: 130 },
|
||||
createEditCol(gridWo),
|
||||
createEditCol(this),
|
||||
{
|
||||
key: 'delete',
|
||||
...buttonCol,
|
||||
text: 'times',
|
||||
tooltip: r('delete', 'Delete'),
|
||||
events: {
|
||||
onclick: () => {
|
||||
onclick: function () {
|
||||
showConfirm(r('remoteContact', 'Remove Contact'), r('removeFromWorkorder', 'You are removing {name} from work order.\n\nDo you want to Continue?').replace('{name}', this.Name), [
|
||||
{ key: 'continue', text: r('continue', 'Continue') },
|
||||
{ key: 'cancel', text: r('cancel', 'Cancel') }
|
||||
@ -544,6 +615,11 @@ class CustomerCommunication {
|
||||
});
|
||||
gridWo.extraRows = workOrderOnly.filter(c => !nullOrEmpty(c.Notes)).length;
|
||||
gridWo.source = workOrderOnly;
|
||||
gridWo.selectedRowChanged = index => {
|
||||
if (index >= 0 && this.#gridContact.selectedIndexes?.length > 0) {
|
||||
this.#gridContact.selectedIndexes = [];
|
||||
}
|
||||
};
|
||||
this.#gridWo = gridWo;
|
||||
});
|
||||
});
|
||||
@ -554,6 +630,131 @@ class CustomerCommunication {
|
||||
this.#contacts = contacts;
|
||||
// followers
|
||||
const followers = createElement('div');
|
||||
const buttonEditFollower = createElement('button', button => {
|
||||
button.className = 'roundbtn button-edit-followers';
|
||||
button.style.backgroundColor = 'rgb(48, 107, 255)';
|
||||
if (readonly === true || recordReadonly) {
|
||||
button.style.display = 'none';
|
||||
}
|
||||
button.appendChild(createIcon('fa-solid', 'pen'));
|
||||
setTooltip(button, r('editFollower', 'Edit Followers'));
|
||||
button.addEventListener('click', () => {
|
||||
const pop = createPopup(
|
||||
createElement('div', div => {
|
||||
div.style.display = 'flex';
|
||||
div.style.alignItems = 'center';
|
||||
div.append(
|
||||
createElement('div', div => {
|
||||
div.className = 'popup-move';
|
||||
div.style.flex = '1 1 auto';
|
||||
div.innerText = r('editContacts', 'Edit Contacts') + '\n' + r('followers', 'Followers');
|
||||
}),
|
||||
createElement('button', button => {
|
||||
button.style.flex = '0 0 auto';
|
||||
button.style.backgroundColor = 'rgb(1, 199, 172)';
|
||||
button.style.marginRight = '10px';
|
||||
button.className = 'roundbtn button-add-follower';
|
||||
button.appendChild(createIcon('fa-solid', 'user-plus', {
|
||||
width: '16px',
|
||||
height: '16px'
|
||||
}));
|
||||
button.addEventListener('click', () => {
|
||||
if (typeof this.#option.onInitFollower === 'function') {
|
||||
this.#option.onInitFollower().then(data => {
|
||||
if (typeof data === 'string') {
|
||||
showAlert(r('customerRecord', 'Customer Record'), data, 'warn');
|
||||
return;
|
||||
}
|
||||
const add = new Follower({
|
||||
followers: data,
|
||||
onOk: list => {
|
||||
if (typeof this.#option.onAddFollower === 'function') {
|
||||
const result = this.#option.onAddFollower(list);
|
||||
if (typeof result?.then === 'function') {
|
||||
return result.then(r => {
|
||||
this.#gridFollower.source = r;
|
||||
return r;
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
add.show(container);
|
||||
})
|
||||
}
|
||||
});
|
||||
setTooltip(button, r('addFollower', 'Add Follower'))
|
||||
})
|
||||
)
|
||||
}),
|
||||
createElement('div', null,
|
||||
createElement('div', div => {
|
||||
div.style.fontWeight = 'bold';
|
||||
div.innerText = r('contactFromRecord', 'Contacts from Customer Record');
|
||||
}),
|
||||
createElement('div', div => {
|
||||
div.className = 'followers-record';
|
||||
div.style.maxHeight = '400px';
|
||||
div.style.width = '660px';
|
||||
})
|
||||
)
|
||||
);
|
||||
pop.show(container).then(() => {
|
||||
const grid = new Grid();
|
||||
grid.height = 0;
|
||||
grid.allowHtml = true;
|
||||
grid.headerVisible = false;
|
||||
grid.columns = [
|
||||
{
|
||||
key: 'type',
|
||||
type: Grid.ColumnTypes.Icon,
|
||||
width: 50,
|
||||
filter: c => c.SendText ? 'comment-lines' : 'envelope',
|
||||
className: 'icon-contact-type',
|
||||
iconType: 'fa-light'
|
||||
},
|
||||
{ key: 'Name', width: 160 },
|
||||
{ key: 'Email', width: 180 },
|
||||
{ key: 'MobilePhone', width: 130 },
|
||||
{
|
||||
key: 'delete',
|
||||
type: Grid.ColumnTypes.Icon,
|
||||
width: 40,
|
||||
align: 'center',
|
||||
iconType: 'fa-light',
|
||||
text: 'times',
|
||||
tooltip: r('delete', 'Delete'),
|
||||
events: {
|
||||
onclick: function () {
|
||||
showConfirm(
|
||||
r('deleteFollower', 'Delete Follower'),
|
||||
r('promptDeleteFollower', 'Do you want to delete this follower?'))
|
||||
.then(result => {
|
||||
if (result?.key === 'yes') {
|
||||
if (typeof option.onDeleteFollower === 'function') {
|
||||
option.onDeleteFollower(result.key, this);
|
||||
}
|
||||
const index = grid.source.indexOf(this);
|
||||
if (index >= 0) {
|
||||
const source = grid.source;
|
||||
source.splice(index, 1);
|
||||
grid.extraRows = source.filter(c => !nullOrEmpty(c.Notes)).length;
|
||||
grid.source = source;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
grid.init(pop.container.querySelector('.followers-record'));
|
||||
grid.source = this.#data.followers;
|
||||
this.#gridFollower = grid;
|
||||
});
|
||||
});
|
||||
});
|
||||
this.#buttonFollower = buttonEditFollower;
|
||||
container.append(
|
||||
createElement('div', div => {
|
||||
div.className = 'contact-bar follower-bar';
|
||||
@ -570,129 +771,7 @@ class CustomerCommunication {
|
||||
), r('copied', 'Copied')),
|
||||
createElement('div', 'bar-list',
|
||||
followers,
|
||||
createElement('button', button => {
|
||||
button.className = 'roundbtn button-edit-followers';
|
||||
button.style.backgroundColor = 'rgb(48, 107, 255)';
|
||||
if (readonly === true) {
|
||||
button.style.display = 'none';
|
||||
}
|
||||
button.appendChild(createIcon('fa-solid', 'pen'));
|
||||
setTooltip(button, r('editFollower', 'Edit Followers'));
|
||||
button.addEventListener('click', () => {
|
||||
const pop = createPopup(
|
||||
createElement('div', div => {
|
||||
div.style.display = 'flex';
|
||||
div.style.alignItems = 'center';
|
||||
div.append(
|
||||
createElement('div', div => {
|
||||
div.className = 'popup-move';
|
||||
div.style.flex = '1 1 auto';
|
||||
div.innerText = r('editContacts', 'Edit Contacts') + '\n' + r('followers', 'Followers');
|
||||
}),
|
||||
createElement('button', button => {
|
||||
button.style.flex = '0 0 auto';
|
||||
button.style.backgroundColor = 'rgb(1, 199, 172)';
|
||||
button.style.marginRight = '10px';
|
||||
button.className = 'roundbtn button-add-follower';
|
||||
button.appendChild(createIcon('fa-solid', 'user-plus', {
|
||||
width: '16px',
|
||||
height: '16px'
|
||||
}));
|
||||
button.addEventListener('click', () => {
|
||||
if (typeof this.#option.onInitFollower === 'function') {
|
||||
this.#option.onInitFollower().then(data => {
|
||||
if (typeof data === 'string') {
|
||||
showAlert(r('customerRecord', 'Customer Record'), data, 'warn');
|
||||
return;
|
||||
}
|
||||
const add = new Follower({
|
||||
followers: data,
|
||||
onOk: list => {
|
||||
if (typeof this.#option.onAddFollower === 'function') {
|
||||
const result = this.#option.onAddFollower(list);
|
||||
if (typeof result?.then === 'function') {
|
||||
return result.then(r => {
|
||||
this.#gridFollower.source = r;
|
||||
return r;
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
add.show(container);
|
||||
})
|
||||
}
|
||||
});
|
||||
setTooltip(button, r('addFollower', 'Add Follower'))
|
||||
})
|
||||
)
|
||||
}),
|
||||
createElement('div', null,
|
||||
createElement('div', div => {
|
||||
div.style.fontWeight = 'bold';
|
||||
div.innerText = r('contactFromRecord', 'Contacts from Customer Record');
|
||||
}),
|
||||
createElement('div', div => {
|
||||
div.className = 'followers-record';
|
||||
div.style.maxHeight = '400px';
|
||||
div.style.width = '660px';
|
||||
})
|
||||
)
|
||||
);
|
||||
pop.show(container).then(() => {
|
||||
const grid = new Grid();
|
||||
grid.height = 0;
|
||||
grid.allowHtml = true;
|
||||
grid.headerVisible = false;
|
||||
grid.columns = [
|
||||
{
|
||||
key: 'type',
|
||||
type: Grid.ColumnTypes.Icon,
|
||||
width: 50,
|
||||
filter: c => c.SendText ? 'comment-lines' : 'envelope',
|
||||
className: 'icon-contact-type',
|
||||
iconType: 'fa-light'
|
||||
},
|
||||
{ key: 'Name', width: 160 },
|
||||
{ key: 'Email', width: 180 },
|
||||
{ key: 'MobilePhone', width: 130 },
|
||||
{
|
||||
key: 'delete',
|
||||
type: Grid.ColumnTypes.Icon,
|
||||
width: 40,
|
||||
align: 'center',
|
||||
iconType: 'fa-light',
|
||||
text: 'times',
|
||||
tooltip: r('delete', 'Delete'),
|
||||
events: {
|
||||
onclick: function () {
|
||||
showConfirm(
|
||||
r('deleteFollower', 'Delete Follower'),
|
||||
r('promptDeleteFollower', 'Do you want to delete this follower?')).then(result => {
|
||||
if (result?.key === 'yes') {
|
||||
if (typeof option.onDeleteFollower === 'function') {
|
||||
option.onDeleteFollower(result.key, this);
|
||||
}
|
||||
const index = grid.source.indexOf(this);
|
||||
if (index >= 0) {
|
||||
const source = grid.source;
|
||||
source.splice(index, 1);
|
||||
grid.extraRows = source.filter(c => !nullOrEmpty(c.Notes)).length;
|
||||
grid.source = source;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
grid.init(pop.container.querySelector('.followers-record'));
|
||||
grid.source = this.#data.followers;
|
||||
this.#gridFollower = grid;
|
||||
});
|
||||
});
|
||||
})
|
||||
buttonEditFollower
|
||||
)
|
||||
)
|
||||
);
|
||||
@ -718,6 +797,9 @@ class CustomerCommunication {
|
||||
createElement('button', button => {
|
||||
button.className = 'roundbtn button-send-message';
|
||||
button.style.backgroundColor = 'rgb(19, 150, 204)';
|
||||
if (readonly === true) {
|
||||
button.style.display = 'none';
|
||||
}
|
||||
button.appendChild(createIcon('fa-solid', 'paper-plane'));
|
||||
setTooltip(button, r('sendMessage', 'Send Message'));
|
||||
button.addEventListener('click', () => {
|
||||
|
Reference in New Issue
Block a user