@operato/contact 10.29.12 → 10.29.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +221 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov.info +7699 -0
- package/dist/src/ox-contact-edit.d.ts +9 -2
- package/dist/src/ox-contact-edit.js +37 -8
- package/dist/src/ox-contact-edit.js.map +1 -1
- package/dist/src/ox-contact-view.js +6 -9
- package/dist/src/ox-contact-view.js.map +1 -1
- package/dist/src/ox-contact.d.ts +6 -1
- package/dist/src/ox-contact.js.map +1 -1
- package/dist/test/ox-contact-counterparty.test.d.ts +2 -0
- package/dist/test/ox-contact-counterparty.test.js +43 -0
- package/dist/test/ox-contact-counterparty.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/test/ox-contact-counterparty.test.ts +57 -0
- package/translations/en.json +1 -1
- package/translations/ja.json +1 -1
- package/translations/ko.json +1 -1
- package/translations/ms.json +1 -1
- package/translations/zh.json +1 -1
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import '@material/web/icon/icon.js';
|
|
2
2
|
import './ox-pfp.js';
|
|
3
3
|
import { LitElement, PropertyValues } from 'lit';
|
|
4
|
-
import { Contact, ContactItem } from './ox-contact.js';
|
|
4
|
+
import { Contact, ContactCounterparty, ContactItem } from './ox-contact.js';
|
|
5
5
|
import { OxPfp } from './ox-pfp.js';
|
|
6
6
|
export declare class OxContactEdit extends LitElement {
|
|
7
7
|
static styles: import("lit").CSSResult[];
|
|
8
8
|
contact: Contact;
|
|
9
|
+
/**
|
|
10
|
+
* Chooses the counterparty the contact belongs to. The host knows where counterparties live; this element only
|
|
11
|
+
* shows the one chosen. Resolves to the counterparty, to null to clear it, or to undefined when the choice was
|
|
12
|
+
* cancelled. Without it the counterparty is shown and can only be cleared.
|
|
13
|
+
*/
|
|
14
|
+
pickCounterparty?: (current?: ContactCounterparty | null) => Promise<ContactCounterparty | null | undefined>;
|
|
9
15
|
private stageContact;
|
|
10
16
|
name: HTMLTextAreaElement;
|
|
11
|
-
company: HTMLTextAreaElement;
|
|
12
17
|
note: HTMLTextAreaElement;
|
|
13
18
|
pfp: OxPfp;
|
|
14
19
|
fields: NodeListOf<HTMLDivElement>;
|
|
@@ -16,6 +21,8 @@ export declare class OxContactEdit extends LitElement {
|
|
|
16
21
|
updated(changes: PropertyValues<this>): void;
|
|
17
22
|
buildItems(): ContactItem[];
|
|
18
23
|
buildStageContact(): void;
|
|
24
|
+
chooseCounterparty(): Promise<void>;
|
|
25
|
+
setCounterparty(counterparty: ContactCounterparty | null): void;
|
|
19
26
|
onChangeItem(e: Event, item: ContactItem): void;
|
|
20
27
|
save(): void;
|
|
21
28
|
cancel(): void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
2
|
import '@material/web/icon/icon.js';
|
|
3
3
|
import './ox-pfp.js';
|
|
4
|
-
import { html, css, LitElement } from 'lit';
|
|
4
|
+
import { html, css, nothing, LitElement } from 'lit';
|
|
5
5
|
import { customElement, property, state, query, queryAll } from 'lit/decorators.js';
|
|
6
6
|
import { ScrollbarStyles } from '@operato/styles';
|
|
7
7
|
import { i18next } from '@operato/i18n';
|
|
@@ -12,7 +12,8 @@ let OxContactEdit = class OxContactEdit extends LitElement {
|
|
|
12
12
|
this.stageContact = JSON.parse(JSON.stringify(this.contact));
|
|
13
13
|
}
|
|
14
14
|
render() {
|
|
15
|
-
|
|
15
|
+
var _a;
|
|
16
|
+
const { profile, items = [], name, counterparty, note } = this.stageContact || {};
|
|
16
17
|
var sorted = {};
|
|
17
18
|
items.forEach(item => {
|
|
18
19
|
if (!sorted[item.type]) {
|
|
@@ -29,8 +30,12 @@ let OxContactEdit = class OxContactEdit extends LitElement {
|
|
|
29
30
|
<div name-content>
|
|
30
31
|
<span>${i18next.t('label.name')}</span>
|
|
31
32
|
<input type="text" id="name" .value=${name !== null && name !== void 0 ? name : ''} @change=${(e) => this.buildStageContact()} />
|
|
32
|
-
<span>${i18next.t('label.
|
|
33
|
-
<
|
|
33
|
+
<span>${i18next.t('label.counterparty')}</span>
|
|
34
|
+
<div counterparty>
|
|
35
|
+
<span>${(_a = counterparty === null || counterparty === void 0 ? void 0 : counterparty.name) !== null && _a !== void 0 ? _a : ''}</span>
|
|
36
|
+
${this.pickCounterparty ? html `<md-icon choose-counterparty @click=${() => this.chooseCounterparty()}>search</md-icon>` : nothing}
|
|
37
|
+
${counterparty ? html `<md-icon clear-counterparty @click=${() => this.setCounterparty(null)}>cancel</md-icon>` : nothing}
|
|
38
|
+
</div>
|
|
34
39
|
</div>
|
|
35
40
|
</div>
|
|
36
41
|
${['department', 'email', 'phone', 'address'].map(type => {
|
|
@@ -82,11 +87,19 @@ let OxContactEdit = class OxContactEdit extends LitElement {
|
|
|
82
87
|
...this.stageContact,
|
|
83
88
|
profile: this.pfp.profile,
|
|
84
89
|
name: this.name.value,
|
|
85
|
-
company: this.company.value,
|
|
86
90
|
note: this.note.value,
|
|
87
91
|
items: this.buildItems()
|
|
88
92
|
};
|
|
89
93
|
}
|
|
94
|
+
async chooseCounterparty() {
|
|
95
|
+
var _a;
|
|
96
|
+
const picked = await ((_a = this.pickCounterparty) === null || _a === void 0 ? void 0 : _a.call(this, this.stageContact.counterparty));
|
|
97
|
+
if (picked !== undefined)
|
|
98
|
+
this.setCounterparty(picked);
|
|
99
|
+
}
|
|
100
|
+
setCounterparty(counterparty) {
|
|
101
|
+
this.stageContact = { ...this.stageContact, counterparty };
|
|
102
|
+
}
|
|
90
103
|
onChangeItem(e, item) {
|
|
91
104
|
const target = e.currentTarget;
|
|
92
105
|
const labelElement = target.querySelector('[data-item="label"]');
|
|
@@ -200,6 +213,22 @@ OxContactEdit.styles = [
|
|
|
200
213
|
}
|
|
201
214
|
}
|
|
202
215
|
|
|
216
|
+
div[counterparty] {
|
|
217
|
+
display: flex;
|
|
218
|
+
align-items: center;
|
|
219
|
+
gap: var(--spacing-small);
|
|
220
|
+
min-height: 2em;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
div[counterparty] span {
|
|
224
|
+
flex: 1;
|
|
225
|
+
text-align: left;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
div[counterparty] md-icon {
|
|
229
|
+
cursor: pointer;
|
|
230
|
+
}
|
|
231
|
+
|
|
203
232
|
div[field] {
|
|
204
233
|
display: flex;
|
|
205
234
|
flex-direction: row;
|
|
@@ -227,15 +256,15 @@ OxContactEdit.styles = [
|
|
|
227
256
|
__decorate([
|
|
228
257
|
property({ type: Object })
|
|
229
258
|
], OxContactEdit.prototype, "contact", void 0);
|
|
259
|
+
__decorate([
|
|
260
|
+
property({ attribute: false })
|
|
261
|
+
], OxContactEdit.prototype, "pickCounterparty", void 0);
|
|
230
262
|
__decorate([
|
|
231
263
|
state()
|
|
232
264
|
], OxContactEdit.prototype, "stageContact", void 0);
|
|
233
265
|
__decorate([
|
|
234
266
|
query('#name')
|
|
235
267
|
], OxContactEdit.prototype, "name", void 0);
|
|
236
|
-
__decorate([
|
|
237
|
-
query('#company')
|
|
238
|
-
], OxContactEdit.prototype, "company", void 0);
|
|
239
268
|
__decorate([
|
|
240
269
|
query('#note')
|
|
241
270
|
], OxContactEdit.prototype, "note", void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-contact-edit.js","sourceRoot":"","sources":["../../src/ox-contact-edit.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport './ox-pfp.js'\n\nimport { html, css, LitElement, PropertyValues } from 'lit'\nimport { customElement, property, state, query, queryAll } from 'lit/decorators.js'\nimport { Contact, ContactField, ContactItem } from './ox-contact.js'\nimport { ScrollbarStyles } from '@operato/styles'\nimport { i18next } from '@operato/i18n'\nimport { OxPfp } from './ox-pfp.js'\n\n@customElement('ox-contact-edit')\nexport class OxContactEdit extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: block;\n padding: 25px;\n }\n\n input,\n select,\n textarea {\n padding: 8px;\n border-radius: 4px;\n border: 1px solid var(--md-sys-color-outline, #ccc);\n background-color: #fff;\n color: var(--md-sys-color-on-surface);\n font-size: 16px; /* for iPhone */\n box-shadow: 0 1px 1px 0px rgba(0, 0, 0, 0.1);\n transition:\n border-color 0.3s ease,\n box-shadow 0.3s ease;\n }\n\n input:focus,\n select:focus,\n textarea:focus {\n border-color: var(--md-sys-color-primary, #6200ea);\n box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);\n outline: none;\n }\n\n :host > div {\n padding: 10px 0;\n display: block;\n border-bottom: 1px solid blue;\n }\n\n :host > div > div {\n padding: 4px 0;\n box-sizing: border-box;\n\n display: flex;\n flex-direction: row;\n gap: 10px;\n align-items: center;\n }\n\n :host > div > div:hover {\n position: relative;\n }\n\n [data-item='label'] {\n width: 100px;\n text-align: right;\n }\n\n [data-item='value'] {\n flex: 1;\n }\n\n :host > div[name] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: bold;\n font-size: 1.4em;\n }\n\n :host ox-pfp {\n display: inline-block;\n width: 100px;\n height: 100px;\n }\n\n :host > div[name] > div[name-content] {\n flex: 1;\n\n display: grid;\n grid-template-columns: minmax(auto, 160px) 1fr;\n gap: var(--spacing-medium);\n align-items: center;\n\n span {\n text-align: right;\n }\n }\n\n div[field] {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 10px;\n }\n\n div[field] > span {\n width: 100px;\n text-align: right;\n }\n\n div[field] > input {\n flex: 1;\n }\n\n textarea {\n width: 100%;\n min-height: 100px;\n box-sizing: border-box;\n resize: none;\n }\n `\n ]\n\n @property({ type: Object }) contact: Contact = {}\n\n @state() private stageContact: Contact = JSON.parse(JSON.stringify(this.contact))\n\n @query('#name') name!: HTMLTextAreaElement\n @query('#company') company!: HTMLTextAreaElement\n @query('#note') note!: HTMLTextAreaElement\n @query('ox-pfp') pfp!: OxPfp\n @queryAll('[item-field]') fields!: NodeListOf<HTMLDivElement>\n\n render() {\n const { profile, items = [], name, company, note } = this.stageContact || {}\n var sorted: { [type: string]: ContactItem[] } = {}\n\n items.forEach(item => {\n if (!sorted[item.type as string]) {\n sorted[item.type] = [item]\n } else {\n sorted[item.type as string].push(item)\n }\n })\n\n return html`\n <div name>\n <ox-pfp .profile=${profile} .name=${name}></ox-pfp>\n\n <div name-content>\n <span>${i18next.t('label.name')}</span>\n <input type=\"text\" id=\"name\" .value=${name ?? ''} @change=${(e: Event) => this.buildStageContact()} />\n <span>${i18next.t('label.company')}</span>\n <input type=\"text\" id=\"company\" .value=${company ?? ''} @change=${(e: Event) => this.buildStageContact()} />\n </div>\n </div>\n ${['department', 'email', 'phone', 'address'].map(type => {\n var items = [...(sorted[type] || []), { type: type as ContactField, label: 'work', value: '' }]\n\n return html`\n <div data-type=${type}>\n ${type}\n ${items.map(\n item =>\n html`<div @change=${(e: Event) => this.onChangeItem(e, item)} .item=${item} item-field>\n ${item.value\n ? html`<md-icon\n @click=${() => {\n item.value = ''\n this.buildStageContact()\n }}\n >cancel</md-icon\n >`\n : html`<md-icon></md-icon>`}\n <select .value=${item.label} data-item=\"label\">\n ${['home', 'work', 'other', 'mobile'].map(\n option => html` <option value=${option} ?selected=${option === item.label}>${option}</option>`\n )}\n </select>\n <input type=\"text\" .value=${item.value} data-item=\"value\" />\n </div>`\n )}\n </div>\n `\n })}\n <div note>\n note\n <textarea id=\"note\" .value=${note || ''} @change=${() => this.buildStageContact()}></textarea>\n </div>\n `\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('contact')) {\n this.stageContact = JSON.parse(JSON.stringify(this.contact))\n }\n }\n\n buildItems() {\n const items: ContactItem[] = []\n\n this.fields.forEach(fieldElement => {\n const item = (fieldElement as any).item\n if (item.value) {\n items.push(item)\n }\n })\n\n return items\n }\n\n buildStageContact() {\n this.stageContact = {\n ...this.stageContact,\n profile: this.pfp.profile,\n name: this.name.value,\n company: this.company.value,\n note: this.note.value,\n items: this.buildItems()\n }\n }\n\n onChangeItem(e: Event, item: ContactItem) {\n const target = e.currentTarget as HTMLElement\n const labelElement = target.querySelector('[data-item=\"label\"]') as HTMLSelectElement\n const valueElement = target.querySelector('[data-item=\"value\"]') as HTMLInputElement\n\n item.label = labelElement.value\n item.value = valueElement.value\n\n if (e.target === valueElement || item.value) {\n this.buildStageContact()\n }\n }\n\n save() {\n this.buildStageContact()\n\n this.dispatchEvent(\n new CustomEvent('edit-done', {\n detail: this.stageContact\n })\n )\n }\n\n cancel() {\n this.dispatchEvent(\n new CustomEvent('edit-cancel', {\n detail: this.stageContact\n })\n )\n }\n\n reset() {\n this.buildStageContact()\n\n this.stageContact = JSON.parse(JSON.stringify(this.contact))\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ox-contact-edit.js","sourceRoot":"","sources":["../../src/ox-contact-edit.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport './ox-pfp.js'\n\nimport { html, css, nothing, LitElement, PropertyValues } from 'lit'\nimport { customElement, property, state, query, queryAll } from 'lit/decorators.js'\nimport { Contact, ContactCounterparty, ContactField, ContactItem } from './ox-contact.js'\nimport { ScrollbarStyles } from '@operato/styles'\nimport { i18next } from '@operato/i18n'\nimport { OxPfp } from './ox-pfp.js'\n\n@customElement('ox-contact-edit')\nexport class OxContactEdit extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: block;\n padding: 25px;\n }\n\n input,\n select,\n textarea {\n padding: 8px;\n border-radius: 4px;\n border: 1px solid var(--md-sys-color-outline, #ccc);\n background-color: #fff;\n color: var(--md-sys-color-on-surface);\n font-size: 16px; /* for iPhone */\n box-shadow: 0 1px 1px 0px rgba(0, 0, 0, 0.1);\n transition:\n border-color 0.3s ease,\n box-shadow 0.3s ease;\n }\n\n input:focus,\n select:focus,\n textarea:focus {\n border-color: var(--md-sys-color-primary, #6200ea);\n box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);\n outline: none;\n }\n\n :host > div {\n padding: 10px 0;\n display: block;\n border-bottom: 1px solid blue;\n }\n\n :host > div > div {\n padding: 4px 0;\n box-sizing: border-box;\n\n display: flex;\n flex-direction: row;\n gap: 10px;\n align-items: center;\n }\n\n :host > div > div:hover {\n position: relative;\n }\n\n [data-item='label'] {\n width: 100px;\n text-align: right;\n }\n\n [data-item='value'] {\n flex: 1;\n }\n\n :host > div[name] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: bold;\n font-size: 1.4em;\n }\n\n :host ox-pfp {\n display: inline-block;\n width: 100px;\n height: 100px;\n }\n\n :host > div[name] > div[name-content] {\n flex: 1;\n\n display: grid;\n grid-template-columns: minmax(auto, 160px) 1fr;\n gap: var(--spacing-medium);\n align-items: center;\n\n span {\n text-align: right;\n }\n }\n\n div[counterparty] {\n display: flex;\n align-items: center;\n gap: var(--spacing-small);\n min-height: 2em;\n }\n\n div[counterparty] span {\n flex: 1;\n text-align: left;\n }\n\n div[counterparty] md-icon {\n cursor: pointer;\n }\n\n div[field] {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 10px;\n }\n\n div[field] > span {\n width: 100px;\n text-align: right;\n }\n\n div[field] > input {\n flex: 1;\n }\n\n textarea {\n width: 100%;\n min-height: 100px;\n box-sizing: border-box;\n resize: none;\n }\n `\n ]\n\n @property({ type: Object }) contact: Contact = {}\n /**\n * Chooses the counterparty the contact belongs to. The host knows where counterparties live; this element only\n * shows the one chosen. Resolves to the counterparty, to null to clear it, or to undefined when the choice was\n * cancelled. Without it the counterparty is shown and can only be cleared.\n */\n @property({ attribute: false }) pickCounterparty?: (current?: ContactCounterparty | null) => Promise<ContactCounterparty | null | undefined>\n\n @state() private stageContact: Contact = JSON.parse(JSON.stringify(this.contact))\n\n @query('#name') name!: HTMLTextAreaElement\n @query('#note') note!: HTMLTextAreaElement\n @query('ox-pfp') pfp!: OxPfp\n @queryAll('[item-field]') fields!: NodeListOf<HTMLDivElement>\n\n render() {\n const { profile, items = [], name, counterparty, note } = this.stageContact || {}\n var sorted: { [type: string]: ContactItem[] } = {}\n\n items.forEach(item => {\n if (!sorted[item.type as string]) {\n sorted[item.type] = [item]\n } else {\n sorted[item.type as string].push(item)\n }\n })\n\n return html`\n <div name>\n <ox-pfp .profile=${profile} .name=${name}></ox-pfp>\n\n <div name-content>\n <span>${i18next.t('label.name')}</span>\n <input type=\"text\" id=\"name\" .value=${name ?? ''} @change=${(e: Event) => this.buildStageContact()} />\n <span>${i18next.t('label.counterparty')}</span>\n <div counterparty>\n <span>${counterparty?.name ?? ''}</span>\n ${this.pickCounterparty ? html`<md-icon choose-counterparty @click=${() => this.chooseCounterparty()}>search</md-icon>` : nothing}\n ${counterparty ? html`<md-icon clear-counterparty @click=${() => this.setCounterparty(null)}>cancel</md-icon>` : nothing}\n </div>\n </div>\n </div>\n ${['department', 'email', 'phone', 'address'].map(type => {\n var items = [...(sorted[type] || []), { type: type as ContactField, label: 'work', value: '' }]\n\n return html`\n <div data-type=${type}>\n ${type}\n ${items.map(\n item =>\n html`<div @change=${(e: Event) => this.onChangeItem(e, item)} .item=${item} item-field>\n ${item.value\n ? html`<md-icon\n @click=${() => {\n item.value = ''\n this.buildStageContact()\n }}\n >cancel</md-icon\n >`\n : html`<md-icon></md-icon>`}\n <select .value=${item.label} data-item=\"label\">\n ${['home', 'work', 'other', 'mobile'].map(\n option => html` <option value=${option} ?selected=${option === item.label}>${option}</option>`\n )}\n </select>\n <input type=\"text\" .value=${item.value} data-item=\"value\" />\n </div>`\n )}\n </div>\n `\n })}\n <div note>\n note\n <textarea id=\"note\" .value=${note || ''} @change=${() => this.buildStageContact()}></textarea>\n </div>\n `\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('contact')) {\n this.stageContact = JSON.parse(JSON.stringify(this.contact))\n }\n }\n\n buildItems() {\n const items: ContactItem[] = []\n\n this.fields.forEach(fieldElement => {\n const item = (fieldElement as any).item\n if (item.value) {\n items.push(item)\n }\n })\n\n return items\n }\n\n buildStageContact() {\n this.stageContact = {\n ...this.stageContact,\n profile: this.pfp.profile,\n name: this.name.value,\n note: this.note.value,\n items: this.buildItems()\n }\n }\n\n async chooseCounterparty() {\n const picked = await this.pickCounterparty?.(this.stageContact.counterparty)\n if (picked !== undefined) this.setCounterparty(picked)\n }\n\n setCounterparty(counterparty: ContactCounterparty | null) {\n this.stageContact = { ...this.stageContact, counterparty }\n }\n\n onChangeItem(e: Event, item: ContactItem) {\n const target = e.currentTarget as HTMLElement\n const labelElement = target.querySelector('[data-item=\"label\"]') as HTMLSelectElement\n const valueElement = target.querySelector('[data-item=\"value\"]') as HTMLInputElement\n\n item.label = labelElement.value\n item.value = valueElement.value\n\n if (e.target === valueElement || item.value) {\n this.buildStageContact()\n }\n }\n\n save() {\n this.buildStageContact()\n\n this.dispatchEvent(\n new CustomEvent('edit-done', {\n detail: this.stageContact\n })\n )\n }\n\n cancel() {\n this.dispatchEvent(\n new CustomEvent('edit-cancel', {\n detail: this.stageContact\n })\n )\n }\n\n reset() {\n this.buildStageContact()\n\n this.stageContact = JSON.parse(JSON.stringify(this.contact))\n }\n}\n"]}
|
|
@@ -8,7 +8,8 @@ let OxContactView = class OxContactView extends LitElement {
|
|
|
8
8
|
this.contact = {};
|
|
9
9
|
}
|
|
10
10
|
render() {
|
|
11
|
-
|
|
11
|
+
var _a;
|
|
12
|
+
const { profile, items = [], name, counterparty, note } = this.contact || {};
|
|
12
13
|
var sorted = {};
|
|
13
14
|
items.forEach(item => {
|
|
14
15
|
if (!sorted[item.type]) {
|
|
@@ -26,13 +27,13 @@ let OxContactView = class OxContactView extends LitElement {
|
|
|
26
27
|
<div>
|
|
27
28
|
<span data-item="value">${name}</span>
|
|
28
29
|
</div>
|
|
29
|
-
<div
|
|
30
|
-
<span data-item="value">${
|
|
30
|
+
<div counterparty>
|
|
31
|
+
<span data-item="value">${(_a = counterparty === null || counterparty === void 0 ? void 0 : counterparty.name) !== null && _a !== void 0 ? _a : ''}</span>
|
|
31
32
|
</div>
|
|
32
33
|
</div>
|
|
33
34
|
</div>
|
|
34
35
|
|
|
35
|
-
${['department', 'email', 'phone', 'address', '
|
|
36
|
+
${['department', 'email', 'phone', 'address', 'etc']
|
|
36
37
|
.map(type => sorted[type])
|
|
37
38
|
.filter(items => items && items.length > 0)
|
|
38
39
|
.map(items => html `<div data-type=${items[0].type}>
|
|
@@ -143,10 +144,6 @@ OxContactView.styles = css `
|
|
|
143
144
|
content: 'diversity_3';
|
|
144
145
|
}
|
|
145
146
|
|
|
146
|
-
div[data-type='company'] md-icon::before {
|
|
147
|
-
content: 'business';
|
|
148
|
-
}
|
|
149
|
-
|
|
150
147
|
div[data-type='etc'] md-icon::before {
|
|
151
148
|
content: 'feed';
|
|
152
149
|
}
|
|
@@ -172,7 +169,7 @@ OxContactView.styles = css `
|
|
|
172
169
|
font-size: 1.2em;
|
|
173
170
|
}
|
|
174
171
|
|
|
175
|
-
[name-content] [
|
|
172
|
+
[name-content] [counterparty] {
|
|
176
173
|
color: var(--md-sys-color-on-secondary-container, #666);
|
|
177
174
|
font-weight: normal;
|
|
178
175
|
font-size: 0.9em;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-contact-view.js","sourceRoot":"","sources":["../../src/ox-contact-view.ts"],"names":[],"mappings":";AAAA,OAAO,kBAAkB,CAAA;AAEzB,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAIpD,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,UAAU;IAAtC;;
|
|
1
|
+
{"version":3,"file":"ox-contact-view.js","sourceRoot":"","sources":["../../src/ox-contact-view.ts"],"names":[],"mappings":";AAAA,OAAO,kBAAkB,CAAA;AAEzB,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAIpD,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,UAAU;IAAtC;;QA6HuB,YAAO,GAAY,EAAE,CAAA;IAoDnD,CAAC;IAlDC,MAAM;;QACJ,MAAM,EAAE,OAAO,EAAE,KAAK,GAAG,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAA;QAC5E,IAAI,MAAM,GAAsC,EAAE,CAAA;QAElD,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACnB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAc,CAAC,EAAE,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YAC5B,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC,IAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACxC,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,OAAO,IAAI,CAAA;;gCAEiB,OAAO,UAAU,IAAI;;;;sCAIf,IAAI;;;sCAGJ,MAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,IAAI,mCAAI,EAAE;;;;;QAKtD,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC;aACjD,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;aACzB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;aAC1C,GAAG,CACF,KAAK,CAAC,EAAE,CACN,IAAI,CAAA,kBAAkB,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI;;gBAE/B,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI;gBACb,KAAK,CAAC,GAAG,CACT,IAAI,CAAC,EAAE,CACL,IAAI,CAAA;gDAC0B,IAAI,CAAC,KAAK;8CACZ,IAAI,CAAC,KAAK;yBAC/B,CACV;mBACI,CACV;;;;eAIM,IAAI,IAAI,EAAE;;KAEpB,CAAA;IACH,CAAC;;AA/KM,oBAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0HlB,AA1HY,CA0HZ;AAE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8CAAsB;AA7HtC,aAAa;IADzB,aAAa,CAAC,iBAAiB,CAAC;GACpB,aAAa,CAiLzB","sourcesContent":["import './ox-pfp-view.js'\n\nimport { html, css, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { Contact, ContactField, ContactItem } from './ox-contact.js'\n\n@customElement('ox-contact-view')\nexport class OxContactView extends LitElement {\n static styles = css`\n :host {\n display: block;\n --md-icon-size: 16px;\n\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface);\n }\n\n :host > div {\n padding: var(--spacing-medium, 8px);\n display: block;\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n font-size: 0.9em;\n text-transform: capitalize;\n }\n\n :host > div > div {\n padding: 4px 0;\n box-sizing: border-box;\n\n display: flex;\n flex-direction: row;\n gap: 10px;\n }\n\n :host > div > div:hover {\n position: relative;\n }\n\n :host > div > div:hover::before {\n content: '';\n display: block;\n position: absolute;\n text-align: left;\n line-height: 24px;\n top: 0;\n right: 0;\n width: 100%;\n height: 100%;\n opacity: 0.15;\n background-image: linear-gradient(var(--md-sys-color-primary, gray), var(--md-sys-color-primary, gray));\n }\n\n [data-item='label'] {\n width: 80px;\n text-align: right;\n color: var(--md-sys-color-primary, #017e7f);\n }\n\n [data-item='value'] {\n flex: 1;\n text-transform: none;\n }\n\n :host > div[name] {\n display: flex;\n align-items: center;\n gap: 15px;\n font-weight: bold;\n font-size: 1.4em;\n }\n\n :host ox-pfp-view {\n display: inline-block;\n\n --ox-pfp-size: 75px;\n }\n\n :host > div[name] > div[name-content] {\n flex: 1;\n\n display: flex;\n flex-direction: column;\n }\n\n div[data-type='email'] md-icon::before {\n content: 'mail_outline';\n }\n\n div[data-type='phone'] md-icon::before {\n content: 'phone';\n }\n\n div[data-type='address'] md-icon::before {\n content: 'place';\n }\n\n div[data-type='department'] md-icon::before {\n content: 'diversity_3';\n }\n\n div[data-type='etc'] md-icon::before {\n content: 'feed';\n }\n\n div[note] md-icon::before {\n content: 'subject';\n }\n\n :host > div > [name-content] {\n gap: 3px;\n }\n\n div md-icon {\n position: relative;\n top: 3px;\n margin-right: 3px;\n opacity: 0.5;\n color: var(--md-sys-color-on-primary-container, #333);\n }\n\n [name-content] div {\n color: var(--md-sys-color-on-primary-container, #333);\n font-size: 1.2em;\n }\n\n [name-content] [counterparty] {\n color: var(--md-sys-color-on-secondary-container, #666);\n font-weight: normal;\n font-size: 0.9em;\n }\n `\n\n @property({ type: Object }) contact: Contact = {}\n\n render() {\n const { profile, items = [], name, counterparty, note } = this.contact || {}\n var sorted: { [type: string]: ContactItem[] } = {}\n\n items.forEach(item => {\n if (!sorted[item.type as string]) {\n sorted[item.type] = [item]\n } else {\n sorted[item.type as string].push(item)\n }\n })\n\n return html`\n <div name>\n <ox-pfp-view .profile=${profile} .name=${name}></ox-pfp-view>\n\n <div name-content>\n <div>\n <span data-item=\"value\">${name}</span>\n </div>\n <div counterparty>\n <span data-item=\"value\">${counterparty?.name ?? ''}</span>\n </div>\n </div>\n </div>\n\n ${['department', 'email', 'phone', 'address', 'etc']\n .map(type => sorted[type])\n .filter(items => items && items.length > 0)\n .map(\n items =>\n html`<div data-type=${items[0].type}>\n <md-icon></md-icon>\n ${items[0].type}\n ${items.map(\n item =>\n html`<div>\n <label data-item=\"label\"> ${item.label}</label>\n <span data-item=\"value\">${item.value}</span>\n </div>`\n )}\n </div>`\n )}\n <div note>\n <md-icon></md-icon>\n note\n <div>${note || ''}</div>\n </div>\n `\n }\n}\n"]}
|
package/dist/src/ox-contact.d.ts
CHANGED
|
@@ -27,11 +27,16 @@ export type ContactItem = {
|
|
|
27
27
|
label: string;
|
|
28
28
|
value: string;
|
|
29
29
|
};
|
|
30
|
+
/** The counterparty a contact belongs to - a reference, shown by its name. */
|
|
31
|
+
export type ContactCounterparty = {
|
|
32
|
+
id: string;
|
|
33
|
+
name?: string;
|
|
34
|
+
};
|
|
30
35
|
export type Contact = {
|
|
31
36
|
id?: string;
|
|
32
37
|
profile?: Profile;
|
|
33
38
|
name?: string;
|
|
34
|
-
|
|
39
|
+
counterparty?: ContactCounterparty | null;
|
|
35
40
|
items?: ContactItem[];
|
|
36
41
|
note?: string;
|
|
37
42
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-contact.js","sourceRoot":"","sources":["../../src/ox-contact.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,sBAAsB,CAAA;AAC7B,OAAO,sBAAsB,CAAA;AAE7B,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAEzE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAKpD,MAAM,CAAN,IAAY,YAUX;AAVD,WAAY,YAAY;IACtB,sCAAsB,CAAA;IACtB,+BAAe,CAAA;IACf,mCAAmB,CAAA;IACnB,+BAAe,CAAA;IACf,qCAAqB,CAAA;IACrB,mCAAmB,CAAA;IACnB,mCAAmB,CAAA;IACnB,yCAAyB,CAAA;IACzB,qCAAqB,CAAA;AACvB,CAAC,EAVW,YAAY,KAAZ,YAAY,QAUvB;AAED,MAAM,CAAN,IAAY,YAKX;AALD,WAAY,YAAY;IACtB,6BAAa,CAAA;IACb,6BAAa,CAAA;IACb,+BAAe,CAAA;IACf,iCAAiB,CAAA;AACnB,CAAC,EALW,YAAY,KAAZ,YAAY,QAKvB;
|
|
1
|
+
{"version":3,"file":"ox-contact.js","sourceRoot":"","sources":["../../src/ox-contact.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,sBAAsB,CAAA;AAC7B,OAAO,sBAAsB,CAAA;AAE7B,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAEzE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAKpD,MAAM,CAAN,IAAY,YAUX;AAVD,WAAY,YAAY;IACtB,sCAAsB,CAAA;IACtB,+BAAe,CAAA;IACf,mCAAmB,CAAA;IACnB,+BAAe,CAAA;IACf,qCAAqB,CAAA;IACrB,mCAAmB,CAAA;IACnB,mCAAmB,CAAA;IACnB,yCAAyB,CAAA;IACzB,qCAAqB,CAAA;AACvB,CAAC,EAVW,YAAY,KAAZ,YAAY,QAUvB;AAED,MAAM,CAAN,IAAY,YAKX;AALD,WAAY,YAAY;IACtB,6BAAa,CAAA;IACb,6BAAa,CAAA;IACb,+BAAe,CAAA;IACf,iCAAiB,CAAA;AACnB,CAAC,EALW,YAAY,KAAZ,YAAY,QAKvB;AAyBM,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,UAAU;IAAlC;;QAmBuB,YAAO,GAAY,EAAE,CAAA;QAExC,aAAQ,GAAa,KAAK,CAAA;IA6CrC,CAAC;IAzCC,MAAM;QACJ,OAAO,IAAI,CAAA;;QAGP,IAAI,CAAC,QAAQ;YACX,CAAC,CAAC,IAAI,CAAA;yBACS,IAAI,CAAC,OAAO;6BACR,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;2BAC/B,CAAC,CAAc,EAAE,EAAE;gBAC9B,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,MAAM,CAAA;gBACvB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAA;YACvB,CAAC;gCACiB;YACtB,CAAC,CAAC,IAAI,CAAA,8BAA8B,IAAI,CAAC,OAAO,sBACpD;;;;UAKI,IAAI,CAAC,QAAQ;YACX,CAAC,CAAC,IAAI,CAAA;iCACe,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;kDACR,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC;;;iCAG1C,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;6CACd,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;;iCAEtC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;2CACd,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;;eAEvD;YACH,CAAC,CAAC,IAAI,CAAA;iCACe,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;2CAClB,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC;;eAG3D;;WAEG,CAAA;IACT,CAAC;;AAhEM,gBAAM,GAAG;IACd,kBAAkB;IAClB,GAAG,CAAA;;;;;;;;;;;;;KAaF;CACF,AAhBY,CAgBZ;AAE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;0CAAsB;AAExC;IAAR,KAAK,EAAE;2CAA2B;AAET;IAAzB,KAAK,CAAC,iBAAiB,CAAC;yCAAuB;AAvBrC,SAAS;IADrB,aAAa,CAAC,YAAY,CAAC;GACf,SAAS,CAkErB","sourcesContent":["import '@material/web/icon/icon.js'\nimport './ox-contact-edit.js'\nimport './ox-contact-view.js'\n\nimport { html, css, LitElement } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\n\nimport { i18next } from '@operato/i18n'\nimport { CommonHeaderStyles } from '@operato/styles'\n\nimport { OxContactEdit } from './ox-contact-edit.js'\nimport { Profile } from './ox-pfp-view.js'\n\nexport enum ContactField {\n JobTitle = 'job-title',\n Phone = 'phone',\n Address = 'address',\n Email = 'email',\n Birthday = 'birthday',\n Profile = 'profile',\n Picture = 'picture',\n Department = 'department',\n Homepage = 'homepage'\n}\n\nexport enum ContactLabel {\n home = 'home',\n work = 'work',\n other = 'other',\n mobile = 'mobile'\n}\n\nexport type ContactItem = {\n id?: string\n type: ContactField\n label: string\n value: string\n}\n\n/** The counterparty a contact belongs to - a reference, shown by its name. */\nexport type ContactCounterparty = {\n id: string\n name?: string\n}\n\nexport type Contact = {\n id?: string\n profile?: Profile\n name?: string\n counterparty?: ContactCounterparty | null\n items?: ContactItem[]\n note?: string\n}\n\n@customElement('ox-contact')\nexport class OxContact extends LitElement {\n static styles = [\n CommonHeaderStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface);\n }\n\n ox-contact-view,\n ox-contact-edit {\n padding: var(--padding-default);\n flex: 1;\n }\n `\n ]\n\n @property({ type: Object }) contact: Contact = {}\n\n @state() editMode?: boolean = false\n\n @query('ox-contact-edit') editor!: OxContactEdit\n\n render() {\n return html` \n <div container>\n ${\n this.editMode\n ? html`<ox-contact-edit\n .contact=${this.contact}\n @edit-cancel=${() => (this.editMode = false)}\n @edit-done=${(e: CustomEvent) => {\n this.contact = e.detail\n this.editMode = false\n }}\n ></ox-contact-edit>`\n : html` <ox-contact-view .contact=${this.contact}></ox-contact-view> `\n }\n </div>\n \n <div class=\"footer\">\n ${\n this.editMode\n ? html`\n <button @click=${() => this.editor.reset()}>\n <md-icon>restart_alt</md-icon>${i18next.t('button.reset')}\n </button>\n <div filler></div>\n <button @click=${() => this.editor.cancel()}>\n <md-icon>cancel</md-icon>${i18next.t('button.cancel')}\n </button>\n <button @click=${() => this.editor.save()}>\n <md-icon>done</md-icon>${i18next.t('button.confirm')}\n </button>\n `\n : html`\n <button @click=${() => (this.editMode = true)}>\n <md-icon>edit</md-icon>${i18next.t('button.edit')}\n </button>\n `\n }\n </div>\n </div>`\n }\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import { fixture, expect, oneEvent } from '@open-wc/testing';
|
|
3
|
+
import '../src/ox-contact-edit.js';
|
|
4
|
+
import '../src/ox-contact-view.js';
|
|
5
|
+
/* The counterparty a contact belongs to is a reference: the host picks it, the elements show its name and pass it on whole. */
|
|
6
|
+
const contact = { id: 'c1', name: 'Kim', counterparty: { id: 'acme', name: 'ACME' } };
|
|
7
|
+
async function saved(el) {
|
|
8
|
+
const done = oneEvent(el, 'edit-done');
|
|
9
|
+
el.save();
|
|
10
|
+
return (await done).detail;
|
|
11
|
+
}
|
|
12
|
+
describe('a contact’s counterparty', () => {
|
|
13
|
+
it('is shown by its name', async () => {
|
|
14
|
+
const el = await fixture(html `<ox-contact-view .contact=${contact}></ox-contact-view>`);
|
|
15
|
+
expect(el.shadowRoot.querySelector('[counterparty]').textContent.trim()).to.equal('ACME');
|
|
16
|
+
});
|
|
17
|
+
it('is the counterparty the host picks, saved as the reference it is', async () => {
|
|
18
|
+
const picked = { id: 'globex', name: 'Globex' };
|
|
19
|
+
let offered;
|
|
20
|
+
const el = await fixture(html `<ox-contact-edit .contact=${contact} .pickCounterparty=${async (current) => ((offered = current), picked)}></ox-contact-edit>`);
|
|
21
|
+
el.shadowRoot.querySelector('[choose-counterparty]').click();
|
|
22
|
+
await new Promise(resolve => setTimeout(resolve));
|
|
23
|
+
await el.updateComplete;
|
|
24
|
+
expect(offered).to.deep.equal({ id: 'acme', name: 'ACME' });
|
|
25
|
+
expect(el.shadowRoot.querySelector('[counterparty] span').textContent).to.equal('Globex');
|
|
26
|
+
expect((await saved(el)).counterparty).to.deep.equal(picked);
|
|
27
|
+
});
|
|
28
|
+
it('stays as it was when the choice is cancelled, and is cleared on asking', async () => {
|
|
29
|
+
const el = await fixture(html `<ox-contact-edit .contact=${contact} .pickCounterparty=${async () => undefined}></ox-contact-edit>`);
|
|
30
|
+
el.shadowRoot.querySelector('[choose-counterparty]').click();
|
|
31
|
+
await new Promise(resolve => setTimeout(resolve));
|
|
32
|
+
expect((await saved(el)).counterparty).to.deep.equal({ id: 'acme', name: 'ACME' });
|
|
33
|
+
el.shadowRoot.querySelector('[clear-counterparty]').click();
|
|
34
|
+
await el.updateComplete;
|
|
35
|
+
expect((await saved(el)).counterparty).to.equal(null);
|
|
36
|
+
});
|
|
37
|
+
it('cannot be chosen without a host picker, only cleared', async () => {
|
|
38
|
+
const el = await fixture(html `<ox-contact-edit .contact=${contact}></ox-contact-edit>`);
|
|
39
|
+
expect(el.shadowRoot.querySelector('[choose-counterparty]')).to.equal(null);
|
|
40
|
+
expect(el.shadowRoot.querySelector('[clear-counterparty]')).to.not.equal(null);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=ox-contact-counterparty.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ox-contact-counterparty.test.js","sourceRoot":"","sources":["../../test/ox-contact-counterparty.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit'\nimport { fixture, expect, oneEvent } from '@open-wc/testing'\n\nimport { OxContactEdit } from '../src/ox-contact-edit.js'\nimport { OxContactView } from '../src/ox-contact-view.js'\nimport { Contact, ContactCounterparty } from '../src/ox-contact.js'\nimport '../src/ox-contact-edit.js'\nimport '../src/ox-contact-view.js'\n\n/* The counterparty a contact belongs to is a reference: the host picks it, the elements show its name and pass it on whole. */\n\nconst contact: Contact = { id: 'c1', name: 'Kim', counterparty: { id: 'acme', name: 'ACME' } }\n\nasync function saved(el: OxContactEdit) {\n const done = oneEvent(el, 'edit-done')\n el.save()\n return ((await done) as CustomEvent<Contact>).detail\n}\n\ndescribe('a contact’s counterparty', () => {\n it('is shown by its name', async () => {\n const el = await fixture<OxContactView>(html`<ox-contact-view .contact=${contact}></ox-contact-view>`)\n expect(el.shadowRoot!.querySelector('[counterparty]')!.textContent!.trim()).to.equal('ACME')\n })\n\n it('is the counterparty the host picks, saved as the reference it is', async () => {\n const picked: ContactCounterparty = { id: 'globex', name: 'Globex' }\n let offered: ContactCounterparty | null | undefined\n const el = await fixture<OxContactEdit>(\n html`<ox-contact-edit .contact=${contact} .pickCounterparty=${async (current: ContactCounterparty | null | undefined) => ((offered = current), picked)}></ox-contact-edit>`\n )\n ;(el.shadowRoot!.querySelector('[choose-counterparty]') as HTMLElement).click()\n await new Promise(resolve => setTimeout(resolve))\n await el.updateComplete\n\n expect(offered).to.deep.equal({ id: 'acme', name: 'ACME' })\n expect(el.shadowRoot!.querySelector('[counterparty] span')!.textContent).to.equal('Globex')\n expect((await saved(el)).counterparty).to.deep.equal(picked)\n })\n\n it('stays as it was when the choice is cancelled, and is cleared on asking', async () => {\n const el = await fixture<OxContactEdit>(html`<ox-contact-edit .contact=${contact} .pickCounterparty=${async () => undefined}></ox-contact-edit>`)\n ;(el.shadowRoot!.querySelector('[choose-counterparty]') as HTMLElement).click()\n await new Promise(resolve => setTimeout(resolve))\n expect((await saved(el)).counterparty).to.deep.equal({ id: 'acme', name: 'ACME' })\n\n ;(el.shadowRoot!.querySelector('[clear-counterparty]') as HTMLElement).click()\n await el.updateComplete\n expect((await saved(el)).counterparty).to.equal(null)\n })\n\n it('cannot be chosen without a host picker, only cleared', async () => {\n const el = await fixture<OxContactEdit>(html`<ox-contact-edit .contact=${contact}></ox-contact-edit>`)\n expect(el.shadowRoot!.querySelector('[choose-counterparty]')).to.equal(null)\n expect(el.shadowRoot!.querySelector('[clear-counterparty]')).to.not.equal(null)\n })\n})\n"]}
|