@things-factory/contact 7.0.55 → 7.0.56

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.
@@ -2,21 +2,21 @@ import '@material/web/icon/icon.js'
2
2
  import '@operato/contact/ox-contact-view.js'
3
3
  import '@operato/contact/ox-contact-edit.js'
4
4
 
5
- import { html, css, LitElement } from 'lit'
5
+ import { html, css, LitElement, PropertyValues } from 'lit'
6
6
  import { customElement, property, query, state } from 'lit/decorators.js'
7
7
  import gql from 'graphql-tag'
8
8
 
9
9
  import { client } from '@operato/graphql'
10
10
  import { Contact } from '@operato/contact/ox-contact.js'
11
11
  import { i18next } from '@operato/i18n'
12
- import { ButtonContainerStyles, ScrollbarStyles } from '@operato/styles'
12
+ import { CommonHeaderStyles, ScrollbarStyles } from '@operato/styles'
13
13
  import { OxContactEdit } from '@operato/contact/ox-contact-edit.js'
14
14
 
15
15
  @customElement('contact-popup')
16
16
  export class ContactPopup extends LitElement {
17
17
  static styles = [
18
18
  ScrollbarStyles,
19
- ButtonContainerStyles,
19
+ CommonHeaderStyles,
20
20
  css`
21
21
  :host {
22
22
  display: flex;
@@ -33,9 +33,12 @@ export class ContactPopup extends LitElement {
33
33
  `
34
34
  ]
35
35
 
36
- @property({ type: Object }) contact: Contact = {}
36
+ @property({ type: String }) contactId?: string
37
37
  @property({ type: Boolean, attribute: 'edit-mode' }) editMode?: boolean = false
38
38
  @property({ type: Boolean }) detachable?: boolean = false
39
+ @property({ type: Object }) closeCallback?: (contact?: Contact | null) => void
40
+
41
+ @state() contact: Contact = {}
39
42
 
40
43
  @query('ox-contact-edit') editor!: OxContactEdit
41
44
 
@@ -54,7 +57,7 @@ export class ContactPopup extends LitElement {
54
57
  : html` <ox-contact-view .contact=${this.contact}></ox-contact-view>`}
55
58
  </div>
56
59
 
57
- <div class="button-container">
60
+ <div class="footer">
58
61
  ${!this.editMode
59
62
  ? html`
60
63
  ${this.detachable
@@ -71,22 +74,71 @@ export class ContactPopup extends LitElement {
71
74
  </button>
72
75
  `
73
76
  : html``}
77
+ <div filler></div>
74
78
  <button @click=${() => (this.editMode = true)}><md-icon>edit</md-icon>${i18next.t('button.edit')}</button>
75
- <button @click=${() => history.back()}><md-icon>close</md-icon>${i18next.t('button.close')}</button>
79
+ <button @click=${this.onClose} ok><md-icon>close</md-icon>${i18next.t('button.close')}</button>
76
80
  `
77
81
  : html`
78
- <button @click=${() => this.editor.save()}><md-icon>save</md-icon>${i18next.t('button.save')}</button>
79
- <button @click=${() => this.editor.cancel()}>
80
- <md-icon>cancel</md-icon>${i18next.t('button.cancel')}
81
- </button>
82
82
  <button @click=${() => this.editor.reset()}>
83
83
  <md-icon>restart_alt</md-icon>${i18next.t('button.reset')}
84
84
  </button>
85
+ <div filler></div>
86
+ <button @click=${() => this.editor.cancel()}>
87
+ <md-icon>cancel</md-icon>${i18next.t('button.cancel')}
88
+ </button>
89
+ <button @click=${() => this.editor.save()} ok><md-icon>save</md-icon>${i18next.t('button.save')}</button>
85
90
  `}
86
91
  </div>
87
92
  `
88
93
  }
89
94
 
