mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-09-20 15:45:55 +08:00
Some cleanups for new AddressBook
This commit is contained in:
parent
c162a3acc6
commit
052f34a9f5
|
@ -15,7 +15,6 @@ export class ContactModel extends AbstractModel {
|
|||
constructor() {
|
||||
super();
|
||||
|
||||
this.properties = [];
|
||||
this.jCard = new JCard();
|
||||
|
||||
this.addObservables({
|
||||
|
@ -30,8 +29,7 @@ export class ContactModel extends AbstractModel {
|
|||
surName: '', // LastName
|
||||
middleName: '', // MiddleName
|
||||
namePrefix: '', // NamePrefix
|
||||
nameSuffix: '', // NameSuffix
|
||||
nickname: null
|
||||
nameSuffix: '' // NameSuffix
|
||||
});
|
||||
// this.email = koArrayWithDestroy();
|
||||
this.email = ko.observableArray();
|
||||
|
@ -43,6 +41,15 @@ export class ContactModel extends AbstractModel {
|
|||
|
||||
fullName: () => (this.givenName() + ' ' + this.surName()).trim(),
|
||||
|
||||
nickname: {
|
||||
read: () => {
|
||||
let prop = this.jCard.getOne('nickname');
|
||||
return prop && prop.value;
|
||||
},
|
||||
write: value =>
|
||||
value ? this.jCard.set('nickname', value/*, params, group*/) : this.jCard.remove('nickname')
|
||||
},
|
||||
|
||||
display: () => {
|
||||
let a = this.jCard.getOne('fn')?.value,
|
||||
b = this.fullName(),
|
||||
|
@ -85,17 +92,12 @@ export class ContactModel extends AbstractModel {
|
|||
static reviveFromJson(json) {
|
||||
const contact = super.reviveFromJson(json);
|
||||
if (contact) {
|
||||
let list = [];
|
||||
|
||||
let jCard = new JCard(json.jCard),
|
||||
props = jCard.getOne('n')?.value;
|
||||
props && props.forEach((value, index) =>
|
||||
value && contact[nProps[index]](value)
|
||||
);
|
||||
|
||||
props = jCard.getOne('nickname');
|
||||
props && contact.nickname(props.value);
|
||||
|
||||
['email', 'tel', 'url'].forEach(field => {
|
||||
props = jCard.get(field);
|
||||
props && props.forEach(prop => {
|
||||
|
@ -106,7 +108,6 @@ export class ContactModel extends AbstractModel {
|
|||
});
|
||||
});
|
||||
|
||||
contact.properties = list;
|
||||
contact.jCard = jCard;
|
||||
}
|
||||
return contact;
|
||||
|
@ -116,7 +117,7 @@ export class ContactModel extends AbstractModel {
|
|||
* @returns {string}
|
||||
*/
|
||||
generateUid() {
|
||||
return ''+this.id;
|
||||
return '' + this.id;
|
||||
}
|
||||
|
||||
addEmail() {
|
||||
|
@ -160,8 +161,6 @@ export class ContactModel extends AbstractModel {
|
|||
]/*, params, group*/);
|
||||
// jCard.parseFullName({set:true});
|
||||
|
||||
this.nickname() ? jCard.set('nickname', this.nickname()/*, params, group*/) : jCard.remove('nickname');
|
||||
|
||||
['email', 'tel', 'url'].forEach(field => {
|
||||
let values = this[field].map(item => item.value());
|
||||
jCard.get(field).forEach(prop => {
|
||||
|
|
|
@ -148,10 +148,6 @@
|
|||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
&.read-only .button-save-contact {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.b-view-content {
|
||||
|
|
|
@ -23,7 +23,6 @@ import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
|||
import { AskPopupView } from 'View/Popup/Ask';
|
||||
|
||||
const
|
||||
viewProperties = koArrayWithDestroy(),
|
||||
CONTACTS_PER_PAGE = 50,
|
||||
ScopeContacts = 'Contacts';
|
||||
|
||||
|
@ -38,20 +37,15 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
search: '',
|
||||
contactsCount: 0,
|
||||
|
||||
currentContact: null,
|
||||
selectorContact: null,
|
||||
|
||||
importUploaderButton: null,
|
||||
importButton: null,
|
||||
|
||||
contactsPage: 1,
|
||||
|
||||
viewClearSearch: false,
|
||||
|
||||
viewReadOnly: false,
|
||||
|
||||
viewSaving: false,
|
||||
|
||||
watchDirty: false,
|
||||
watchHash: false,
|
||||
hasChanges: false,
|
||||
|
||||
contact: null
|
||||
});
|
||||
|
@ -62,7 +56,7 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
|
||||
this.selector = new Selector(
|
||||
ContactUserStore,
|
||||
this.currentContact,
|
||||
this.selectorContact,
|
||||
null,
|
||||
'.e-contact-item .actionHandle',
|
||||
'.e-contact-item .checkboxItem',
|
||||
|
@ -87,7 +81,7 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
|
||||
contactsCheckedOrSelected: () => {
|
||||
const checked = ContactUserStore.filter(item => item.checked && item.checked()),
|
||||
selected = this.currentContact();
|
||||
selected = this.selectorContact();
|
||||
|
||||
return selected
|
||||
? [...checked, selected].unique()
|
||||
|
@ -96,34 +90,27 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
|
||||
contactsCheckedOrSelectedUids: () => this.contactsCheckedOrSelected().map(contact => contact.id()),
|
||||
|
||||
contactsSyncEnabled: () => ContactUserStore.allowSync() && ContactUserStore.syncMode(),
|
||||
|
||||
viewHash: () => '' + viewProperties.map(property => property.value && property.value()).join('')
|
||||
contactsSyncEnabled: () => ContactUserStore.allowSync() && ContactUserStore.syncMode()
|
||||
});
|
||||
|
||||
this.search.subscribe(() => this.reloadContactList());
|
||||
|
||||
this.viewHash.subscribe(() => {
|
||||
if (this.watchHash() && !this.viewReadOnly() && !this.watchDirty()) {
|
||||
this.watchDirty(true);
|
||||
}
|
||||
});
|
||||
|
||||
this.saveCommand = this.saveCommand.bind(this);
|
||||
|
||||
// this.hasChanges(!!contact()?.toJSON().jCard);
|
||||
|
||||
decorateKoCommands(this, {
|
||||
// close: self => !self.watchDirty(),
|
||||
// close: self => !self.hasChanges(),
|
||||
deleteCommand: self => 0 < self.contactsCheckedOrSelected().length,
|
||||
newMessageCommand: self => 0 < self.contactsCheckedOrSelected().length,
|
||||
saveCommand: self => !self.viewSaving() && !self.viewReadOnly()
|
||||
&& (self.contact()?.hasValidName() || self.contact()?.email().length),
|
||||
saveCommand: self => !self.viewSaving() && !self.hasChanges(),
|
||||
syncCommand: self => !self.contacts.syncing() && !self.contacts.importing()
|
||||
});
|
||||
}
|
||||
|
||||
newContact() {
|
||||
this.populateViewContact(null);
|
||||
this.currentContact(null);
|
||||
this.selectorContact(null);
|
||||
}
|
||||
|
||||
deleteCommand() {
|
||||
|
@ -207,7 +194,7 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
}
|
||||
|
||||
if (res) {
|
||||
this.watchDirty(false);
|
||||
this.hasChanges(false);
|
||||
}
|
||||
}, {
|
||||
RequestUid: requestUid,
|
||||
|
@ -237,14 +224,14 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
removeCheckedOrSelectedContactsFromList() {
|
||||
const contacts = this.contactsCheckedOrSelected();
|
||||
|
||||
let currentContact = this.currentContact(),
|
||||
let selectorContact = this.selectorContact(),
|
||||
count = ContactUserStore.length;
|
||||
|
||||
if (contacts.length) {
|
||||
contacts.forEach(contact => {
|
||||
if (currentContact && currentContact.id() === contact.id()) {
|
||||
currentContact = null;
|
||||
this.currentContact(null);
|
||||
if (selectorContact && selectorContact.id() === contact.id()) {
|
||||
selectorContact = null;
|
||||
this.selectorContact(null);
|
||||
}
|
||||
|
||||
contact.deleted(true);
|
||||
|
@ -282,18 +269,12 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
* @param {?ContactModel} contact
|
||||
*/
|
||||
populateViewContact(contact) {
|
||||
this.watchHash(false);
|
||||
|
||||
if (!contact) {
|
||||
contact = new ContactModel;
|
||||
}
|
||||
this.viewReadOnly(contact.readOnly());
|
||||
this.contact(contact);
|
||||
|
||||
viewProperties(contact.properties);
|
||||
|
||||
this.watchDirty(false);
|
||||
this.watchHash(true);
|
||||
this.hasChanges(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -330,7 +311,6 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
ContactUserStore(list);
|
||||
|
||||
ContactUserStore.loading(false);
|
||||
this.viewClearSearch(!!this.search());
|
||||
},
|
||||
{
|
||||
Offset: offset,
|
||||
|
@ -368,12 +348,12 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
|
||||
// initUploader
|
||||
|
||||
if (this.importUploaderButton()) {
|
||||
if (this.importButton()) {
|
||||
const j = new Jua({
|
||||
action: serverRequest('UploadContacts'),
|
||||
limit: 1,
|
||||
disableDocumentDropPrevent: true,
|
||||
clickElement: this.importUploaderButton()
|
||||
clickElement: this.importButton()
|
||||
});
|
||||
|
||||
if (j) {
|
||||
|
@ -391,7 +371,7 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
}
|
||||
|
||||
onClose() {
|
||||
if (this.watchDirty() && AskPopupView.hidden()) {
|
||||
if (this.hasChanges() && AskPopupView.hidden()) {
|
||||
showScreenPopup(AskPopupView, [
|
||||
i18n('POPUPS_ASK/DESC_WANT_CLOSE_THIS_WINDOW'),
|
||||
() => this.close()
|
||||
|
@ -408,17 +388,15 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
|
||||
onHide() {
|
||||
this.contact(null);
|
||||
this.currentContact(null);
|
||||
this.selectorContact(null);
|
||||
this.search('');
|
||||
this.contactsCount(0);
|
||||
|
||||
ContactUserStore([]);
|
||||
|
||||
this.sLastComposeFocusedField = '';
|
||||
|
||||
if (this.bBackToCompose) {
|
||||
this.bBackToCompose = false;
|
||||
|
||||
showMessageComposer();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<a id="contacts-more-dropdown-id" class="btn dropdown-toggle fontastic" href="#" tabindex="-1">☰</a>
|
||||
<menu class="dropdown-menu right-edge" role="menu" aria-labelledby="contacts-more-dropdown-id">
|
||||
<li role="presentation">
|
||||
<a href="#" tabindex="-1" data-bind="initDom: importUploaderButton">
|
||||
<a href="#" tabindex="-1" data-bind="initDom: importButton">
|
||||
<i data-bind="css: {'icon-import': !contacts.importing(), 'icon-spinner': contacts.importing}"></i>
|
||||
<span data-i18n="CONTACTS/BUTTON_IMPORT"></span>
|
||||
</a>
|
||||
|
@ -48,7 +48,7 @@
|
|||
</div>
|
||||
<div class="b-list-content g-ui-user-select-none" data-bind="css: {'hideContactListCheckbox': !useCheckboxesInList()}">
|
||||
<div class="content">
|
||||
<div class="listClear" data-bind="visible: viewClearSearch() && '' !== search()">
|
||||
<div class="listClear" data-bind="visible: !!search()">
|
||||
<span class="g-ui-link" data-i18n="CONTACTS/CLEAR_SEARCH" data-bind="click: clearSearch"></span>
|
||||
</div>
|
||||
<div class="listEmptyList" data-bind="visible: 0 === contacts().length && '' === search() && !contacts.loading()"
|
||||
|
@ -72,16 +72,16 @@
|
|||
<!-- ko template: { name: 'Paginator', data: contactsPaginator } --><!-- /ko -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="b-view-content-toolbar btn-toolbar" data-bind="css: {'read-only': viewReadOnly}, i18nUpdate: contact">
|
||||
<div class="b-view-content-toolbar btn-toolbar" data-bind="i18nUpdate: contact">
|
||||
<!-- ko with: contact -->
|
||||
<div class="btn-group">
|
||||
<button class="btn button-save-contact" data-bind="command: $root.saveCommand, css: {'dirty': $root.watchDirty}">
|
||||
<button class="btn button-save-contact" data-bind="visible: !readOnly(), command: $root.saveCommand, css: {'dirty': $root.hasChanges}">
|
||||
<i data-bind="css: {'icon-ok': !$root.viewSaving(), 'icon-spinner': $root.viewSaving()}"></i>
|
||||
<span data-i18n="CONTACTS/BUTTON_CREATE_CONTACT" data-bind="visible: !id"></span>
|
||||
<span data-i18n="CONTACTS/BUTTON_CREATE_CONTACT" data-bind="visible: !id()"></span>
|
||||
<span data-i18n="CONTACTS/BUTTON_UPDATE_CONTACT" data-bind="visible: id"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group dropdown" data-bind="registerBootstrapDropdown: true">
|
||||
<div class="btn-group dropdown" data-bind="visible: !readOnly(), registerBootstrapDropdown: true">
|
||||
<a id="button-add-prop-dropdown-id" href="#" tabindex="-1" class="btn dropdown-toggle" data-i18n="CONTACTS/ADD_MENU_LABEL"></a>
|
||||
<menu class="dropdown-menu right-edge" style="text-align: left" tabindex="-1" role="menu" aria-labelledby="button-add-prop-dropdown-id">
|
||||
<li role="presentation">
|
||||
|
@ -118,15 +118,15 @@
|
|||
</div>
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
<div class="b-view-content" data-bind="css: {'read-only': viewReadOnly}">
|
||||
<div class="b-view-content">
|
||||
<div class="b-contact-view-desc" data-bind="visible: !contact"
|
||||
data-i18n="CONTACTS/CONTACT_VIEW_DESC"></div>
|
||||
<div data-bind="visible: contact, i18nUpdate: contact">
|
||||
<div class="form-horizontal top-part">
|
||||
<div class="control-group" data-bind="visible: !viewReadOnly() || hasValidName()">
|
||||
<!-- ko with: contact -->
|
||||
<div class="form-horizontal top-part" data-bind="css: {'read-only': readOnly}">
|
||||
<div class="control-group" data-bind="visible: !readOnly() || hasValidName()">
|
||||
<label class="fontastic iconsize24">👤</label>
|
||||
<div>
|
||||
<!-- ko with: contact -->
|
||||
<div class="property-line">
|
||||
<span data-bind="text: givenName"></span>
|
||||
<input type="text"
|
||||
|
@ -145,10 +145,8 @@
|
|||
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="value: nickname" data-i18n="[placeholder]CONTACTS/PLACEHOLDER_ENTER_NICK_NAME">
|
||||
</div>
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- ko with: contact -->
|
||||
<div class="control-group" data-bind="email().length">
|
||||
<label class="fontastic iconsize24" data-i18n="[title]GLOBAL/EMAIL">@</label>
|
||||
<div>
|
||||
|
@ -191,8 +189,8 @@
|
|||
<a href="#" class="btn fontastic" data-bind="visible: !readOnly(), click: $root.addUrl">✚</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
<!-- /ko -->
|
||||
<!--
|
||||
<div class="e-read-only-sign fontastic iconsize24" data-i18n="[title]CONTACTS/LABEL_READ_ONLY">🔒</div>
|
||||
-->
|
||||
|
|
Loading…
Reference in a new issue