mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2026-02-06 09:56:03 +00:00
Implement new modal dialog for decisions, second step
This commit is contained in:
parent
3f4a51eb76
commit
4c85f3690e
@ -27,6 +27,7 @@
|
||||
:id="data.resource.id"
|
||||
:type="data.type"
|
||||
:name="name"
|
||||
:modalData="data.modalData"
|
||||
@close="close"
|
||||
/>
|
||||
<confirm-modal
|
||||
|
||||
@ -8,19 +8,33 @@
|
||||
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<p v-html="message" />
|
||||
<ds-radio
|
||||
<!-- Wolle <ds-radio
|
||||
v-model="form.reasonCategory"
|
||||
:schema="formSchema.reasonCategory"
|
||||
:label="$t('report.reason.category.label')"
|
||||
:options="form.reasonCategoryOptions"
|
||||
labelProp="label"
|
||||
/>
|
||||
/> -->
|
||||
<ds-text class="ds-text-soft">
|
||||
{{ $t('moderation.reports.decideModal.reason.category.label') }}
|
||||
</ds-text>
|
||||
<ds-text v-for="(reasonCategory, index) in form.reasonCategoryOptions" :key="index">
|
||||
<input
|
||||
id="checkbox"
|
||||
type="checkbox"
|
||||
v-model="reasonCategory.checked"
|
||||
:checked="reasonCategory.checked"
|
||||
/>
|
||||
|
||||
<label for="checkbox" v-html="reasonCategory.label"></label>
|
||||
</ds-text>
|
||||
<!-- reasonDescription -->
|
||||
<ds-input
|
||||
class="reason-description"
|
||||
class="ds-input-description"
|
||||
v-model="form.reasonDescription"
|
||||
:schema="formSchema.reasonDescription"
|
||||
:label="$t('report.reason.description.label')"
|
||||
:placeholder="$t('report.reason.description.placeholder')"
|
||||
:label="$t('moderation.reports.decideModal.reason.optionalDescription.label')"
|
||||
:placeholder="$t('moderation.reports.decideModal.reason.optionalDescription.placeholder')"
|
||||
type="textarea"
|
||||
rows="5"
|
||||
/>
|
||||
@ -28,21 +42,40 @@
|
||||
{{ form.reasonDescription.length }}/{{ formSchema.reasonDescription.max }}
|
||||
</small>
|
||||
<ds-space />
|
||||
<!-- internalDescription -->
|
||||
<ds-input
|
||||
class="ds-input-description"
|
||||
v-model="form.internalDescription"
|
||||
:schema="formSchema.internalDescription"
|
||||
:label="$t('moderation.reports.decideModal.reason.internalDescription.label')"
|
||||
:placeholder="$t('moderation.reports.decideModal.reason.internalDescription.placeholder')"
|
||||
type="textarea"
|
||||
rows="5"
|
||||
/>
|
||||
<small class="smallTag">
|
||||
{{ form.internalDescription.length }}/{{ formSchema.internalDescription.max }}
|
||||
</small>
|
||||
<ds-space />
|
||||
<template #footer>
|
||||
<base-button class="cancel" icon="close" @click="cancel">
|
||||
{{ $t('report.cancel') }}
|
||||
<base-button
|
||||
class="cancel"
|
||||
:danger="!modalData.buttons.confirm.danger"
|
||||
:icon="modalData.buttons.cancel.icon"
|
||||
@click="cancel"
|
||||
>
|
||||
{{ $t(modalData.buttons.cancel.textIdent) }}
|
||||
</base-button>
|
||||
|
||||
<base-button
|
||||
danger
|
||||
:danger="modalData.buttons.confirm.danger"
|
||||
filled
|
||||
class="confirm"
|
||||
icon="exclamation-circle"
|
||||
:disabled="!form.reasonCategory"
|
||||
:icon="modalData.buttons.confirm.icon"
|
||||
:disabled="!isReasonCategoryChecked"
|
||||
:loading="loading"
|
||||
@click="confirm"
|
||||
>
|
||||
{{ $t('report.submit') }}
|
||||
{{ $t(modalData.buttons.confirm.textIdent) }}
|
||||
</base-button>
|
||||
</template>
|
||||
</ds-modal>
|
||||
@ -50,9 +83,9 @@
|
||||
|
||||
<script>
|
||||
import { SweetalertIcon } from 'vue-sweetalert-icons'
|
||||
import { reportMutation } from '~/graphql/Moderation.js'
|
||||
// Wolle import { reportMutation } from '~/graphql/Moderation.js'
|
||||
import { valuesReasonCategoryOptions } from '~/constants/modals.js'
|
||||
import validReport from '~/components/utils/ReportModal'
|
||||
import validReport from '~/components/utils/DecideModal'
|
||||
|
||||
export default {
|
||||
name: 'DecideModal',
|
||||
@ -62,6 +95,7 @@ export default {
|
||||
props: {
|
||||
name: { type: String, default: '' },
|
||||
type: { type: String, required: true },
|
||||
modalData: { type: Object, required: true },
|
||||
id: { type: String, required: true },
|
||||
},
|
||||
data() {
|
||||
@ -70,9 +104,10 @@ export default {
|
||||
success: false,
|
||||
loading: false,
|
||||
form: {
|
||||
reasonCategory: null,
|
||||
// Wolle reasonCategory: null,
|
||||
reasonCategoryOptions: [],
|
||||
reasonDescription: '',
|
||||
internalDescription: '',
|
||||
},
|
||||
}
|
||||
},
|
||||
@ -81,16 +116,23 @@ export default {
|
||||
return {
|
||||
label: this.$t('report.reason.category.options.' + reasonCategory),
|
||||
value: reasonCategory,
|
||||
checked: false,
|
||||
}
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
// Wolle title() {
|
||||
// return this.$t(`report.${this.type}.title`)
|
||||
// },
|
||||
// message() {
|
||||
// const name = this.$filters.truncate(this.name, 30)
|
||||
// return this.$t(`report.${this.type}.message`, { name })
|
||||
// },
|
||||
title() {
|
||||
return this.$t(`report.${this.type}.title`)
|
||||
return this.$t(this.modalData.titleIdent)
|
||||
},
|
||||
message() {
|
||||
const name = this.$filters.truncate(this.name, 30)
|
||||
return this.$t(`report.${this.type}.message`, { name })
|
||||
return this.$t(this.modalData.messageIdent, this.modalData.messageParams)
|
||||
},
|
||||
formSchema() {
|
||||
const validReportSchema = validReport({ translate: this.$t })
|
||||
@ -98,61 +140,113 @@ export default {
|
||||
...validReportSchema.formSchema,
|
||||
}
|
||||
},
|
||||
isReasonCategoryChecked() {
|
||||
return this.form.reasonCategoryOptions.find(el => el.checked)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// Wolle async cancel() {
|
||||
// // TODO: Use the "modalData" structure introduced in "ConfirmModal" and refactor this here. Be aware that all the Jest tests have to be refactored as well !!!
|
||||
// // await this.modalData.buttons.cancel.callback()
|
||||
// this.isOpen = false
|
||||
// setTimeout(() => {
|
||||
// this.$emit('close')
|
||||
// }, 1000)
|
||||
// },
|
||||
async cancel() {
|
||||
// TODO: Use the "modalData" structure introduced in "ConfirmModal" and refactor this here. Be aware that all the Jest tests have to be refactored as well !!!
|
||||
// await this.modalData.buttons.cancel.callback()
|
||||
await this.modalData.buttons.cancel.callback()
|
||||
this.isOpen = false
|
||||
setTimeout(() => {
|
||||
this.$emit('close')
|
||||
}, 1000)
|
||||
},
|
||||
// Wolle async confirm() {
|
||||
// const { reasonCategory, reasonDescription } = this.form
|
||||
// this.loading = true
|
||||
// // TODO: Use the "modalData" structure introduced in "ConfirmModal" and refactor this here. Be aware that all the Jest tests have to be refactored as well !!!
|
||||
// // await this.modalData.buttons.confirm.callback()
|
||||
// this.$apollo
|
||||
// .mutate({
|
||||
// mutation: reportMutation(),
|
||||
// variables: {
|
||||
// resourceId: this.id,
|
||||
// reasonCategory: reasonCategory.value,
|
||||
// reasonDescription,
|
||||
// },
|
||||
// })
|
||||
// .then(({ _data }) => {
|
||||
// this.success = true
|
||||
// this.$toast.success(this.$t('report.success'))
|
||||
// setTimeout(() => {
|
||||
// this.isOpen = false
|
||||
// setTimeout(() => {
|
||||
// this.success = false
|
||||
// this.$emit('close')
|
||||
// }, 500)
|
||||
// }, 1500)
|
||||
// this.loading = false
|
||||
// })
|
||||
// .catch(err => {
|
||||
// this.$emit('close')
|
||||
// this.success = false
|
||||
// switch (err.message) {
|
||||
// case 'GraphQL error: User':
|
||||
// this.$toast.error(this.$t('report.user.error'))
|
||||
// break
|
||||
// case 'GraphQL error: Post':
|
||||
// this.$toast.error(this.$t('report.contribution.error'))
|
||||
// break
|
||||
// case 'GraphQL error: Comment':
|
||||
// this.$toast.error(this.$t('report.comment.error'))
|
||||
// break
|
||||
// default:
|
||||
// this.$toast.error(err.message)
|
||||
// }
|
||||
// this.isOpen = false
|
||||
// this.loading = false
|
||||
// })
|
||||
// },
|
||||
async confirm() {
|
||||
const { reasonCategory, reasonDescription } = this.form
|
||||
this.loading = true
|
||||
// TODO: Use the "modalData" structure introduced in "ConfirmModal" and refactor this here. Be aware that all the Jest tests have to be refactored as well !!!
|
||||
// await this.modalData.buttons.confirm.callback()
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: reportMutation(),
|
||||
variables: {
|
||||
resourceId: this.id,
|
||||
reasonCategory: reasonCategory.value,
|
||||
reasonDescription,
|
||||
},
|
||||
try {
|
||||
await this.modalData.buttons.confirm.callback({
|
||||
reasonCategoryAry: this.form.reasonCategoryOptions
|
||||
.filter(el => el.checked)
|
||||
.map(el => el.value),
|
||||
reasonDescription: this.form.reasonDescription,
|
||||
})
|
||||
.then(({ _data }) => {
|
||||
this.success = true
|
||||
this.$toast.success(this.$t('report.success'))
|
||||
setTimeout(() => {
|
||||
this.isOpen = false
|
||||
setTimeout(() => {
|
||||
this.success = false
|
||||
this.$emit('close')
|
||||
}, 500)
|
||||
}, 1500)
|
||||
this.loading = false
|
||||
})
|
||||
.catch(err => {
|
||||
this.$emit('close')
|
||||
this.success = false
|
||||
switch (err.message) {
|
||||
case 'GraphQL error: User':
|
||||
this.$toast.error(this.$t('report.user.error'))
|
||||
break
|
||||
case 'GraphQL error: Post':
|
||||
this.$toast.error(this.$t('report.contribution.error'))
|
||||
break
|
||||
case 'GraphQL error: Comment':
|
||||
this.$toast.error(this.$t('report.comment.error'))
|
||||
break
|
||||
default:
|
||||
this.$toast.error(err.message)
|
||||
}
|
||||
this.success = true
|
||||
setTimeout(() => {
|
||||
this.isOpen = false
|
||||
this.loading = false
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.success = false
|
||||
this.$emit('close')
|
||||
}, 500)
|
||||
}, 1500)
|
||||
} catch (err) {
|
||||
this.success = false
|
||||
this.$emit('close')
|
||||
switch (err.message) {
|
||||
// Wolle actualise
|
||||
case 'GraphQL error: User':
|
||||
this.$toast.error(this.$t('report.user.error'))
|
||||
break
|
||||
// Wolle actualise
|
||||
case 'GraphQL error: Post':
|
||||
this.$toast.error(this.$t('report.contribution.error'))
|
||||
break
|
||||
// Wolle actualise
|
||||
case 'GraphQL error: Comment':
|
||||
this.$toast.error(this.$t('report.comment.error'))
|
||||
break
|
||||
default:
|
||||
this.$toast.error(err.message)
|
||||
}
|
||||
this.isOpen = false
|
||||
this.loading = false
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -160,7 +254,7 @@ export default {
|
||||
|
||||
<style lang="scss">
|
||||
.ds-modal {
|
||||
max-width: 600px !important;
|
||||
max-width: 700px !important;
|
||||
}
|
||||
.ds-radio-option {
|
||||
width: 100% !important;
|
||||
@ -169,7 +263,10 @@ export default {
|
||||
margin: 5px 20px 5px 5px !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
.reason-description {
|
||||
.ds-text-soft {
|
||||
color: $text-color-soft;
|
||||
}
|
||||
.ds-input-description {
|
||||
margin-top: $space-x-small !important;
|
||||
margin-bottom: $space-xx-small !important;
|
||||
}
|
||||
|
||||
@ -81,8 +81,8 @@ export default {
|
||||
danger: true,
|
||||
icon: report.resource.disabled ? 'eye-slash' : 'eye',
|
||||
textIdent: 'moderation.reports.decideModal.submit',
|
||||
callback: () => {
|
||||
this.confirmCallback(report.resource)
|
||||
callback: decisionReasonData => {
|
||||
this.confirmCallback(report.resource, decisionReasonData)
|
||||
},
|
||||
},
|
||||
cancel: {
|
||||
@ -115,8 +115,10 @@ export default {
|
||||
this.closed = null
|
||||
this.reviewed = option.value.reviewed
|
||||
},
|
||||
async confirmCallback(resource) {
|
||||
async confirmCallback(resource, decisionReasonData) {
|
||||
console.log('decisionReasonData: ', decisionReasonData)
|
||||
const { disabled: disable, id: resourceId } = resource
|
||||
// Wolle decisionReasonData properties into the mutation !!!
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: reviewMutation(),
|
||||
|
||||
30
webapp/components/utils/DecideModal.js
Normal file
30
webapp/components/utils/DecideModal.js
Normal file
@ -0,0 +1,30 @@
|
||||
// Wolle import { valuesReasonCategoryOptions } from '~/constants/modals.js'
|
||||
|
||||
export default function validReport({ translate }) {
|
||||
return {
|
||||
formSchema: {
|
||||
// Wolle reasonCategory: {
|
||||
// type: 'object',
|
||||
// required: true,
|
||||
// fields: {
|
||||
// value: {
|
||||
// type: 'enum',
|
||||
// enum: valuesReasonCategoryOptions,
|
||||
// required: true,
|
||||
// message: translate('report.reason.category.invalid'),
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
reasonDescription: {
|
||||
type: 'string',
|
||||
min: 0,
|
||||
max: 200,
|
||||
},
|
||||
internalDescription: {
|
||||
type: 'string',
|
||||
min: 0,
|
||||
max: 200,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
37
webapp/components/utils/DecideModal.spec.js
Normal file
37
webapp/components/utils/DecideModal.spec.js
Normal file
@ -0,0 +1,37 @@
|
||||
// Wolle implement
|
||||
import validReport from './DecideModal'
|
||||
import Schema from 'async-validator'
|
||||
|
||||
let translate
|
||||
|
||||
beforeEach(() => {
|
||||
translate = jest.fn(() => 'Validation error')
|
||||
})
|
||||
|
||||
describe('validReport', () => {
|
||||
const validate = object => {
|
||||
const { formSchema } = validReport({ translate })
|
||||
const validator = new Schema(formSchema)
|
||||
return validator.validate(object, { suppressWarning: true }).catch(({ errors }) => {
|
||||
throw new Error(errors[0].message)
|
||||
})
|
||||
}
|
||||
|
||||
describe('reasonCategory', () => {
|
||||
describe('invalid enum', () => {
|
||||
it('rejects', async () => {
|
||||
await expect(validate({ reasonCategory: { value: 'invalid_enum' } })).rejects.toThrow(
|
||||
'Validation error',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('valid enum', () => {
|
||||
it('resolves', async () => {
|
||||
await expect(
|
||||
validate({ reasonCategory: { value: 'discrimination_etc' } }),
|
||||
).resolves.toBeUndefined()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -388,7 +388,20 @@
|
||||
"title": "Entsperre den Kommentar abschließend",
|
||||
"message": "Möchtest du den Kommentar \"<b>{name}</b>\" wirklich <b>entsperrt</b> lassen?"
|
||||
}
|
||||
}
|
||||
},
|
||||
"reason": {
|
||||
"category": {
|
||||
"label": "Wähle Kategorien:"
|
||||
},
|
||||
"optionalDescription": {
|
||||
"label": "Bitte erkläre dem betroffenen Benutzer: Warum entscheidest du so?",
|
||||
"placeholder": "Optionale erklärende Informationen …"
|
||||
},
|
||||
"internalDescription": {
|
||||
"label": "Notizen für Moderatoren:",
|
||||
"placeholder": "Zusätzliche interne Informationen …"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -567,6 +567,19 @@
|
||||
"title": "Finally Enable Comment",
|
||||
"message": "Do you really want to let the comment \"<b>{name}</b>\" stay <b>enabled</b>?"
|
||||
}
|
||||
},
|
||||
"reason": {
|
||||
"category": {
|
||||
"label": "Select categories:"
|
||||
},
|
||||
"optionalDescription": {
|
||||
"label": "Please explain to the affected user: Why you decide this way?",
|
||||
"placeholder": "Optional explaining information …"
|
||||
},
|
||||
"internalDescription": {
|
||||
"label": "Notice to moderators:",
|
||||
"placeholder": "Additional internal information …"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user