@mindful-web/marko-web-identity-x 1.0.0

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.
Files changed (138) hide show
  1. package/.eslintignore +1 -0
  2. package/LICENSE +21 -0
  3. package/README.md +200 -0
  4. package/api/fragment-types.json +1 -0
  5. package/api/fragments/active-user.js +108 -0
  6. package/api/mutations/add-external-user-id.js +24 -0
  7. package/api/mutations/create-app-user.js +11 -0
  8. package/api/mutations/delete-app-user-for-current-application.js +7 -0
  9. package/api/mutations/impersonate-app-user.js +12 -0
  10. package/api/mutations/logout-app-user.js +11 -0
  11. package/api/mutations/send-change-email-link.js +7 -0
  12. package/api/mutations/send-login-link.js +7 -0
  13. package/api/mutations/set-custom-attributes.js +15 -0
  14. package/api/queries/check-content-access.js +19 -0
  15. package/api/queries/get-active-context.js +45 -0
  16. package/api/queries/load-user-by-external-id.js +14 -0
  17. package/api/queries/load-user-by-id.js +11 -0
  18. package/api/queries/load-user.js +11 -0
  19. package/browser/.eslintrc.js +11 -0
  20. package/browser/access.vue +377 -0
  21. package/browser/authenticate.vue +278 -0
  22. package/browser/change-email-confirm.vue +120 -0
  23. package/browser/change-email-init.vue +179 -0
  24. package/browser/comments/create.vue +107 -0
  25. package/browser/comments/post.vue +151 -0
  26. package/browser/comments/stream.vue +319 -0
  27. package/browser/custom-column.vue +314 -0
  28. package/browser/dayjs.js +6 -0
  29. package/browser/download-related.vue +120 -0
  30. package/browser/download.vue +380 -0
  31. package/browser/errors/authentication.js +7 -0
  32. package/browser/errors/feature.js +7 -0
  33. package/browser/errors/form.js +7 -0
  34. package/browser/errors/logout.js +7 -0
  35. package/browser/form/address-block.vue +131 -0
  36. package/browser/form/common/checkbox-group.vue +140 -0
  37. package/browser/form/common/form-group.vue +24 -0
  38. package/browser/form/common/form-label.vue +17 -0
  39. package/browser/form/consent.vue +121 -0
  40. package/browser/form/fields/address-extra.vue +68 -0
  41. package/browser/form/fields/city.vue +68 -0
  42. package/browser/form/fields/comment-body.vue +63 -0
  43. package/browser/form/fields/country.vue +94 -0
  44. package/browser/form/fields/custom-boolean.vue +58 -0
  45. package/browser/form/fields/custom-select-group.vue +25 -0
  46. package/browser/form/fields/custom-select-multiple.vue +97 -0
  47. package/browser/form/fields/custom-select-write-in-inline.vue +39 -0
  48. package/browser/form/fields/custom-select-write-in.vue +66 -0
  49. package/browser/form/fields/custom-select.vue +191 -0
  50. package/browser/form/fields/custom-text.vue +62 -0
  51. package/browser/form/fields/display-name.vue +64 -0
  52. package/browser/form/fields/email.vue +62 -0
  53. package/browser/form/fields/family-name.vue +68 -0
  54. package/browser/form/fields/given-name.vue +68 -0
  55. package/browser/form/fields/organization-title.vue +68 -0
  56. package/browser/form/fields/organization.vue +68 -0
  57. package/browser/form/fields/phone-number.vue +68 -0
  58. package/browser/form/fields/postal-code.vue +68 -0
  59. package/browser/form/fields/receive-email.vue +58 -0
  60. package/browser/form/fields/region.vue +106 -0
  61. package/browser/form/fields/regional-policy.vue +59 -0
  62. package/browser/form/fields/street.vue +68 -0
  63. package/browser/graphql/create-client.js +65 -0
  64. package/browser/graphql/parse.js +1 -0
  65. package/browser/graphql/queries/download-related-content.js +38 -0
  66. package/browser/index.js +110 -0
  67. package/browser/login-fields.vue +214 -0
  68. package/browser/login.vue +331 -0
  69. package/browser/logout.vue +68 -0
  70. package/browser/mixins/global-auto-signup-event-emitter.js +18 -0
  71. package/browser/mixins/global-event-emitter.js +28 -0
  72. package/browser/profile.vue +688 -0
  73. package/browser/service.js +32 -0
  74. package/browser/utils/clean-path.js +1 -0
  75. package/browser/utils/cookies-enabled.js +10 -0
  76. package/browser/utils/get-as-array.js +6 -0
  77. package/browser/utils/get-referring-page.js +7 -0
  78. package/browser/utils/get.js +8 -0
  79. package/browser/utils/post.js +10 -0
  80. package/browser/utils/redirect.js +7 -0
  81. package/browser/utils/region-country-codes.js +1 -0
  82. package/components/access.marko +24 -0
  83. package/components/access.marko.js +61 -0
  84. package/components/comment-stream.marko +31 -0
  85. package/components/comment-stream.marko.js +71 -0
  86. package/components/context.marko +15 -0
  87. package/components/context.marko.js +52 -0
  88. package/components/form-access.marko +60 -0
  89. package/components/form-access.marko.js +111 -0
  90. package/components/form-authenticate.marko +32 -0
  91. package/components/form-authenticate.marko.js +73 -0
  92. package/components/form-change-email.marko +27 -0
  93. package/components/form-change-email.marko.js +68 -0
  94. package/components/form-login.marko +32 -0
  95. package/components/form-login.marko.js +72 -0
  96. package/components/form-logout.marko +7 -0
  97. package/components/form-logout.marko.js +36 -0
  98. package/components/form-profile.marko +38 -0
  99. package/components/form-profile.marko.js +78 -0
  100. package/components/form-register.marko +2 -0
  101. package/components/form-register.marko.js +32 -0
  102. package/components/identify.marko +17 -0
  103. package/components/identify.marko.js +59 -0
  104. package/components/marko.json +90 -0
  105. package/components/non-auth-identify.marko +15 -0
  106. package/components/non-auth-identify.marko.js +53 -0
  107. package/config.js +161 -0
  108. package/hooks.js +20 -0
  109. package/index.js +30 -0
  110. package/marko.json +6 -0
  111. package/middleware/content-access-state.js +31 -0
  112. package/middleware/content-download-state.js +27 -0
  113. package/middleware.js +32 -0
  114. package/package.json +40 -0
  115. package/routes/access.js +29 -0
  116. package/routes/authenticate.js +58 -0
  117. package/routes/change-email-confirm.js +60 -0
  118. package/routes/change-email-init.js +16 -0
  119. package/routes/comment-count.js +19 -0
  120. package/routes/comments.js +43 -0
  121. package/routes/countries.js +19 -0
  122. package/routes/create-comment.js +25 -0
  123. package/routes/download.js +29 -0
  124. package/routes/flag-comment.js +21 -0
  125. package/routes/index.js +40 -0
  126. package/routes/login-fields.js +35 -0
  127. package/routes/login.js +95 -0
  128. package/routes/logout.js +19 -0
  129. package/routes/profile.js +183 -0
  130. package/routes/regions.js +22 -0
  131. package/service.js +483 -0
  132. package/utils/call-hooks-for.js +28 -0
  133. package/utils/context-cookie.js +30 -0
  134. package/utils/create-client.js +48 -0
  135. package/utils/create-identity-builder.js +33 -0
  136. package/utils/get-as-array.js +6 -0
  137. package/utils/json-error-handler.js +41 -0
  138. package/utils/token-cookie.js +30 -0
