@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.
- package/.eslintignore +1 -0
- package/LICENSE +21 -0
- package/README.md +200 -0
- package/api/fragment-types.json +1 -0
- package/api/fragments/active-user.js +108 -0
- package/api/mutations/add-external-user-id.js +24 -0
- package/api/mutations/create-app-user.js +11 -0
- package/api/mutations/delete-app-user-for-current-application.js +7 -0
- package/api/mutations/impersonate-app-user.js +12 -0
- package/api/mutations/logout-app-user.js +11 -0
- package/api/mutations/send-change-email-link.js +7 -0
- package/api/mutations/send-login-link.js +7 -0
- package/api/mutations/set-custom-attributes.js +15 -0
- package/api/queries/check-content-access.js +19 -0
- package/api/queries/get-active-context.js +45 -0
- package/api/queries/load-user-by-external-id.js +14 -0
- package/api/queries/load-user-by-id.js +11 -0
- package/api/queries/load-user.js +11 -0
- package/browser/.eslintrc.js +11 -0
- package/browser/access.vue +377 -0
- package/browser/authenticate.vue +278 -0
- package/browser/change-email-confirm.vue +120 -0
- package/browser/change-email-init.vue +179 -0
- package/browser/comments/create.vue +107 -0
- package/browser/comments/post.vue +151 -0
- package/browser/comments/stream.vue +319 -0
- package/browser/custom-column.vue +314 -0
- package/browser/dayjs.js +6 -0
- package/browser/download-related.vue +120 -0
- package/browser/download.vue +380 -0
- package/browser/errors/authentication.js +7 -0
- package/browser/errors/feature.js +7 -0
- package/browser/errors/form.js +7 -0
- package/browser/errors/logout.js +7 -0
- package/browser/form/address-block.vue +131 -0
- package/browser/form/common/checkbox-group.vue +140 -0
- package/browser/form/common/form-group.vue +24 -0
- package/browser/form/common/form-label.vue +17 -0
- package/browser/form/consent.vue +121 -0
- package/browser/form/fields/address-extra.vue +68 -0
- package/browser/form/fields/city.vue +68 -0
- package/browser/form/fields/comment-body.vue +63 -0
- package/browser/form/fields/country.vue +94 -0
- package/browser/form/fields/custom-boolean.vue +58 -0
- package/browser/form/fields/custom-select-group.vue +25 -0
- package/browser/form/fields/custom-select-multiple.vue +97 -0
- package/browser/form/fields/custom-select-write-in-inline.vue +39 -0
- package/browser/form/fields/custom-select-write-in.vue +66 -0
- package/browser/form/fields/custom-select.vue +191 -0
- package/browser/form/fields/custom-text.vue +62 -0
- package/browser/form/fields/display-name.vue +64 -0
- package/browser/form/fields/email.vue +62 -0
- package/browser/form/fields/family-name.vue +68 -0
- package/browser/form/fields/given-name.vue +68 -0
- package/browser/form/fields/organization-title.vue +68 -0
- package/browser/form/fields/organization.vue +68 -0
- package/browser/form/fields/phone-number.vue +68 -0
- package/browser/form/fields/postal-code.vue +68 -0
- package/browser/form/fields/receive-email.vue +58 -0
- package/browser/form/fields/region.vue +106 -0
- package/browser/form/fields/regional-policy.vue +59 -0
- package/browser/form/fields/street.vue +68 -0
- package/browser/graphql/create-client.js +65 -0
- package/browser/graphql/parse.js +1 -0
- package/browser/graphql/queries/download-related-content.js +38 -0
- package/browser/index.js +110 -0
- package/browser/login-fields.vue +214 -0
- package/browser/login.vue +331 -0
- package/browser/logout.vue +68 -0
- package/browser/mixins/global-auto-signup-event-emitter.js +18 -0
- package/browser/mixins/global-event-emitter.js +28 -0
- package/browser/profile.vue +688 -0
- package/browser/service.js +32 -0
- package/browser/utils/clean-path.js +1 -0
- package/browser/utils/cookies-enabled.js +10 -0
- package/browser/utils/get-as-array.js +6 -0
- package/browser/utils/get-referring-page.js +7 -0
- package/browser/utils/get.js +8 -0
- package/browser/utils/post.js +10 -0
- package/browser/utils/redirect.js +7 -0
- package/browser/utils/region-country-codes.js +1 -0
- package/components/access.marko +24 -0
- package/components/access.marko.js +61 -0
- package/components/comment-stream.marko +31 -0
- package/components/comment-stream.marko.js +71 -0
- package/components/context.marko +15 -0
- package/components/context.marko.js +52 -0
- package/components/form-access.marko +60 -0
- package/components/form-access.marko.js +111 -0
- package/components/form-authenticate.marko +32 -0
- package/components/form-authenticate.marko.js +73 -0
- package/components/form-change-email.marko +27 -0
- package/components/form-change-email.marko.js +68 -0
- package/components/form-login.marko +32 -0
- package/components/form-login.marko.js +72 -0
- package/components/form-logout.marko +7 -0
- package/components/form-logout.marko.js +36 -0
- package/components/form-profile.marko +38 -0
- package/components/form-profile.marko.js +78 -0
- package/components/form-register.marko +2 -0
- package/components/form-register.marko.js +32 -0
- package/components/identify.marko +17 -0
- package/components/identify.marko.js +59 -0
- package/components/marko.json +90 -0
- package/components/non-auth-identify.marko +15 -0
- package/components/non-auth-identify.marko.js +53 -0
- package/config.js +161 -0
- package/hooks.js +20 -0
- package/index.js +30 -0
- package/marko.json +6 -0
- package/middleware/content-access-state.js +31 -0
- package/middleware/content-download-state.js +27 -0
- package/middleware.js +32 -0
- package/package.json +40 -0
- package/routes/access.js +29 -0
- package/routes/authenticate.js +58 -0
- package/routes/change-email-confirm.js +60 -0
- package/routes/change-email-init.js +16 -0
- package/routes/comment-count.js +19 -0
- package/routes/comments.js +43 -0
- package/routes/countries.js +19 -0
- package/routes/create-comment.js +25 -0
- package/routes/download.js +29 -0
- package/routes/flag-comment.js +21 -0
- package/routes/index.js +40 -0
- package/routes/login-fields.js +35 -0
- package/routes/login.js +95 -0
- package/routes/logout.js +19 -0
- package/routes/profile.js +183 -0
- package/routes/regions.js +22 -0
- package/service.js +483 -0
- package/utils/call-hooks-for.js +28 -0
- package/utils/context-cookie.js +30 -0
- package/utils/create-client.js +48 -0
- package/utils/create-identity-builder.js +33 -0
- package/utils/get-as-array.js +6 -0
- package/utils/json-error-handler.js +41 -0
- package/utils/token-cookie.js +30 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="isRedirecting">
|
|
3
|
+
<p>You've successfully changed your email. Redirecting you...</p>
|
|
4
|
+
</div>
|
|
5
|
+
<div v-else-if="isLoading">
|
|
6
|
+
<p>Changing your email...</p>
|
|
7
|
+
</div>
|
|
8
|
+
<div v-else-if="error" class="alert alert-danger" role="alert">
|
|
9
|
+
<h5 class="alert-heading">
|
|
10
|
+
Unable to change email
|
|
11
|
+
</h5>
|
|
12
|
+
<p>{{ error.message }}</p>
|
|
13
|
+
<hr>
|
|
14
|
+
<p class="mb-0">
|
|
15
|
+
Please try <a :href="endpoints.login" class="alert-link">logging in</a> again.
|
|
16
|
+
</p>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script>
|
|
21
|
+
import redirect from './utils/redirect';
|
|
22
|
+
import cookiesEnabled from './utils/cookies-enabled';
|
|
23
|
+
import post from './utils/post';
|
|
24
|
+
import AuthenticationError from './errors/authentication';
|
|
25
|
+
import FeatureError from './errors/feature';
|
|
26
|
+
import EventEmitter from './mixins/global-event-emitter';
|
|
27
|
+
|
|
28
|
+
export default {
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
*/
|
|
32
|
+
mixins: [EventEmitter],
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
*/
|
|
37
|
+
props: {
|
|
38
|
+
token: {
|
|
39
|
+
type: String,
|
|
40
|
+
required: true,
|
|
41
|
+
},
|
|
42
|
+
endpoints: {
|
|
43
|
+
type: Object,
|
|
44
|
+
required: true,
|
|
45
|
+
},
|
|
46
|
+
redirectTo: {
|
|
47
|
+
type: String,
|
|
48
|
+
default: '/',
|
|
49
|
+
},
|
|
50
|
+
buttonLabel: {
|
|
51
|
+
type: String,
|
|
52
|
+
default: 'Submit',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
*/
|
|
59
|
+
data: () => ({
|
|
60
|
+
error: null,
|
|
61
|
+
isLoading: false,
|
|
62
|
+
isRedirecting: false,
|
|
63
|
+
}),
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
*
|
|
67
|
+
*/
|
|
68
|
+
mounted() {
|
|
69
|
+
if (cookiesEnabled()) {
|
|
70
|
+
this.emit('change-email-mounted');
|
|
71
|
+
this.changeEmail();
|
|
72
|
+
} else {
|
|
73
|
+
this.error = new FeatureError('Your browser does not support cookies. Please enable cookies to use this feature.');
|
|
74
|
+
this.emit('change-email-errored', { message: this.error.message });
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
*
|
|
80
|
+
*/
|
|
81
|
+
methods: {
|
|
82
|
+
/**
|
|
83
|
+
*
|
|
84
|
+
*/
|
|
85
|
+
async changeEmail() {
|
|
86
|
+
this.isLoading = true;
|
|
87
|
+
try {
|
|
88
|
+
const { token } = this;
|
|
89
|
+
if (!token) throw new Error('No change email token was provided.');
|
|
90
|
+
|
|
91
|
+
const res = await post('/change-email/confirm', { token });
|
|
92
|
+
const data = await res.json();
|
|
93
|
+
|
|
94
|
+
if (!res.ok) throw new AuthenticationError(data.message, res.status);
|
|
95
|
+
|
|
96
|
+
this.emit('change-email', { data }, data.entity);
|
|
97
|
+
|
|
98
|
+
this.redirect();
|
|
99
|
+
} catch (e) {
|
|
100
|
+
if (/no token was found/i.test(e.message)) {
|
|
101
|
+
e.message = 'This change email link has either expired or was already used.';
|
|
102
|
+
}
|
|
103
|
+
this.error = e;
|
|
104
|
+
this.emit('change-email-errored', { message: e.message });
|
|
105
|
+
} finally {
|
|
106
|
+
this.isLoading = false;
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
*
|
|
112
|
+
*/
|
|
113
|
+
redirect() {
|
|
114
|
+
this.isRedirecting = true;
|
|
115
|
+
const redirectTo = this.isUserRedirect ? '/' : this.redirectTo;
|
|
116
|
+
redirect(redirectTo);
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
</script>
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="!hasActiveUser">
|
|
3
|
+
<p>Please log in before accessing this page.</p>
|
|
4
|
+
<a
|
|
5
|
+
:href="endpoints.login"
|
|
6
|
+
class="btn btn-secondary"
|
|
7
|
+
role="button"
|
|
8
|
+
>
|
|
9
|
+
{{ buttonLabels.login || "Log in" }}
|
|
10
|
+
</a>
|
|
11
|
+
</div>
|
|
12
|
+
<div v-else-if="complete">
|
|
13
|
+
<h4>Almost Done!</h4>
|
|
14
|
+
<p>
|
|
15
|
+
We just sent an email to <em>{{ email }}</em> with your confirmation link.
|
|
16
|
+
To finish changing your email, open the email message and click the
|
|
17
|
+
link within.
|
|
18
|
+
</p>
|
|
19
|
+
<p>You have now been logged out. To continue, click the link in your inbox.</p>
|
|
20
|
+
<p>
|
|
21
|
+
Note: please check your spam/junk folders.
|
|
22
|
+
If you do not receive this email, your firewall or ISP has likely blocked it.
|
|
23
|
+
Please add {{ senderEmailAddress }} to your whitelist and try registering again.
|
|
24
|
+
</p>
|
|
25
|
+
</div>
|
|
26
|
+
<div v-else>
|
|
27
|
+
<form @submit.prevent="handleSubmit">
|
|
28
|
+
<email
|
|
29
|
+
v-model="email"
|
|
30
|
+
:placeholder="activeUser.email"
|
|
31
|
+
:disabled="loading"
|
|
32
|
+
:label="loginEmailLabel"
|
|
33
|
+
/>
|
|
34
|
+
|
|
35
|
+
<small
|
|
36
|
+
v-if="consentPolicyEnabled && consentPolicy"
|
|
37
|
+
class="text-muted mb-1 d-block"
|
|
38
|
+
v-html="consentPolicy"
|
|
39
|
+
/>
|
|
40
|
+
<button
|
|
41
|
+
type="submit"
|
|
42
|
+
class="btn btn-primary"
|
|
43
|
+
:disabled="loading"
|
|
44
|
+
>
|
|
45
|
+
{{ buttonLabels.continue || "Continue" }}
|
|
46
|
+
</button>
|
|
47
|
+
<p v-if="error" class="mt-3 text-danger">
|
|
48
|
+
An error occurred: {{ error.message }}
|
|
49
|
+
</p>
|
|
50
|
+
</form>
|
|
51
|
+
</div>
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<script>
|
|
55
|
+
import Email from './form/fields/email.vue';
|
|
56
|
+
|
|
57
|
+
import post from './utils/post';
|
|
58
|
+
import cookiesEnabled from './utils/cookies-enabled';
|
|
59
|
+
import FormError from './errors/form';
|
|
60
|
+
import FeatureError from './errors/feature';
|
|
61
|
+
import EventEmitter from './mixins/global-event-emitter';
|
|
62
|
+
|
|
63
|
+
export default {
|
|
64
|
+
/**
|
|
65
|
+
*
|
|
66
|
+
*/
|
|
67
|
+
components: {
|
|
68
|
+
Email,
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
*
|
|
73
|
+
*/
|
|
74
|
+
mixins: [EventEmitter],
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
*
|
|
78
|
+
*/
|
|
79
|
+
props: {
|
|
80
|
+
activeUser: {
|
|
81
|
+
type: Object,
|
|
82
|
+
default: () => {},
|
|
83
|
+
},
|
|
84
|
+
endpoints: {
|
|
85
|
+
type: Object,
|
|
86
|
+
required: true,
|
|
87
|
+
},
|
|
88
|
+
buttonLabels: {
|
|
89
|
+
type: Object,
|
|
90
|
+
default: () => ({
|
|
91
|
+
continue: 'Continue',
|
|
92
|
+
login: 'Log in',
|
|
93
|
+
}),
|
|
94
|
+
},
|
|
95
|
+
consentPolicy: {
|
|
96
|
+
type: String,
|
|
97
|
+
default: null,
|
|
98
|
+
},
|
|
99
|
+
consentPolicyEnabled: {
|
|
100
|
+
type: Boolean,
|
|
101
|
+
default: false,
|
|
102
|
+
},
|
|
103
|
+
appContextId: {
|
|
104
|
+
type: String,
|
|
105
|
+
default: null,
|
|
106
|
+
},
|
|
107
|
+
senderEmailAddress: {
|
|
108
|
+
type: String,
|
|
109
|
+
default: 'noreply@identity-x.parameter1.com',
|
|
110
|
+
},
|
|
111
|
+
loginEmailLabel: {
|
|
112
|
+
type: String,
|
|
113
|
+
default: 'Email Address',
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
*
|
|
119
|
+
*/
|
|
120
|
+
data: () => ({
|
|
121
|
+
email: null,
|
|
122
|
+
complete: false,
|
|
123
|
+
error: null,
|
|
124
|
+
loading: false,
|
|
125
|
+
}),
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
*
|
|
129
|
+
*/
|
|
130
|
+
computed: {
|
|
131
|
+
/**
|
|
132
|
+
*
|
|
133
|
+
*/
|
|
134
|
+
hasActiveUser() {
|
|
135
|
+
return this.activeUser && this.activeUser.email;
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
*
|
|
141
|
+
*/
|
|
142
|
+
mounted() {
|
|
143
|
+
if (cookiesEnabled()) {
|
|
144
|
+
this.emit('change-email-mounted');
|
|
145
|
+
} else {
|
|
146
|
+
this.error = new FeatureError('Your browser does not support cookies. Please enable cookies to use this feature.');
|
|
147
|
+
this.emit('change-email-errored', { message: this.error.message });
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
*
|
|
153
|
+
*/
|
|
154
|
+
methods: {
|
|
155
|
+
/**
|
|
156
|
+
*
|
|
157
|
+
*/
|
|
158
|
+
async handleSubmit() {
|
|
159
|
+
try {
|
|
160
|
+
this.error = null;
|
|
161
|
+
this.loading = true;
|
|
162
|
+
const res = await post('/change-email/initiate', {
|
|
163
|
+
email: this.email,
|
|
164
|
+
appContextId: this.appContextId,
|
|
165
|
+
});
|
|
166
|
+
const data = await res.json();
|
|
167
|
+
if (!res.ok) throw new FormError(data.message, res.status);
|
|
168
|
+
this.complete = true;
|
|
169
|
+
this.emit('change-email-link-sent', { data, email: this.email }, data.entity);
|
|
170
|
+
} catch (e) {
|
|
171
|
+
this.error = e;
|
|
172
|
+
this.emit('change-email-errored', { message: e.message });
|
|
173
|
+
} finally {
|
|
174
|
+
this.loading = false;
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
</script>
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<form :class="blockName" @submit.prevent="handleSubmit">
|
|
3
|
+
<fieldset :disabled="isLoading">
|
|
4
|
+
<display-name v-model="currentDisplayName" label="Posting As" />
|
|
5
|
+
<comment-body v-model="body" />
|
|
6
|
+
<button
|
|
7
|
+
type="submit"
|
|
8
|
+
class="btn btn-primary"
|
|
9
|
+
>
|
|
10
|
+
Submit
|
|
11
|
+
</button>
|
|
12
|
+
</fieldset>
|
|
13
|
+
<p v-if="error" class="mb-0 mt-3">
|
|
14
|
+
Error: {{ error.message }}
|
|
15
|
+
</p>
|
|
16
|
+
</form>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script>
|
|
20
|
+
import post from '../utils/post';
|
|
21
|
+
import FormError from '../errors/form';
|
|
22
|
+
import DisplayName from '../form/fields/display-name.vue';
|
|
23
|
+
import CommentBody from '../form/fields/comment-body.vue';
|
|
24
|
+
import EventEmitter from '../mixins/global-event-emitter';
|
|
25
|
+
|
|
26
|
+
export default {
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
*/
|
|
30
|
+
components: { DisplayName, CommentBody },
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
*
|
|
34
|
+
*/
|
|
35
|
+
mixins: [EventEmitter],
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
*
|
|
39
|
+
*/
|
|
40
|
+
props: {
|
|
41
|
+
stream: {
|
|
42
|
+
type: Object,
|
|
43
|
+
required: true,
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
displayName: {
|
|
47
|
+
type: String,
|
|
48
|
+
required: true,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
*
|
|
54
|
+
*/
|
|
55
|
+
data: () => ({
|
|
56
|
+
blockName: 'idx-create-comment',
|
|
57
|
+
isLoading: false,
|
|
58
|
+
error: null,
|
|
59
|
+
body: '',
|
|
60
|
+
updatedDisplayName: undefined,
|
|
61
|
+
}),
|
|
62
|
+
|
|
63
|
+
computed: {
|
|
64
|
+
/**
|
|
65
|
+
*
|
|
66
|
+
*/
|
|
67
|
+
currentDisplayName: {
|
|
68
|
+
get() {
|
|
69
|
+
return this.updatedDisplayName || this.displayName;
|
|
70
|
+
},
|
|
71
|
+
set(displayName) {
|
|
72
|
+
this.updatedDisplayName = displayName;
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
*
|
|
79
|
+
*/
|
|
80
|
+
methods: {
|
|
81
|
+
/**
|
|
82
|
+
*
|
|
83
|
+
*/
|
|
84
|
+
async handleSubmit() {
|
|
85
|
+
this.error = null;
|
|
86
|
+
this.isLoading = true;
|
|
87
|
+
const { currentDisplayName, body, stream } = this;
|
|
88
|
+
try {
|
|
89
|
+
const res = await post('/comment', {
|
|
90
|
+
displayName: currentDisplayName,
|
|
91
|
+
body,
|
|
92
|
+
stream,
|
|
93
|
+
});
|
|
94
|
+
const data = await res.json();
|
|
95
|
+
if (!res.ok) throw new FormError(data.message, res.status);
|
|
96
|
+
this.body = '';
|
|
97
|
+
this.emit('comment-post-submitted');
|
|
98
|
+
} catch (e) {
|
|
99
|
+
this.error = e;
|
|
100
|
+
this.emit('comment-post-errored', { message: e.message });
|
|
101
|
+
} finally {
|
|
102
|
+
this.isLoading = false;
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
</script>
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="blockName" :data-id="id">
|
|
3
|
+
<div :class="element('header')">
|
|
4
|
+
<div :class="element('display-name')">
|
|
5
|
+
<span>Posted by {{ displayName }}</span>
|
|
6
|
+
</div>
|
|
7
|
+
<div>
|
|
8
|
+
<span :class="element('created-at')">
|
|
9
|
+
{{ postedAt }}
|
|
10
|
+
</span>
|
|
11
|
+
<span v-if="hasActiveUser && !flagged">
|
|
12
|
+
<a
|
|
13
|
+
href="#report-post"
|
|
14
|
+
title="Report post as inappropriate."
|
|
15
|
+
:disabled="isReporting"
|
|
16
|
+
@click.prevent="reportComment"
|
|
17
|
+
>
|
|
18
|
+
Report
|
|
19
|
+
</a>
|
|
20
|
+
<span v-if="isReporting">Reporting...</span>
|
|
21
|
+
<span v-if="error" class="text-danger">Error, try again</span>
|
|
22
|
+
</span>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
<div :class="element('body')">
|
|
26
|
+
<p v-if="flagged" :class="element('flagged')">
|
|
27
|
+
This comment has been reported.
|
|
28
|
+
</p>
|
|
29
|
+
<!-- eslint-disable-next-line -->
|
|
30
|
+
<div v-html="bodyHtml" />
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<script>
|
|
36
|
+
import dayjs from '../dayjs';
|
|
37
|
+
import post from '../utils/post';
|
|
38
|
+
import FormError from '../errors/form';
|
|
39
|
+
import EventEmitter from '../mixins/global-event-emitter';
|
|
40
|
+
|
|
41
|
+
export default {
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
*/
|
|
45
|
+
mixins: [EventEmitter],
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
*
|
|
49
|
+
*/
|
|
50
|
+
props: {
|
|
51
|
+
id: {
|
|
52
|
+
type: String,
|
|
53
|
+
required: true,
|
|
54
|
+
},
|
|
55
|
+
body: {
|
|
56
|
+
type: String,
|
|
57
|
+
required: true,
|
|
58
|
+
},
|
|
59
|
+
displayName: {
|
|
60
|
+
type: String,
|
|
61
|
+
required: true,
|
|
62
|
+
},
|
|
63
|
+
createdAt: {
|
|
64
|
+
type: Number,
|
|
65
|
+
required: true,
|
|
66
|
+
},
|
|
67
|
+
approved: {
|
|
68
|
+
type: Boolean,
|
|
69
|
+
default: true,
|
|
70
|
+
},
|
|
71
|
+
flagged: {
|
|
72
|
+
type: Boolean,
|
|
73
|
+
default: false,
|
|
74
|
+
},
|
|
75
|
+
dateFormat: {
|
|
76
|
+
type: String,
|
|
77
|
+
default: 'MMM Do, YYYY h:mma',
|
|
78
|
+
},
|
|
79
|
+
activeUser: {
|
|
80
|
+
type: Object,
|
|
81
|
+
default: () => {},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
*
|
|
87
|
+
*/
|
|
88
|
+
data: () => ({
|
|
89
|
+
blockName: 'idx-comment-post',
|
|
90
|
+
isReporting: false,
|
|
91
|
+
error: null,
|
|
92
|
+
}),
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
*
|
|
96
|
+
*/
|
|
97
|
+
computed: {
|
|
98
|
+
/**
|
|
99
|
+
*
|
|
100
|
+
*/
|
|
101
|
+
postedAt() {
|
|
102
|
+
const { createdAt } = this;
|
|
103
|
+
if (!createdAt) return null;
|
|
104
|
+
return dayjs(createdAt).format(this.dateFormat);
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
*
|
|
109
|
+
*/
|
|
110
|
+
hasActiveUser() {
|
|
111
|
+
return this.activeUser && this.activeUser.email;
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
*
|
|
116
|
+
*/
|
|
117
|
+
bodyHtml() {
|
|
118
|
+
return this.body.replace(/\n/g, '<br>');
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
*
|
|
124
|
+
*/
|
|
125
|
+
methods: {
|
|
126
|
+
/**
|
|
127
|
+
*
|
|
128
|
+
*/
|
|
129
|
+
element(name) {
|
|
130
|
+
return `${this.blockName}__${name}`;
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
async reportComment() {
|
|
134
|
+
if (this.isReporting) return;
|
|
135
|
+
this.error = null;
|
|
136
|
+
this.isReporting = true;
|
|
137
|
+
try {
|
|
138
|
+
const res = await post(`/comment/flag/${this.id}`);
|
|
139
|
+
const data = await res.json();
|
|
140
|
+
if (!res.ok) throw new FormError(data.message, res.status);
|
|
141
|
+
this.emit('comment-report-submitted', { id: this.id });
|
|
142
|
+
} catch (e) {
|
|
143
|
+
this.error = e;
|
|
144
|
+
this.emit('comment-report-errored', { message: e.message, id: this.id });
|
|
145
|
+
} finally {
|
|
146
|
+
this.isReporting = false;
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
</script>
|