95
+ onClose() {
96
+ this.closeCallback && this.closeCallback(this.contact?.id ? this.contact : null)
97
+
98
+ history.back()
99
+ }
100
+
101
+ updated(changes: PropertyValues<this>) {
102
+ if (changes.has('contactId') && this.contactId) {
103
+ this.fetchContact()
104
+ }
105
+ }
106
+
107
+ async fetchContact() {
108
+ const response = await client.query({
109
+ query: gql`
110
+ query ($id: String!) {
111
+ contact(id: $id) {
112
+ id
113
+ name
114
+ company
115
+ department
116
+ email
117
+ phone
118
+ address
119
+ note
120
+ items {
121
+ type
122
+ label
123
+ value
124
+ }
125
+ profile {
126
+ left
127
+ top
128
+ zoom
129
+ picture
130
+ }
131
+ }
132
+ }
133
+ `,
134
+ variables: {
135
+ id: this.contactId
136
+ }
137
+ })
138
+
139
+ this.contact = response.data.contact
140
+ }
141
+
90
142
  async updateContact(contact: Contact) {
91
143
  if (contact.id) {
92
144
  var { id, ...patch } = contact
@@ -1,23 +1,25 @@
1
1
  import '@material/web/icon/icon.js'
2
2
  import '@operato/data-grist'
3
+ import './contact-popup'
3
4
 
4
5
  import gql from 'graphql-tag'
5
6
  import { css, html, LitElement } from 'lit'
6
7
  import { customElement, property, query } from 'lit/decorators.js'
7
8
 
8
- import { DataGrist, FetchHandler, GristData, GristEventHandler, GristRecord, ZERO_DATA } from '@operato/data-grist'
9
- import { client, gqlContext } from '@operato/graphql'
9
+ import { DataGrist, FetchHandler, GristData, GristRecord, ZERO_DATA } from '@operato/data-grist'
10
+ import { client } from '@operato/graphql'
10
11
  import { i18next } from '@operato/i18n'
11
12
  import { closePopup } from '@operato/popup'
13
+ import { openPopup } from '@operato/layout'
12
14
  import { isMobileDevice } from '@operato/utils'
13
- import { ButtonContainerStyles, CommonGristStyles, ScrollbarStyles } from '@operato/styles'
15
+ import { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles } from '@operato/styles'
14
16
 
15
17
  @customElement('contact-selector')
16
18
  export class ContactSelector extends LitElement {
17
19
  static styles = [
18
20
  ScrollbarStyles,
19
- ButtonContainerStyles,
20
21
  CommonGristStyles,
22
+ CommonHeaderStyles,
21
23
  css`
22
24
  :host {
23
25
  display: flex;
@@ -33,14 +35,8 @@ export class ContactSelector extends LitElement {
33
35
  flex: 1;
34
36
  }
35
37
 
36
- #filters {
37
- display: flex;
38
- flex-direction: row;
39
- justify-content: space-between;
40
- }
41
-
42
- #filters > * {
43
- padding: var(--spacing-medium) var(--spacing-large);
38
+ .header {
39
+ grid-template-areas: 'filters actions';
44
40
  }
45
41
  `
46
42
  ]
@@ -64,18 +60,28 @@ export class ContactSelector extends LitElement {
64
60
  .fetchHandler=${this.fetchHandler.bind(this)}
65
61
  .selectedRecords=${this.selectedRecords}
66
62
  >
67
- <div id="filters" slot="headroom">
68
- <ox-filters-form autofocus></ox-filters-form>
63
+ <div class="header" slot="headroom">
64
+ <div class="filters">
65
+ <ox-filters-form autofocus without-search></ox-filters-form>
66
+ </div>
67
+
68
+ <div class="actions">
69
+ <button @click=${this.onCreate.bind(this)} class="iconbtn">
70
+ <md-icon>add</md-icon>${i18next.t('button.add')}
71
+ </button>
72
+ </div>
69
73
  </div>
70
74
  </ox-grist>
71
75
 
72
- <div class="button-container" style="margin-left:unset;">
76
+ <div class="footer">
73
77
  <button @click=${this.onEmpty.bind(this)}>
74
78
  <md-icon>check_box_outline_blank</md-icon>${i18next.t('button.empty')}
75
79
  </button>
80
+
76
81
  <div filler></div>
82
+
77
83
  <button @click=${this.onCancel.bind(this)}><md-icon>cancel</md-icon>${i18next.t('button.cancel')}</button>
78
- <button @click=${this.onConfirm.bind(this)}><md-icon>done</md-icon>${i18next.t('button.confirm')}</button>
84
+ <button @click=${this.onConfirm.bind(this)} ok><md-icon>done</md-icon>${i18next.t('button.confirm')}</button>
79
85
  </div>
80
86
  `
81
87
  }
@@ -94,6 +100,34 @@ export class ContactSelector extends LitElement {
94
100
  closePopup(this)
95
101
  }
96
102
 
103
+ onCreate() {
104
+ var createdContact
105
+ const popup = openPopup(
106
+ html`
107
+ <contact-popup
108
+ edit-mode
109
+ .closeCallback=${contact => {
110
+ createdContact = contact
111
+ }}
112
+ ></contact-popup>
113
+ `,
114
+ {
115
+ backdrop: true,
116
+ size: 'large',
117
+ title: i18next.t('title.contact')
118
+ }
119
+ )
120
+
121
+ popup.onclosed = () => {
122
+ if (createdContact) {
123
+ this.confirmCallback && this.confirmCallback(createdContact)
124
+ closePopup(this)
125
+ } else {
126
+ this.grist.fetch()
127
+ }
128
+ }
129
+ }
130
+
97
131
  fetchHandler: FetchHandler = async ({ page = 1, limit = 100, sortings = [], filters = [] }) => {
98
132
  const response = await client.query({
99
133
  query: gql`
@@ -128,8 +162,7 @@ export class ContactSelector extends LitElement {
128
162
  filters,
129
163
  pagination: { page, limit },
130
164
  sortings
131
- },
132
- context: gqlContext()
165
+ }
133
166
  })
134
167
 
135
168
  if (!response.errors) {
@@ -8,11 +8,11 @@ import { property } from 'lit/decorators.js'
8
8
  import { client } from '@operato/graphql'
9
9
  import { i18next } from '@operato/i18n'
10
10
  import { isMobileDevice } from '@operato/utils'
11
- import { ButtonContainerStyles } from '@operato/styles'
11
+ import { CommonHeaderStyles } from '@operato/styles'
12
12
 
13
13
  export class ContactImporter extends LitElement {
14
14
  static styles = [
15
- ButtonContainerStyles,
15
+ CommonHeaderStyles,
16
16
  css`
17
17
  :host {
18
18
  display: flex;
@@ -63,8 +63,9 @@ export class ContactImporter extends LitElement {
63
63
  }}
64
64
  ></ox-grist>
65
65
 
66
- <div class="button-container">
67
- <button @click="${this.save.bind(this)}"><md-icon>save</md-icon>${i18next.t('button.save')}</button>
66
+ <div class="footer">
67
+ <div filler></div>
68
+ <button @click=${this.save.bind(this)} done><md-icon>save</md-icon>${i18next.t('button.save')}</button>
68
69
  </div>
69
70
  `
70
71
  }
@@ -414,40 +414,7 @@ export class ContactListPage extends connect(store)(localize(i18next)(ScopedElem
414
414
  }
415
415
 
416
416
  async openContactPopup(record: any) {
417
- const response = await client.query({
418
- query: gql`
419
- query ($id: String!) {
420
- contact(id: $id) {
421
- id
422
- name
423
- company
424
- email
425
- phone
426
- address
427
- department
428
- note
429
- items {
430
- type
431
- label
432
- value
433
- }
434
- profile {
435
- left
436
- top
437
- zoom
438
- picture
439
- }
440
- }
441
- }
442
- `,
443
- variables: {
444
- id: record.id
445
- }
446
- })
447
-
448
- const { contact } = response.data
449
-
450
- const popup = openPopup(html` <contact-popup .contact=${contact}></contact-popup> `, {
417
+ const popup = openPopup(html` <contact-popup .contactId=${record.id}></contact-popup> `, {
451
418
  backdrop: true,
452
419
  size: 'large',
453
420
  title: i18next.t('title.contact')
@@ -1,15 +1,20 @@
1
1
  import '@material/web/icon/icon.js';
2
2
  import '@operato/contact/ox-contact-view.js';
3
3
  import '@operato/contact/ox-contact-edit.js';
4
- import { LitElement } from 'lit';
4
+ import { LitElement, PropertyValues } from 'lit';
5
5
  import { Contact } from '@operato/contact/ox-contact.js';
6
6
  import { OxContactEdit } from '@operato/contact/ox-contact-edit.js';
7
7
  export declare class ContactPopup extends LitElement {
8
8
  static styles: import("lit").CSSResult[];
9
- contact: Contact;
9
+ contactId?: string;
10
10
  editMode?: boolean;
11
11
  detachable?: boolean;
12
+ closeCallback?: (contact?: Contact | null) => void;
13
+ contact: Contact;
12
14
  editor: OxContactEdit;
13
- render(): import("lit").TemplateResult<1>;
15
+ render(): import("lit-html").TemplateResult<1>;
16
+ onClose(): void;
17
+ updated(changes: PropertyValues<this>): void;
18
+ fetchContact(): Promise<void>;
14
19
  updateContact(contact: Contact): Promise<void>;
15
20
  }
@@ -3,18 +3,18 @@ import '@material/web/icon/icon.js';
3
3
  import '@operato/contact/ox-contact-view.js';
4
4
  import '@operato/contact/ox-contact-edit.js';
5
5
  import { html, css, LitElement } from 'lit';
6
- import { customElement, property, query } from 'lit/decorators.js';
6
+ import { customElement, property, query, state } from 'lit/decorators.js';
7
7
  import gql from 'graphql-tag';
8
8
  import { client } from '@operato/graphql';
9
9
  import { i18next } from '@operato/i18n';
10
- import { ButtonContainerStyles, ScrollbarStyles } from '@operato/styles';
10
+ import { CommonHeaderStyles, ScrollbarStyles } from '@operato/styles';
11
11
  import { OxContactEdit } from '@operato/contact/ox-contact-edit.js';
12
12
  let ContactPopup = class ContactPopup extends LitElement {
13
13
  constructor() {
14
14
  super(...arguments);
15
- this.contact = {};
16
15
  this.editMode = false;
17
16
  this.detachable = false;
17
+ this.contact = {};
18
18
  }
19
19
  render() {
20
20
  return html `
@@ -31,7 +31,7 @@ let ContactPopup = class ContactPopup extends LitElement {
31
31
  : html ` <ox-contact-view .contact=${this.contact}></ox-contact-view>`}
32
32
  </div>
33
33
 
34
- <div class="button-container">
34
+ <div class="footer">
35
35
  ${!this.editMode
36
36
  ? html `
37
37
  ${this.detachable
@@ -48,21 +48,66 @@ let ContactPopup = class ContactPopup extends LitElement {
48
48
  </button>
49
49
  `
50
50
  : html ``}
51
+ <div filler></div>
51
52
  <button @click=${() => (this.editMode = true)}><md-icon>edit</md-icon>${i18next.t('button.edit')}</button>
52
- <button @click=${() => history.back()}><md-icon>close</md-icon>${i18next.t('button.close')}</button>
53
+ <button @click=${this.onClose} ok><md-icon>close</md-icon>${i18next.t('button.close')}</button>
53
54
  `
54
55
  : html `
55
- <button @click=${() => this.editor.save()}><md-icon>save</md-icon>${i18next.t('button.save')}</button>
56
- <button @click=${() => this.editor.cancel()}>
57
- <md-icon>cancel</md-icon>${i18next.t('button.cancel')}
58
- </button>
59
56
  <button @click=${() => this.editor.reset()}>
60
57
  <md-icon>restart_alt</md-icon>${i18next.t('button.reset')}
61
58
  </button>
59
+ <div filler></div>
60
+ <button @click=${() => this.editor.cancel()}>
61
+ <md-icon>cancel</md-icon>${i18next.t('button.cancel')}
62
+ </button>
63
+ <button @click=${() => this.editor.save()} ok><md-icon>save</md-icon>${i18next.t('button.save')}</button>
62
64
  `}
63
65
  </div>
64
66
  `;
65
67
  }
68
+ onClose() {
69
+ var _a;
70
+ this.closeCallback && this.closeCallback(((_a = this.contact) === null || _a === void 0 ? void 0 : _a.id) ? this.contact : null);
71
+ history.back();
72
+ }
73
+ updated(changes) {
74
+ if (changes.has('contactId') && this.contactId) {
75
+ this.fetchContact();
76
+ }
77
+ }
78
+ async fetchContact() {
79
+ const response = await client.query({
80
+ query: gql `
81
+ query ($id: String!) {
82
+ contact(id: $id) {
83
+ id
84
+ name
85
+ company
86
+ department
87
+ email
88
+ phone
89
+ address
90
+ note
91
+ items {
92
+ type
93
+ label
94
+ value
95
+ }
96
+ profile {
97
+ left
98
+ top
99
+ zoom
100
+ picture
101
+ }
102
+ }
103
+ }
104
+ `,
105
+ variables: {
106
+ id: this.contactId
107
+ }
108
+ });
109
+ this.contact = response.data.contact;
110
+ }
66
111
  async updateContact(contact) {
67
112
  if (contact.id) {
68
113
  var { id } = contact, patch = __rest(contact, ["id"]);
@@ -138,7 +183,7 @@ let ContactPopup = class ContactPopup extends LitElement {
138
183
  };
139
184
  ContactPopup.styles = [
140
185
  ScrollbarStyles,
141
- ButtonContainerStyles,
186
+ CommonHeaderStyles,
142
187
  css `
143
188
  :host {
144
189
  display: flex;
@@ -155,9 +200,9 @@ ContactPopup.styles = [
155
200
  `
156
201
  ];
157
202
  __decorate([
158
- property({ type: Object }),
159
- __metadata("design:type", Object)
160
- ], ContactPopup.prototype, "contact", void 0);
203
+ property({ type: String }),
204
+ __metadata("design:type", String)
205
+ ], ContactPopup.prototype, "contactId", void 0);
161
206
  __decorate([
162
207
  property({ type: Boolean, attribute: 'edit-mode' }),
163
208
  __metadata("design:type", Boolean)
@@ -166,6 +211,14 @@ __decorate([
166
211
  property({ type: Boolean }),
167
212
  __metadata("design:type", Boolean)
168
213
  ], ContactPopup.prototype, "detachable", void 0);
214
+ __decorate([
215
+ property({ type: Object }),
216
+ __metadata("design:type", Function)
217
+ ], ContactPopup.prototype, "closeCallback", void 0);
218
+ __decorate([
219
+ state(),
220
+ __metadata("design:type", Object)
221
+ ], ContactPopup.prototype, "contact", void 0);
169
222
  __decorate([
170
223
  query('ox-contact-edit'),
171
224
  __metadata("design:type", OxContactEdit)
@@ -1 +1 @@
1
- {"version":3,"file":"contact-popup.js","sourceRoot":"","sources":["../../client/components/contact-popup.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/contact/ox-contact-view.js'\nimport '@operato/contact/ox-contact-edit.js'\n\nimport { html, css, LitElement } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport gql from 'graphql-tag'\n\nimport { client } from '@operato/graphql'\nimport { Contact } from '@operato/contact/ox-contact.js'\nimport { i18next } from '@operato/i18n'\nimport { ButtonContainerStyles, ScrollbarStyles } from '@operato/styles'\nimport { OxContactEdit } from '@operato/contact/ox-contact-edit.js'\n\n@customElement('contact-popup')\nexport class ContactPopup extends LitElement {\n static styles = [\n ScrollbarStyles,\n ButtonContainerStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n color: var(--popup-content-color);\n background-color: var(--popup-content-background-color);\n }\n\n [content] {\n flex: 1;\n padding: var(--spacing-medium);\n overflow: auto;\n }\n `\n ]\n\n @property({ type: Object }) contact: Contact = {}\n @property({ type: Boolean, attribute: 'edit-mode' }) editMode?: boolean = false\n @property({ type: Boolean }) detachable?: boolean = false\n\n @query('ox-contact-edit') editor!: OxContactEdit\n\n render() {\n return html`\n <div content>\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.updateContact(e.detail)\n this.editMode = false\n }}\n ></ox-contact-edit>`\n : html` <ox-contact-view .contact=${this.contact}></ox-contact-view>`}\n </div>\n\n <div class=\"button-container\">\n ${!this.editMode\n ? html`\n ${this.detachable\n ? html`\n <button\n danger\n @click=${() => {\n this.dispatchEvent(new CustomEvent('detach'))\n history.back()\n }}\n >\n <md-icon>link_off</md-icon>\n ${i18next.t('button.detach')}\n </button>\n `\n : html``}\n <button @click=${() => (this.editMode = true)}><md-icon>edit</md-icon>${i18next.t('button.edit')}</button>\n <button @click=${() => history.back()}><md-icon>close</md-icon>${i18next.t('button.close')}</button>\n `\n : html`\n <button @click=${() => this.editor.save()}><md-icon>save</md-icon>${i18next.t('button.save')}</button>\n <button @click=${() => this.editor.cancel()}>\n <md-icon>cancel</md-icon>${i18next.t('button.cancel')}\n </button>\n <button @click=${() => this.editor.reset()}>\n <md-icon>restart_alt</md-icon>${i18next.t('button.reset')}\n </button>\n `}\n </div>\n `\n }\n\n async updateContact(contact: Contact) {\n if (contact.id) {\n var { id, ...patch } = contact\n\n var response = await client.mutate({\n mutation: gql`\n mutation ($id: String!, $patch: ContactPatch!) {\n contact: updateContact(id: $id, patch: $patch) {\n id\n name\n company\n email\n note\n items {\n label\n type\n value\n }\n profile {\n left\n top\n zoom\n picture\n }\n }\n }\n `,\n variables: {\n id,\n patch\n },\n context: {\n hasUpload: true\n }\n })\n } else {\n var response = await client.mutate({\n mutation: gql`\n mutation ($contact: NewContact!) {\n contact: createContact(contact: $contact) {\n id\n name\n company\n email\n note\n items {\n label\n type\n value\n }\n profile {\n left\n top\n zoom\n picture\n }\n }\n }\n `,\n variables: {\n contact\n },\n context: {\n hasUpload: true\n }\n })\n }\n\n this.contact = response.data.contact\n\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: this.contact\n })\n )\n }\n}\n"]}
1
+ {"version":3,"file":"contact-popup.js","sourceRoot":"","sources":["../../client/components/contact-popup.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/contact/ox-contact-view.js'\nimport '@operato/contact/ox-contact-edit.js'\n\nimport { html, css, LitElement, PropertyValues } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport gql from 'graphql-tag'\n\nimport { client } from '@operato/graphql'\nimport { Contact } from '@operato/contact/ox-contact.js'\nimport { i18next } from '@operato/i18n'\nimport { CommonHeaderStyles, ScrollbarStyles } from '@operato/styles'\nimport { OxContactEdit } from '@operato/contact/ox-contact-edit.js'\n\n@customElement('contact-popup')\nexport class ContactPopup extends LitElement {\n static styles = [\n ScrollbarStyles,\n CommonHeaderStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n color: var(--popup-content-color);\n background-color: var(--popup-content-background-color);\n }\n\n [content] {\n flex: 1;\n padding: var(--spacing-medium);\n overflow: auto;\n }\n `\n ]\n\n @property({ type: String }) contactId?: string\n @property({ type: Boolean, attribute: 'edit-mode' }) editMode?: boolean = false\n @property({ type: Boolean }) detachable?: boolean = false\n @property({ type: Object }) closeCallback?: (contact?: Contact | null) => void\n\n @state() contact: Contact = {}\n\n @query('ox-contact-edit') editor!: OxContactEdit\n\n render() {\n return html`\n <div content>\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.updateContact(e.detail)\n this.editMode = false\n }}\n ></ox-contact-edit>`\n : html` <ox-contact-view .contact=${this.contact}></ox-contact-view>`}\n </div>\n\n <div class=\"footer\">\n ${!this.editMode\n ? html`\n ${this.detachable\n ? html`\n <button\n danger\n @click=${() => {\n this.dispatchEvent(new CustomEvent('detach'))\n history.back()\n }}\n >\n <md-icon>link_off</md-icon>\n ${i18next.t('button.detach')}\n </button>\n `\n : html``}\n <div filler></div>\n <button @click=${() => (this.editMode = true)}><md-icon>edit</md-icon>${i18next.t('button.edit')}</button>\n <button @click=${this.onClose} ok><md-icon>close</md-icon>${i18next.t('button.close')}</button>\n `\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()} ok><md-icon>save</md-icon>${i18next.t('button.save')}</button>\n `}\n </div>\n `\n }\n\n onClose() {\n this.closeCallback && this.closeCallback(this.contact?.id ? this.contact : null)\n\n history.back()\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('contactId') && this.contactId) {\n this.fetchContact()\n }\n }\n\n async fetchContact() {\n const response = await client.query({\n query: gql`\n query ($id: String!) {\n contact(id: $id) {\n id\n name\n company\n department\n email\n phone\n address\n note\n items {\n type\n label\n value\n }\n profile {\n left\n top\n zoom\n picture\n }\n }\n }\n `,\n variables: {\n id: this.contactId\n }\n })\n\n this.contact = response.data.contact\n }\n\n async updateContact(contact: Contact) {\n if (contact.id) {\n var { id, ...patch } = contact\n\n var response = await client.mutate({\n mutation: gql`\n mutation ($id: String!, $patch: ContactPatch!) {\n contact: updateContact(id: $id, patch: $patch) {\n id\n name\n company\n email\n note\n items {\n label\n type\n value\n }\n profile {\n left\n top\n zoom\n picture\n }\n }\n }\n `,\n variables: {\n id,\n patch\n },\n context: {\n hasUpload: true\n }\n })\n } else {\n var response = await client.mutate({\n mutation: gql`\n mutation ($contact: NewContact!) {\n contact: createContact(contact: $contact) {\n id\n name\n company\n email\n note\n items {\n label\n type\n value\n }\n profile {\n left\n top\n zoom\n picture\n }\n }\n }\n `,\n variables: {\n contact\n },\n context: {\n hasUpload: true\n }\n })\n }\n\n this.contact = response.data.contact\n\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: this.contact\n })\n )\n }\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import '@material/web/icon/icon.js';
2
2
  import '@operato/data-grist';
3
+ import './contact-popup';
3
4
  import { LitElement } from 'lit';
4
5
  import { DataGrist, FetchHandler, GristData, GristRecord } from '@operato/data-grist';
5
6
  export declare class ContactSelector extends LitElement {
@@ -11,10 +12,11 @@ export declare class ContactSelector extends LitElement {
11
12
  selectedRecords: GristRecord[];
12
13
  list: any;
13
14
  grist: DataGrist;
14
- render(): import("lit").TemplateResult<1>;
15
+ render(): import("lit-html").TemplateResult<1>;
15
16
  onEmpty(): void;
16
17
  onCancel(): void;
17
18
  onConfirm(): void;
19
+ onCreate(): void;
18
20
  fetchHandler: FetchHandler;
19
21
  firstUpdated(): Promise<void>;
20
22
  get selected(): GristRecord | undefined;
@@ -1,15 +1,17 @@
1
1
  import { __decorate, __metadata } from "tslib";
2
2
  import '@material/web/icon/icon.js';
3
3
  import '@operato/data-grist';
4
+ import './contact-popup';
4
5
  import gql from 'graphql-tag';
5
6
  import { css, html, LitElement } from 'lit';
6
7
  import { customElement, property, query } from 'lit/decorators.js';
7
8
  import { DataGrist, ZERO_DATA } from '@operato/data-grist';
8
- import { client, gqlContext } from '@operato/graphql';
9
+ import { client } from '@operato/graphql';
9
10
  import { i18next } from '@operato/i18n';
10
11
  import { closePopup } from '@operato/popup';
12
+ import { openPopup } from '@operato/layout';
11
13
  import { isMobileDevice } from '@operato/utils';
12
- import { ButtonContainerStyles, CommonGristStyles, ScrollbarStyles } from '@operato/styles';
14
+ import { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles } from '@operato/styles';
13
15
  let ContactSelector = class ContactSelector extends LitElement {
14
16
  constructor() {
15
17
  super(...arguments);
@@ -49,8 +51,7 @@ let ContactSelector = class ContactSelector extends LitElement {
49
51
  filters,
50
52
  pagination: { page, limit },
51
53
  sortings
52
- },
53
- context: gqlContext()
54
+ }
54
55
  });
55
56
  if (!response.errors) {
56
57
  const records = response.data.fetch.items.map((item) => {
@@ -79,18 +80,28 @@ let ContactSelector = class ContactSelector extends LitElement {
79
80
  .fetchHandler=${this.fetchHandler.bind(this)}
80
81
  .selectedRecords=${this.selectedRecords}
81
82
  >
82
- <div id="filters" slot="headroom">
83
- <ox-filters-form autofocus></ox-filters-form>
83
+ <div class="header" slot="headroom">
84
+ <div class="filters">
85
+ <ox-filters-form autofocus without-search></ox-filters-form>
86
+ </div>
87
+
88
+ <div class="actions">
89
+ <button @click=${this.onCreate.bind(this)} class="iconbtn">
90
+ <md-icon>add</md-icon>${i18next.t('button.add')}
91
+ </button>
92
+ </div>
84
93
  </div>
85
94
  </ox-grist>
86
95
 
87
- <div class="button-container" style="margin-left:unset;">
96
+ <div class="footer">
88
97
  <button @click=${this.onEmpty.bind(this)}>
89
98
  <md-icon>check_box_outline_blank</md-icon>${i18next.t('button.empty')}
90
99
  </button>
100
+
91
101
  <div filler></div>
102
+
92
103
  <button @click=${this.onCancel.bind(this)}><md-icon>cancel</md-icon>${i18next.t('button.cancel')}</button>
93
- <button @click=${this.onConfirm.bind(this)}><md-icon>done</md-icon>${i18next.t('button.confirm')}</button>
104
+ <button @click=${this.onConfirm.bind(this)} ok><md-icon>done</md-icon>${i18next.t('button.confirm')}</button>
94
105
  </div>
95
106
  `;
96
107
  }
@@ -105,6 +116,30 @@ let ContactSelector = class ContactSelector extends LitElement {
105
116
  this.confirmCallback && this.confirmCallback(this.selected);
106
117
  closePopup(this);
107
118
  }
119
+ onCreate() {
120
+ var createdContact;
121
+ const popup = openPopup(html `
122
+ <contact-popup
123
+ edit-mode
124
+ .closeCallback=${contact => {
125
+ createdContact = contact;
126
+ }}
127
+ ></contact-popup>
128
+ `, {
129
+ backdrop: true,
130
+ size: 'large',
131
+ title: i18next.t('title.contact')
132
+ });
133
+ popup.onclosed = () => {
134
+ if (createdContact) {
135
+ this.confirmCallback && this.confirmCallback(createdContact);
136
+ closePopup(this);
137
+ }
138
+ else {
139
+ this.grist.fetch();
140
+ }
141
+ };
142
+ }
108
143
  async firstUpdated() {
109
144
  this.config = {
110
145
  pagination: { pages: [100, 200, 500] },
@@ -244,8 +279,8 @@ let ContactSelector = class ContactSelector extends LitElement {
244
279
  };
245
280
  ContactSelector.styles = [
246
281
  ScrollbarStyles,
247
- ButtonContainerStyles,
248
282
  CommonGristStyles,
283
+ CommonHeaderStyles,
249
284
  css `
250
285
  :host {
251
286
  display: flex;
@@ -261,14 +296,8 @@ ContactSelector.styles = [
261
296
  flex: 1;
262
297
  }
263
298
 
264
- #filters {
265
- display: flex;
266
- flex-direction: row;
267
- justify-content: space-between;
268
- }
269
-
270
- #filters > * {
271
- padding: var(--spacing-medium) var(--spacing-large);
299
+ .header {
300
+ grid-template-areas: 'filters actions';
272
301
  }
273
302
  `
274
303
  ];