@@ -0,0 +1,319 @@
1
+ <template>
2
+ <div :class="classNames">
3
+ <div :class="element('header')">
4
+ {{ headerText }}
5
+ </div>
6
+
7
+ <div :class="element('body')">
8
+ <div
9
+ v-if="hasActiveUser"
10
+ :class="element('create-post')"
11
+ >
12
+ <p :class="element('login-message')">
13
+ <span :class="element(`login-message--cta`)">
14
+ Post a Comment
15
+ </span>
16
+ </p>
17
+ <div v-if="archived" :class="element('archived')">
18
+ This thread is archived and is no longer accepting comments.
19
+ </div>
20
+ <create
21
+ v-else
22
+ :display-name="activeUser.displayName"
23
+ :stream="{ identifier, title, description, url }"
24
+ @comment-post-submitted="load"
25
+ />
26
+ </div>
27
+ <div v-else :class="element('login-form-wrapper')">
28
+ <p v-if="showLoginMessage" :class="element('login-message')">
29
+ <span :class="element(`login-message--cta`)">
30
+ Post a Comment
31
+ </span>
32
+ You must be signed in to leave a comment.
33
+ To sign in or create an account,
34
+ enter your email address and we'll send you a one-click sign-in link.
35
+ </p>
36
+ <login
37
+ :class="element('login-form')"
38
+ :additional-event-data="additionalEventData"
39
+ :source="loginSource"
40
+ :active-user="activeUser"
41
+ :endpoints="endpoints"
42
+ :consent-policy="consentPolicy"
43
+ :app-context-id="appContextId"
44
+ :regional-consent-policies="regionalConsentPolicies"
45
+ :button-labels="loginButtonLabels"
46
+ :required-create-fields="requiredCreateFields"
47
+ :default-field-labels="defaultFieldLabels"
48
+ @login-link-sent="showLoginMessage = false"
49
+ />
50
+ </div>
51
+
52
+ <h5
53
+ v-if="latestCommentsHeader && approvedComments.length"
54
+ :class="element('latest-comments')"
55
+ >
56
+ {{ latestCommentsHeader }} ({{ approvedComments.length }})
57
+ </h5>
58
+ </div>
59
+ <div v-if="isLoading" :class="element('loading')">
60
+ Loading comments...
61
+ </div>
62
+ <div v-else-if="error" :class="element('error')">
63
+ Unable to load comments: {{ error.message }}
64
+ </div>
65
+ <div v-else-if="approvedComments.length === 0" :class="element('no-posts')">
66
+ {{ noCommentsMessage }}
67
+ </div>
68
+ <div v-else :class="element('posts')">
69
+ <div
70
+ v-for="comment in approvedComments"
71
+ :key="comment.id"
72
+ :class="element('post')"
73
+ >
74
+ <post
75
+ :id="comment.id"
76
+ :additional-event-data="additionalEventData"
77
+ :body="comment.body"
78
+ :display-name="comment.user.displayName"
79
+ :created-at="comment.createdAt"
80
+ :approved="comment.approved"
81
+ :flagged="comment.flagged"
82
+ :date-format="dateFormat"
83
+ :active-user="activeUser"
84
+ @comment-report-submitted="load"
85
+ />
86
+ </div>
87
+ <div v-if="hasNextPage" :class="element('post')">
88
+ <button :class="loadMoreButtonClass" :disabled="isLoadingMore" @click.prevent="loadMore">
89
+ <span v-if="isLoadingMore">Loading...</span>
90
+ <span v-else>{{ loadMoreCommentsMessage }}</span>
91
+ </button>
92
+ </div>
93
+ </div>
94
+ <div :class="element('bottom')" />
95
+ </div>
96
+ </template>
97
+
98
+ <script>
99
+ import get from '../utils/get';
100
+ import Login from '../login.vue';
101
+ import Post from './post.vue';
102
+ import Create from './create.vue';
103
+ import EventEmitter from '../mixins/global-event-emitter';
104
+
105
+ export default {
106
+ /**
107
+ *
108
+ */
109
+ components: { Login, Post, Create },
110
+
111
+ /**
112
+ *
113
+ */
114
+ mixins: [EventEmitter],
115
+
116
+ /**
117
+ *
118
+ */
119
+ props: {
120
+ loginSource: {
121
+ type: String,
122
+ default: 'comments',
123
+ },
124
+ activeUser: {
125
+ type: Object,
126
+ default: () => {},
127
+ },
128
+ identifier: {
129
+ type: String,
130
+ required: true,
131
+ },
132
+ title: {
133
+ type: String,
134
+ default: undefined,
135
+ },
136
+ description: {
137
+ type: String,
138
+ default: undefined,
139
+ },
140
+ url: {
141
+ type: String,
142
+ default: undefined,
143
+ },
144
+ endpoints: {
145
+ type: Object,
146
+ required: true,
147
+ },
148
+ headerText: {
149
+ type: String,
150
+ default: 'Comments',
151
+ },
152
+ loadMoreButtonClass: {
153
+ type: String,
154
+ default: 'btn btn-primary',
155
+ },
156
+ loadMoreCommentsMessage: {
157
+ type: String,
158
+ default: 'Show More Comments',
159
+ },
160
+ latestCommentsHeader: {
161
+ type: String,
162
+ default: 'All Comments',
163
+ },
164
+ loginButtonLabels: {
165
+ type: Object,
166
+ default: () => ({
167
+ submit: 'Login / Register',
168
+ continue: 'Continue',
169
+ logout: 'Logout',
170
+ }),
171
+ },
172
+ noCommentsMessage: {
173
+ type: String,
174
+ default: 'This article hasn’t received any comments yet. Want to start the conversation?',
175
+ },
176
+ modifiers: {
177
+ type: Array,
178
+ default: () => [],
179
+ },
180
+ consentPolicy: {
181
+ type: String,
182
+ default: null,
183
+ },
184
+ dateFormat: {
185
+ type: String,
186
+ default: undefined,
187
+ },
188
+ appContextId: {
189
+ type: String,
190
+ default: null,
191
+ },
192
+ regionalConsentPolicies: {
193
+ type: Array,
194
+ default: () => [],
195
+ },
196
+ requiredCreateFields: {
197
+ type: Array,
198
+ default: () => [],
199
+ },
200
+ defaultFieldLabels: {
201
+ type: Object,
202
+ default: () => ({}),
203
+ },
204
+ },
205
+
206
+ data: () => ({
207
+ blockName: 'idx-comment-stream',
208
+ isLoading: false,
209
+ isLoadingMore: false,
210
+ showLoginMessage: true,
211
+ error: null,
212
+ comments: [],
213
+ archived: false,
214
+ hasNextPage: false,
215
+ endCursor: null,
216
+ totalCount: 0,
217
+ }),
218
+
219
+ computed: {
220
+ /**
221
+ *
222
+ */
223
+ classNames() {
224
+ const { blockName } = this;
225
+ const classNames = [blockName];
226
+ this.modifiers.map((mod) => classNames.push(`${blockName}--${mod}`));
227
+ classNames.push(`${blockName}__counter--${this.comments.length}`);
228
+ return classNames;
229
+ },
230
+
231
+ /**
232
+ *
233
+ */
234
+ hasActiveUser() {
235
+ return this.activeUser && this.activeUser.email;
236
+ },
237
+ /**
238
+ *
239
+ */
240
+ approvedComments() {
241
+ return this.comments.filter((comment) => comment.approved);
242
+ },
243
+ },
244
+
245
+ /**
246
+ *
247
+ */
248
+ created() {
249
+ this.load();
250
+ },
251
+
252
+ /**
253
+ *
254
+ */
255
+ mounted() {
256
+ this.emit('comment-stream-mounted', { identifier: this.identifier });
257
+ },
258
+
259
+ /**
260
+ *
261
+ */
262
+ methods: {
263
+ /**
264
+ *
265
+ */
266
+ element(name) {
267
+ return `${this.blockName}__${name}`;
268
+ },
269
+
270
+ /**
271
+ *
272
+ */
273
+ async load() {
274
+ this.error = null;
275
+ this.isLoading = true;
276
+ try {
277
+ const res = await get(`/comments/${this.identifier}`);
278
+ const data = await res.json();
279
+ if (!res.ok) throw new Error(data.message);
280
+ this.totalCount = data.totalCount;
281
+ this.comments = data.edges.map((edge) => edge.node);
282
+ this.hasNextPage = data.pageInfo.hasNextPage;
283
+ this.endCursor = data.pageInfo.endCursor;
284
+ this.archived = data.stream ? data.stream.archived : false;
285
+ this.emit('comment-stream-loaded', { hasNextPage: this.hasNextPage });
286
+ } catch (e) {
287
+ this.error = e;
288
+ this.emit('comment-stream-errored', { message: e.message });
289
+ } finally {
290
+ this.isLoading = false;
291
+ }
292
+ },
293
+
294
+ /**
295
+ *
296
+ */
297
+ async loadMore() {
298
+ this.error = null;
299
+ this.isLoadingMore = true;
300
+ try {
301
+ const res = await get(`/comments/${this.identifier}?after=${this.endCursor}`);
302
+ const data = await res.json();
303
+ if (!res.ok) throw new Error(data.message);
304
+ this.totalCount = data.totalCount;
305
+ const comments = data.edges.map((edge) => edge.node);
306
+ this.comments.push(...comments);
307
+ this.hasNextPage = data.pageInfo.hasNextPage;
308
+ this.endCursor = data.pageInfo.endCursor;
309
+ this.emit('comment-stream-loaded-more', { hasNextPage: this.hasNextPage });
310
+ } catch (e) {
311
+ this.error = e;
312
+ this.emit('comment-stream-errored', { message: e.message });
313
+ } finally {
314
+ this.isLoadingMore = false;
315
+ }
316
+ },
317
+ },
318
+ };
319
+ </script>
@@ -0,0 +1,314 @@
1
+ <template>
2
+ <div :class="colClasses">
3
+ <!-- @todo compute and dynamic render this if the props are the same? -->
4
+ <given-name
5
+ v-if="fieldKey === 'givenName'"
6
+ v-model="user.givenName"
7
+ :class-name="className"
8
+ :required="required"
9
+ :label="label"
10
+ />
11
+ <family-name
12
+ v-else-if="fieldKey === 'familyName'"
13
+ v-model="user.familyName"
14
+ :class-name="className"
15
+ :required="required"
16
+ :label="label"
17
+ />
18
+ <div v-else-if="fieldKey === 'email'">
19
+ <form-label :for="fieldKey" :required="required">
20
+ {{ label }}
21
+ </form-label>
22
+ <div class="form-group">
23
+ <div class="input-group">
24
+ <input disabled :value="user.email" class="form-control">
25
+ <div v-if="enableChangeEmail" class="input-group-append">
26
+ <a
27
+ :href="endpoints.changeEmail"
28
+ class="btn btn-outline-secondary d-flex justify-content-center flex-column"
29
+ title="Change your login email address"
30
+ >
31
+ Change
32
+ </a>
33
+ </div>
34
+ </div>
35
+ </div>
36
+ </div>
37
+ <organization
38
+ v-else-if="fieldKey === 'organization'"
39
+ v-model="user.organization"
40
+ :class-name="className"
41
+ :required="required"
42
+ :label="label"
43
+ />
44
+ <organization-title
45
+ v-else-if="fieldKey === 'organizationTitle'"
46
+ v-model="user.organizationTitle"
47
+ :class-name="className"
48
+ :required="required"
49
+ :label="label"
50
+ />
51
+ <phone-number
52
+ v-else-if="fieldKey === 'phoneNumber'"
53
+ v-model="user.phoneNumber"
54
+ :class-name="className"
55
+ :required="required"
56
+ :label="label"
57
+ />
58
+ <phone-number
59
+ v-else-if="fieldKey === 'mobileNumber'"
60
+ v-model="user.mobileNumber"
61
+ :class-name="className"
62
+ :required="required"
63
+ :label="label"
64
+ />
65
+ <country-code
66
+ v-else-if="fieldKey === 'countryCode'"
67
+ v-model="user.countryCode"
68
+ :class-name="className"
69
+ :required="required"
70
+ :label="label"
71
+ />
72
+ <street
73
+ v-else-if="fieldKey === 'street'"
74
+ v-model="user.street"
75
+ :class-name="className"
76
+ :required="required"
77
+ :label="label"
78
+ />
79
+ <address-extra
80
+ v-else-if="fieldKey === 'addressExtra'"
81
+ v-model="user.addressExtra"
82
+ :class-name="className"
83
+ :required="required"
84
+ :label="label"
85
+ />
86
+ <city
87
+ v-else-if="fieldKey === 'city'"
88
+ v-model="user.city"
89
+ :class-name="className"
90
+ :required="required"
91
+ :label="label"
92
+ />
93
+ <template v-else-if="fieldKey === 'regionCode'">
94
+ <region-code
95
+ v-if="showCountryCodeFields"
96
+ v-model="user.regionCode"
97
+ :country-code="user.countryCode"
98
+ :class-name="className"
99
+ :required="required"
100
+ :label="label"
101
+ />
102
+ </template>
103
+ <template v-else-if="fieldKey === 'postalCode'">
104
+ <postal-code
105
+ v-if="showCountryCodeFields"
106
+ v-model="user.postalCode"
107
+ :class-name="className"
108
+ :required="required"
109
+ :label="label"
110
+ />
111
+ </template>
112
+ <custom-select
113
+ v-else-if="type === 'custom-select' && customField"
114
+ :id="fieldId"
115
+ :label="label"
116
+ :required="required"
117
+ :multiple="customField.field.multiple"
118
+ :selected="customField.answers"
119
+ :options="customField.field.options"
120
+ @change="onCustomSelectChange(customField.answers, $event)"
121
+ />
122
+ <custom-boolean
123
+ v-else-if="type === 'custom-boolean' && customField"
124
+ :id="fieldId"
125
+ :label="label"
126
+ :message="label"
127
+ :required="required"
128
+ :value="customField.answer"
129
+ @input="onCustomBooleanChange(customField.id, $event)"
130
+ />
131
+ <pre v-else>
132
+ label: {{ label }}
133
+ key: {{ fieldKey }}
134
+ id: {{ fieldId }}
135
+ type: {{ type }}
136
+ required: {{ required }}
137
+ width: {{ width }}
138
+ </pre>
139
+ </div>
140
+ </template>
141
+
142
+ <script>
143
+ import regionCountryCodes from './utils/region-country-codes';
144
+ import AddressExtra from './form/fields/address-extra.vue';
145
+ import City from './form/fields/city.vue';
146
+ import CountryCode from './form/fields/country.vue';
147
+ import CustomBoolean from './form/fields/custom-boolean.vue';
148
+ import CustomSelect from './form/fields/custom-select.vue';
149
+ import FamilyName from './form/fields/family-name.vue';
150
+ import FormLabel from './form/common/form-label.vue';
151
+ import GivenName from './form/fields/given-name.vue';
152
+ import Organization from './form/fields/organization.vue';
153
+ import OrganizationTitle from './form/fields/organization-title.vue';
154
+ import PhoneNumber from './form/fields/phone-number.vue';
155
+ import PostalCode from './form/fields/postal-code.vue';
156
+ import RegionCode from './form/fields/region.vue';
157
+ import Street from './form/fields/street.vue';
158
+
159
+ export default {
160
+ /**
161
+ *
162
+ */
163
+ components: {
164
+ AddressExtra,
165
+ City,
166
+ CountryCode,
167
+ CustomSelect,
168
+ CustomBoolean,
169
+ FamilyName,
170
+ FormLabel,
171
+ GivenName,
172
+ Organization,
173
+ OrganizationTitle,
174
+ PhoneNumber,
175
+ PostalCode,
176
+ RegionCode,
177
+ Street,
178
+ },
179
+ /**
180
+ *
181
+ */
182
+ props: {
183
+ label: {
184
+ type: String,
185
+ required: true,
186
+ },
187
+ fieldKey: {
188
+ type: String,
189
+ default: null,
190
+ },
191
+ fieldId: {
192
+ type: String,
193
+ default: null,
194
+ },
195
+ type: {
196
+ type: String,
197
+ required: true,
198
+ validator(value) {
199
+ return ['built-in', 'custom-select', 'custom-boolean'].includes(value);
200
+ },
201
+ },
202
+ required: {
203
+ type: Boolean,
204
+ default: false,
205
+ },
206
+ width: {
207
+ type: Number,
208
+ default: 1,
209
+ validator(value) {
210
+ return [0.25, 0.33, 0.5, 0.66, 1].includes(value);
211
+ },
212
+ },
213
+ user: {
214
+ type: Object,
215
+ required: true,
216
+ },
217
+ endpoints: {
218
+ type: Object,
219
+ required: true,
220
+ },
221
+ enableChangeEmail: {
222
+ type: Boolean,
223
+ default: false,
224
+ },
225
+ className: {
226
+ type: String,
227
+ default: '',
228
+ },
229
+ },
230
+ /**
231
+ *
232
+ */
233
+ computed: {
234
+ countryCode() {
235
+ return this.user.countryCode;
236
+ },
237
+ /**
238
+ *
239
+ */
240
+ showCountryCodeFields() {
241
+ return regionCountryCodes.includes(this.user.countryCode);
242
+ },
243
+
244
+ /**
245
+ *
246
+ */
247
+ customField() {
248
+ const { fieldId, user, type } = this;
249
+ const key = type === 'custom-select' ? 'customSelectFieldAnswers' : 'customBooleanFieldAnswers';
250
+ const found = user[key].find((ans) => ans.id === fieldId);
251
+ return found;
252
+ },
253
+ /**
254
+ *
255
+ */
256
+ colClasses() {
257
+ const classes = ['col'];
258
+ switch (this.width) {
259
+ case 0.25:
260
+ classes.push('col-md-3');
261
+ break;
262
+ case 0.33:
263
+ classes.push('col-md-4');
264
+ break;
265
+ case 0.5:
266
+ classes.push('col-md-6');
267
+ break;
268
+ case 0.66:
269
+ classes.push('col-md-8');
270
+ break;
271
+ default:
272
+ break;
273
+ }
274
+ return classes;
275
+ },
276
+ },
277
+ /**
278
+ *
279
+ */
280
+ watch: {
281
+ /**
282
+ * Clear region and postal codes on country code change.
283
+ */
284
+ countryCode() {
285
+ this.user.regionCode = null;
286
+ this.user.postalCode = null;
287
+ },
288
+ },
289
+
290
+ /**
291
+ *
292
+ */
293
+ methods: {
294
+ /**
295
+ *
296
+ */
297
+ onCustomBooleanChange(id) {
298
+ const objIndex = this.customBooleanFieldAnswers.findIndex(((obj) => obj.id === id));
299
+ const answer = !this.customBooleanFieldAnswers[objIndex].answer;
300
+ this.customBooleanFieldAnswers[objIndex].answer = answer;
301
+ this.user.customBooleanFieldAnswers = this.customBooleanFieldAnswers;
302
+ },
303
+
304
+ /**
305
+ *
306
+ */
307
+ onCustomSelectChange(answers, $event) {
308
+ const ids = Array.isArray($event) ? [...$event] : [...($event ? [$event] : [])];
309
+ answers.splice(0);
310
+ if (ids.length) answers.push(...ids.map((id) => ({ id })));
311
+ },
312
+ },
313
+ };
314
+ </script>
@@ -0,0 +1,6 @@
1
+ import dayjs from 'dayjs';
2
+ import advancedFormat from 'dayjs/plugin/advancedFormat';
3
+
4
+ dayjs.extend(advancedFormat);
5
+
6
+ export default dayjs;