@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,688 @@
1
+ <template>
2
+ <div v-if="hasActiveUser" id="profile-form-wrapper">
3
+ <p v-if="!didSubmit">
4
+ {{ callToAction }}
5
+ </p>
6
+ <form v-if="!didSubmit" @submit.prevent="handleSubmit">
7
+ <fieldset :disabled="isLoading">
8
+ <div v-if="enableChangeEmail" class="row">
9
+ <div class="col-12">
10
+ <label>Email address</label>
11
+ <div class="form-group">
12
+ <div class="input-group">
13
+ <input disabled :value="user.email" class="form-control">
14
+ <div class="input-group-append">
15
+ <a
16
+ :href="endpoints.changeEmail"
17
+ class="btn btn-outline-secondary d-flex justify-content-center flex-column"
18
+ title="Change your login email address"
19
+ >
20
+ Change email
21
+ </a>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ </div>
27
+ <div class="row">
28
+ <div
29
+ v-if="givenNameSettings.visible"
30
+ class="col-12"
31
+ :class="{ 'col-md-6': familyNameSettings.visible }"
32
+ >
33
+ <given-name
34
+ v-model="user.givenName"
35
+ :required="givenNameSettings.required"
36
+ :label="defaultFieldLabels.givenName"
37
+ />
38
+ </div>
39
+ <div
40
+ v-if="familyNameSettings.visible"
41
+ class="col-12"
42
+ :class="{ 'col-md-6': givenNameSettings.visible }"
43
+ >
44
+ <family-name
45
+ v-model="user.familyName"
46
+ :required="familyNameSettings.required"
47
+ :label="defaultFieldLabels.familyName"
48
+ />
49
+ </div>
50
+ </div>
51
+
52
+ <div class="row">
53
+ <div
54
+ v-if="organizationSettings.visible"
55
+ class="col-12"
56
+ :class="{ 'col-md-6': organizationTitleSettings.visible }"
57
+ >
58
+ <organization
59
+ v-model="user.organization"
60
+ :required="organizationSettings.required"
61
+ :label="defaultFieldLabels.organization"
62
+ />
63
+ </div>
64
+ <div
65
+ v-if="organizationTitleSettings.visible"
66
+ class="col-12"
67
+ :class="{ 'col-md-6': organizationSettings.visible }"
68
+ >
69
+ <organization-title
70
+ v-model="user.organizationTitle"
71
+ :required="organizationTitleSettings.required"
72
+ :label="defaultFieldLabels.organizationTitle"
73
+ />
74
+ </div>
75
+ </div>
76
+
77
+ <div class="row">
78
+ <div
79
+ v-if="phoneNumberSettings.visible"
80
+ class="col-12"
81
+ :class="{
82
+ 'col-md-6': countryCodeSettings.visible || mobileNumberSettings.visible,
83
+ 'col-md-4': countryCodeSettings.visible && mobileNumberSettings.visible,
84
+ }"
85
+ >
86
+ <phone-number
87
+ v-model="user.phoneNumber"
88
+ :required="phoneNumberSettings.required"
89
+ :label="defaultFieldLabels.phoneNumber"
90
+ />
91
+ </div>
92
+ <div
93
+ v-if="mobileNumberSettings.visible"
94
+ class="col-12"
95
+ :class="{
96
+ 'col-md-6': countryCodeSettings.visible || phoneNumberSettings.visible,
97
+ 'col-md-4': countryCodeSettings.visible && phoneNumberSettings.visible,
98
+ }"
99
+ >
100
+ <phone-number
101
+ v-model="user.mobileNumber"
102
+ :required="mobileNumberSettings.required"
103
+ :label="defaultFieldLabels.mobileNumber"
104
+ />
105
+ </div>
106
+ <div
107
+ v-if="countryCodeSettings.visible"
108
+ class="col-12"
109
+ :class="{
110
+ 'col-md-6': mobileNumberSettings.visible || phoneNumberSettings.visible,
111
+ 'col-md-4': mobileNumberSettings.visible && phoneNumberSettings.visible
112
+ }"
113
+ >
114
+ <country
115
+ v-model="user.countryCode"
116
+ :required="countryCodeSettings.required"
117
+ :label="defaultFieldLabels.country"
118
+ />
119
+ </div>
120
+ </div>
121
+
122
+ <address-block
123
+ v-if="showAddressBlock"
124
+ :user="user"
125
+ :street="streetSettings"
126
+ :address-extra="addressExtraSettings"
127
+ :city="citySettings"
128
+ :region-code="regionCodeSettings"
129
+ :postal-code="postalCodeSettings"
130
+ :default-field-labels="defaultFieldLabels"
131
+ />
132
+
133
+ <div v-if="customTextFieldAnswers.length" class="row mt-3">
134
+ <custom-text
135
+ v-for="fieldAnswer in customTextFieldAnswers"
136
+ :id="fieldAnswer.id"
137
+ :key="fieldAnswer.id"
138
+ :label="fieldAnswer.field.label"
139
+ :required="fieldAnswer.field.required"
140
+ :value="fieldAnswer.value"
141
+ @change="onCustomTextChange(fieldAnswer.id, $event)"
142
+ />
143
+ </div>
144
+
145
+ <div v-if="customSelectFieldAnswers.length" class="row">
146
+ <custom-select
147
+ v-for="fieldAnswer in customSelectFieldAnswers"
148
+ :id="fieldAnswer.field.id"
149
+ :key="fieldAnswer.id"
150
+ class="col-12"
151
+ :class="{ 'col-md-6': (customSelectFieldAnswers.length > 1) }"
152
+ :label="fieldAnswer.field.label"
153
+ :required="customSelectIsRequired(fieldAnswer)"
154
+ :multiple="fieldAnswer.field.multiple"
155
+ :selected="fieldAnswer.answers"
156
+ :options="fieldAnswer.field.options"
157
+ @change="onCustomSelectChange(fieldAnswer.answers, $event)"
158
+ />
159
+ </div>
160
+
161
+ <div v-if="customBooleanFieldAnswers.length" class="row mt-3">
162
+ <div
163
+ v-if="booleanQuestionsLabel"
164
+ class="col-12 boolean-questions-label"
165
+ v-html="booleanQuestionsLabel"
166
+ />
167
+ <div
168
+ v-for="fieldAnswer in customBooleanFieldAnswers"
169
+ :key="fieldAnswer.id"
170
+ class="col-12"
171
+ >
172
+ <custom-boolean
173
+ :id="fieldAnswer.id"
174
+ :message="fieldAnswer.field.label"
175
+ :required="fieldAnswer.field.required"
176
+ :value="fieldAnswer.answer"
177
+ @input="onCustomBooleanChange(fieldAnswer.id)"
178
+ />
179
+ </div>
180
+ </div>
181
+
182
+ <form-consent
183
+ :user="user"
184
+ :consent-policy="consentPolicy"
185
+ :consent-policy-enabled="consentPolicyEnabled"
186
+ :email-consent-request="emailConsentRequest"
187
+ :email-consent-request-enabled="emailConsentRequestEnabled"
188
+ :regional-consent-policies="regionalConsentPolicies"
189
+ :country-code="countryCode"
190
+ />
191
+
192
+ <div class="d-flex align-items-center">
193
+ <button type="submit" class="btn btn-primary">
194
+ {{ buttonLabel }}
195
+ </button>
196
+ </div>
197
+ </fieldset>
198
+ <p v-if="error" class="mt-3 text-danger">
199
+ An error occurred: {{ error }}
200
+ </p>
201
+ </form>
202
+ <div v-else>
203
+ <div class="success-message">
204
+ <div class="success-message__title">
205
+ Your profile has been saved.
206
+ </div>
207
+ <div v-if="returnTo" class="success-message__message">
208
+ <p>
209
+ You will be automatically redirected in {{ returnToDelay / 1000 }} seconds.
210
+ </p>
211
+ <p>
212
+ To continue now,
213
+ <a :href="returnTo">click here</a>.
214
+ </p>
215
+ </div>
216
+ <div v-else class="success-message__message">
217
+ <p>
218
+ To continue modifying your profile,
219
+ <button class="" type="button" @click="handleReload()">
220
+ click here
221
+ </button>.
222
+ </p>
223
+ <p>
224
+ To return to the home page, <a href="/">click here</a>.
225
+ </p>
226
+ </div>
227
+ </div>
228
+ </div>
229
+ </div>
230
+ <div v-else>
231
+ <p>You must be logged in to modify your user profile.</p>
232
+ <login
233
+ :additional-event-data="additionalEventData"
234
+ :source="loginSource"
235
+ :endpoints="endpoints"
236
+ :app-context-id="appContextId"
237
+ :consent-policy="consentPolicy"
238
+ :consent-policy-enabled="consentPolicyEnabled"
239
+ :email-consent-request="emailConsentRequest"
240
+ :email-consent-request-enabled="emailConsentRequestEnabled"
241
+ :regional-consent-policies="regionalConsentPolicies"
242
+ :required-create-fields="requiredCreateFields"
243
+ :default-field-labels="defaultFieldLabels"
244
+ />
245
+ </div>
246
+ </template>
247
+
248
+ <script>
249
+ import post from './utils/post';
250
+ import cookiesEnabled from './utils/cookies-enabled';
251
+ import regionCountryCodes from './utils/region-country-codes';
252
+
253
+ import AddressBlock from './form/address-block.vue';
254
+ import FormConsent from './form/consent.vue';
255
+ import CustomBoolean from './form/fields/custom-boolean.vue';
256
+ import CustomSelect from './form/fields/custom-select.vue';
257
+ import CustomText from './form/fields/custom-text.vue';
258
+ import GivenName from './form/fields/given-name.vue';
259
+ import FamilyName from './form/fields/family-name.vue';
260
+ import Organization from './form/fields/organization.vue';
261
+ import OrganizationTitle from './form/fields/organization-title.vue';
262
+ import Country from './form/fields/country.vue';
263
+ import PhoneNumber from './form/fields/phone-number.vue';
264
+ import Login from './login.vue';
265
+
266
+ import FeatureError from './errors/feature';
267
+ import FormError from './errors/form';
268
+ import AutoSignupEventEmitter from './mixins/global-auto-signup-event-emitter';
269
+ import EventEmitter from './mixins/global-event-emitter';
270
+
271
+ const { isArray } = Array;
272
+
273
+ export default {
274
+ components: {
275
+ AddressBlock,
276
+ CustomBoolean,
277
+ CustomSelect,
278
+ CustomText,
279
+ GivenName,
280
+ FamilyName,
281
+ FormConsent,
282
+ Organization,
283
+ OrganizationTitle,
284
+ Country,
285
+ PhoneNumber,
286
+ Login,
287
+ },
288
+
289
+ /**
290
+ *
291
+ */
292
+ mixins: [EventEmitter, AutoSignupEventEmitter],
293
+
294
+ /**
295
+ *
296
+ */
297
+ props: {
298
+ loginSource: {
299
+ type: String,
300
+ default: 'default',
301
+ },
302
+ endpoints: {
303
+ type: Object,
304
+ required: true,
305
+ },
306
+ activeUser: {
307
+ type: Object,
308
+ default: () => ({}),
309
+ },
310
+ callToAction: {
311
+ type: String,
312
+ default: 'To complete your profile, please fill out the required fields.',
313
+ },
314
+ requiredServerFields: {
315
+ type: Array,
316
+ default: () => [],
317
+ },
318
+ requiredClientFields: {
319
+ type: Array,
320
+ default: () => [],
321
+ },
322
+ activeCustomFieldIds: {
323
+ type: Array,
324
+ default: () => [],
325
+ },
326
+ requiredCreateFields: {
327
+ type: Array,
328
+ default: () => [],
329
+ },
330
+ defaultFieldLabels: {
331
+ type: Object,
332
+ default: () => {},
333
+ },
334
+ hiddenFields: {
335
+ type: Array,
336
+ default: () => [],
337
+ },
338
+ reloadPageOnSubmit: {
339
+ type: Boolean,
340
+ default: false,
341
+ },
342
+ consentPolicy: {
343
+ type: String,
344
+ default: null,
345
+ },
346
+ consentPolicyEnabled: {
347
+ type: Boolean,
348
+ default: false,
349
+ },
350
+ emailConsentRequest: {
351
+ type: String,
352
+ default: null,
353
+ },
354
+ emailConsentRequestEnabled: {
355
+ type: Boolean,
356
+ default: false,
357
+ },
358
+ appContextId: {
359
+ type: String,
360
+ default: null,
361
+ },
362
+ buttonLabel: {
363
+ type: String,
364
+ default: 'Submit',
365
+ },
366
+ regionalConsentPolicies: {
367
+ type: Array,
368
+ default: () => [],
369
+ },
370
+ requiredLoginFields: {
371
+ type: Array,
372
+ default: () => [],
373
+ },
374
+ defaultCountryCode: {
375
+ type: String,
376
+ default: null,
377
+ },
378
+ booleanQuestionsLabel: {
379
+ type: String,
380
+ default: null,
381
+ },
382
+ returnTo: {
383
+ type: String,
384
+ default: null,
385
+ },
386
+ returnToDelay: {
387
+ type: Number,
388
+ default: 3000,
389
+ },
390
+ enableChangeEmail: {
391
+ type: Boolean,
392
+ default: false,
393
+ },
394
+ },
395
+
396
+ /**
397
+ *
398
+ */
399
+ data() {
400
+ return {
401
+ error: null,
402
+ isLoading: false,
403
+ isReloadingPage: false,
404
+ isRedirectingPage: false,
405
+ didSubmit: false,
406
+ user: {
407
+ ...this.activeUser,
408
+ ...(
409
+ !this.hiddenFields.includes('countryCode')
410
+ && this.defaultCountryCode
411
+ && !this.activeUser.countryCode
412
+ && { countryCode: this.defaultCountryCode }
413
+ ),
414
+ },
415
+ };
416
+ },
417
+
418
+ /**
419
+ *
420
+ */
421
+ computed: {
422
+ /**
423
+ *
424
+ */
425
+ hasActiveUser() {
426
+ return this.user && this.user.email;
427
+ },
428
+
429
+ /**
430
+ *
431
+ */
432
+ requiredFields() {
433
+ return [...this.requiredServerFields, ...this.requiredClientFields];
434
+ },
435
+
436
+ /**
437
+ *
438
+ */
439
+ countryCode() {
440
+ const { user } = this;
441
+ if (!user) return null;
442
+ return user.countryCode;
443
+ },
444
+
445
+ /**
446
+ *
447
+ */
448
+ customBooleanFieldAnswers() {
449
+ const { activeCustomFieldIds: ids } = this;
450
+ const { customBooleanFieldAnswers } = this.user;
451
+ const answers = isArray(customBooleanFieldAnswers) ? customBooleanFieldAnswers : [];
452
+ return answers.filter(ids.length > 0 ? ({ field }) => ids.includes(field.id) : () => true)
453
+ .sort(this.sortByActiveCustomFieldId);
454
+ },
455
+
456
+ /**
457
+ *
458
+ */
459
+ customSelectFieldAnswers() {
460
+ const { activeCustomFieldIds: ids } = this;
461
+ const { customSelectFieldAnswers } = this.user;
462
+ const answers = isArray(customSelectFieldAnswers) ? customSelectFieldAnswers : [];
463
+ return answers.filter(ids.length > 0 ? ({ field }) => ids.includes(field.id) : () => true)
464
+ .sort(this.sortByActiveCustomFieldIds);
465
+ },
466
+
467
+ /**
468
+ *
469
+ */
470
+ customTextFieldAnswers() {
471
+ const { activeCustomFieldIds: ids } = this;
472
+ const { customTextFieldAnswers } = this.user;
473
+ const answers = isArray(customTextFieldAnswers) ? customTextFieldAnswers : [];
474
+ return answers.filter(ids.length > 0 ? ({ field }) => ids.includes(field.id) : () => true)
475
+ .sort(this.sortByActiveCustomFieldIds);
476
+ },
477
+
478
+ showAddressBlock() {
479
+ // Don't show at all until country is selected.
480
+ if (!this.countryCode) return false;
481
+
482
+ // Only show if a subfield is visible
483
+ if (this.citySettings.visible) return true;
484
+ if (this.streetSettings.visible) return true;
485
+ if (this.regionCodeSettings.visible) return true;
486
+ if (this.postalCodeSettings.visible) return true;
487
+ return false;
488
+ },
489
+
490
+ /**
491
+ * Field settings
492
+ */
493
+ givenNameSettings() {
494
+ return {
495
+ required: this.requiredFields.includes('givenName'),
496
+ visible: !this.hiddenFields.includes('givenName'),
497
+ };
498
+ },
499
+ familyNameSettings() {
500
+ return {
501
+ required: this.requiredFields.includes('familyName'),
502
+ visible: !this.hiddenFields.includes('familyName'),
503
+ };
504
+ },
505
+ organizationSettings() {
506
+ return {
507
+ required: this.requiredFields.includes('organization'),
508
+ visible: !this.hiddenFields.includes('organization'),
509
+ };
510
+ },
511
+ organizationTitleSettings() {
512
+ return {
513
+ required: this.requiredFields.includes('organizationTitle'),
514
+ visible: !this.hiddenFields.includes('organizationTitle'),
515
+ };
516
+ },
517
+ countryCodeSettings() {
518
+ return {
519
+ required: this.requiredFields.includes('countryCode'),
520
+ visible: !this.hiddenFields.includes('countryCode'),
521
+ };
522
+ },
523
+ streetSettings() {
524
+ return {
525
+ required: this.requiredFields.includes('street'),
526
+ visible: !this.hiddenFields.includes('street'),
527
+ };
528
+ },
529
+ addressExtraSettings() {
530
+ return {
531
+ required: this.requiredFields.includes('addressExtra'),
532
+ visible: !this.hiddenFields.includes('addressExtra'),
533
+ };
534
+ },
535
+ phoneNumberSettings() {
536
+ return {
537
+ required: this.requiredFields.includes('phoneNumber'),
538
+ visible: !this.hiddenFields.includes('phoneNumber'),
539
+ };
540
+ },
541
+ mobileNumberSettings() {
542
+ return {
543
+ required: this.requiredFields.includes('mobileNumber'),
544
+ visible: !this.hiddenFields.includes('mobileNumber'),
545
+ };
546
+ },
547
+ citySettings() {
548
+ return {
549
+ required: this.requiredFields.includes('city'),
550
+ visible: !this.hiddenFields.includes('city'),
551
+ };
552
+ },
553
+ regionCodeSettings() {
554
+ const canRequire = regionCountryCodes.includes(this.countryCode);
555
+ return {
556
+ required: canRequire && this.requiredFields.includes('regionCode'),
557
+ visible: canRequire && !this.hiddenFields.includes('regionCode'),
558
+ };
559
+ },
560
+ postalCodeSettings() {
561
+ const canRequire = regionCountryCodes.includes(this.countryCode);
562
+ return {
563
+ required: canRequire && this.requiredFields.includes('postalCode'),
564
+ visible: canRequire && !this.hiddenFields.includes('postalCode'),
565
+ };
566
+ },
567
+ },
568
+
569
+ /**
570
+ *
571
+ */
572
+ watch: {
573
+ /**
574
+ * Clear region and postal codes on country code change.
575
+ */
576
+ countryCode() {
577
+ this.user.regionCode = null;
578
+ this.user.postalCode = null;
579
+ },
580
+ },
581
+
582
+ /**
583
+ *
584
+ */
585
+ mounted() {
586
+ if (cookiesEnabled()) {
587
+ this.emit('profile-mounted');
588
+ } else {
589
+ const error = new FeatureError('Your browser does not support cookies. Please enable cookies to use this feature.');
590
+ this.error = error.message;
591
+ this.emit('profile-errored', { message: error.message });
592
+ }
593
+ },
594
+
595
+ /**
596
+ *
597
+ */
598
+ methods: {
599
+ /**
600
+ *
601
+ */
602
+ onCustomBooleanChange(id) {
603
+ const objIndex = this.customBooleanFieldAnswers.findIndex(((obj) => obj.id === id));
604
+ const answer = !this.customBooleanFieldAnswers[objIndex].answer;
605
+ this.customBooleanFieldAnswers[objIndex].answer = answer;
606
+
607
+ this.user.customBooleanFieldAnswers = this.customBooleanFieldAnswers;
608
+ },
609
+
610
+ onCustomSelectChange(answers, $event) {
611
+ const ids = Array.isArray($event) ? [...$event] : [...($event ? [$event] : [])];
612
+ answers.splice(0);
613
+ if (ids.length) answers.push(...ids.map((id) => ({ id })));
614
+ },
615
+
616
+ onCustomTextChange(id, customText) {
617
+ const objIndex = this.customTextFieldAnswers.findIndex(((obj) => obj.id === id));
618
+ this.customTextFieldAnswers[objIndex].value = customText;
619
+ this.user.customTextFieldAnswers = this.customTextFieldAnswers;
620
+ },
621
+
622
+ customSelectIsRequired(fieldAnswer) {
623
+ return this.requiredFields.includes(fieldAnswer.field.id) || fieldAnswer.field.required;
624
+ },
625
+
626
+ sortByActiveCustomFieldIds(a, b) {
627
+ const { activeCustomFieldIds: ids } = this;
628
+ const sortingArr = ids.length > 0 ? ids : [];
629
+ return sortingArr.indexOf(a.field.id) - sortingArr.indexOf(b.field.id);
630
+ },
631
+
632
+ async handleReload() {
633
+ this.isReloadingPage = true;
634
+ window.location.reload(true);
635
+ },
636
+
637
+ /**
638
+ *
639
+ */
640
+ async handleSubmit() {
641
+ this.error = null;
642
+ this.isLoading = true;
643
+ this.didSubmit = false;
644
+ try {
645
+ const res = await post('/profile', {
646
+ ...this.user,
647
+ additionalEventData: {
648
+ ...this.additionalEventData,
649
+ actionSource: this.loginSource,
650
+ },
651
+ });
652
+ const data = await res.json();
653
+ if (!res.ok) throw new FormError(data.message, res.status);
654
+
655
+ this.user = data.user;
656
+ this.didSubmit = true;
657
+ // force scroll to top of page when form and success message toggle
658
+ window.scrollTo(0, 0);
659
+
660
+ this.emitAutoSignup(data);
661
+ this.emit('profile-updated', {
662
+ additionalEventData: {
663
+ ...(this.additionalEventData || {}),
664
+ ...(data.additionalEventData || {}),
665
+ },
666
+ }, data.entity);
667
+
668
+ if (this.reloadPageOnSubmit) {
669
+ this.isReloadingPage = true;
670
+ window.location.reload(true);
671
+ }
672
+
673
+ if (this.returnTo) {
674
+ this.isRedirectingPage = true;
675
+ setTimeout(() => {
676
+ window.location.href = this.returnTo;
677
+ }, this.returnToDelay);
678
+ }
679
+ } catch (e) {
680
+ this.error = e;
681
+ this.emit('profile-errored', { message: e.message });
682
+ } finally {
683
+ this.isLoading = false;
684
+ }
685
+ },
686
+ },
687
+ };
688
+ </script>
@@ -0,0 +1,32 @@
1
+ // It's 2022, why is there not a better way to do this?
2
+ const getCookie = (key) => {
3
+ const cookies = document.cookie.split(';').reduce((obj, cookie) => {
4
+ const trimmed = cookie.trim();
5
+ if (!trimmed) return obj;
6
+ const [name, value] = trimmed.split('=').map((v) => decodeURIComponent(v.trim()));
7
+ return { ...obj, [name]: value };
8
+ }, {});
9
+ return cookies[key];
10
+ };
11
+
12
+ const parseContext = () => {
13
+ try {
14
+ return JSON.parse(getCookie('__idx_ctx'));
15
+ } catch (e) {
16
+ return {};
17
+ }
18
+ };
19
+
20
+ export default class IdentityX {
21
+ constructor() {
22
+ this.refreshContext();
23
+ }
24
+
25
+ getLoginSource() {
26
+ return this.context.loginSource;
27
+ }
28
+
29
+ refreshContext() {
30
+ this.context = parseContext();
31
+ }
32
+ }