Move submit button for admin connection editor to each card to match the other admin forms
This commit is contained in:
@@ -1,100 +1,99 @@
|
||||
<template>
|
||||
<b-card
|
||||
:title="$t('title')"
|
||||
footer-bg-variant="white"
|
||||
footer-class="d-flex flex-wrap flex-fill-child gap-1"
|
||||
class="shadow-sm"
|
||||
>
|
||||
<b-container
|
||||
v-if="canManage"
|
||||
<b-row
|
||||
v-if="issues.length"
|
||||
>
|
||||
<b-row
|
||||
v-if="issues.length"
|
||||
<b-col
|
||||
cols="12"
|
||||
>
|
||||
<b-col
|
||||
cols="12"
|
||||
<b-form-group
|
||||
:label="$t('connectivity-issues')"
|
||||
label-class="text-primary"
|
||||
>
|
||||
<b-form-group
|
||||
:label="$t('connectivity-issues')"
|
||||
label-class="text-primary"
|
||||
<b-alert
|
||||
v-for="issue in issues"
|
||||
:key="issue.issue"
|
||||
show
|
||||
variant="danger"
|
||||
>
|
||||
<b-alert
|
||||
v-for="issue in issues"
|
||||
:key="issue.issue"
|
||||
show
|
||||
variant="danger"
|
||||
>
|
||||
{{ issue.issue }}
|
||||
</b-alert>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col
|
||||
cols="12"
|
||||
lg="12"
|
||||
>
|
||||
<b-form-group
|
||||
:label="$t('form.model-ident.label')"
|
||||
:description="$t('form.model-ident.description', { interpolation: { prefix: '{{{', suffix: '}}}' } })"
|
||||
label-class="text-primary"
|
||||
>
|
||||
<b-form-input
|
||||
v-model="dal.modelIdent"
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('form.model-ident.placeholder')"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col
|
||||
cols="12"
|
||||
lg="12"
|
||||
>
|
||||
<b-form-group
|
||||
:label="$t('form.type.label')"
|
||||
:description="$t('form.type.description')"
|
||||
label-class="text-primary"
|
||||
>
|
||||
<b-form-input
|
||||
v-model="dal.type"
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('form.type.placeholder')"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col
|
||||
cols="12"
|
||||
lg="12"
|
||||
>
|
||||
<b-form-group
|
||||
:label="$t('form.params.label')"
|
||||
:description="$t('form.params.description')"
|
||||
label-class="text-primary"
|
||||
>
|
||||
<b-form-textarea
|
||||
v-model="paramsJson"
|
||||
:disabled="disabled"
|
||||
:class="paramsJsonEditorClass"
|
||||
:placeholder="$t('form.params.placeholder')"
|
||||
rows="5"
|
||||
@blur="processParamsJSON"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-container>
|
||||
<b-container
|
||||
v-else
|
||||
>
|
||||
<b-alert
|
||||
variant="warning"
|
||||
show
|
||||
{{ issue.issue }}
|
||||
</b-alert>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col
|
||||
cols="12"
|
||||
lg="12"
|
||||
>
|
||||
{{ $t('no-access-warning') }}
|
||||
</b-alert>
|
||||
</b-container>
|
||||
<b-form-group
|
||||
:label="$t('form.model-ident.label')"
|
||||
:description="$t('form.model-ident.description', { interpolation: { prefix: '{{{', suffix: '}}}' } })"
|
||||
label-class="text-primary"
|
||||
>
|
||||
<b-form-input
|
||||
v-model="dal.modelIdent"
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('form.model-ident.placeholder')"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col
|
||||
cols="12"
|
||||
lg="12"
|
||||
>
|
||||
<b-form-group
|
||||
:label="$t('form.type.label')"
|
||||
:description="$t('form.type.description')"
|
||||
label-class="text-primary"
|
||||
>
|
||||
<b-form-input
|
||||
v-model="dal.type"
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('form.type.placeholder')"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col
|
||||
cols="12"
|
||||
lg="12"
|
||||
>
|
||||
<b-form-group
|
||||
:label="$t('form.params.label')"
|
||||
:description="$t('form.params.description')"
|
||||
label-class="text-primary"
|
||||
>
|
||||
<b-form-textarea
|
||||
v-model="paramsJson"
|
||||
:disabled="disabled"
|
||||
:class="paramsJsonEditorClass"
|
||||
:placeholder="$t('form.params.placeholder')"
|
||||
rows="5"
|
||||
@blur="processParamsJSON"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
<template #footer>
|
||||
<c-button-submit
|
||||
:disabled="disabled"
|
||||
:processing="processing"
|
||||
:success="success"
|
||||
:text="$t('admin:general.label.submit')"
|
||||
class="ml-auto"
|
||||
@submit="$emit('submit')"
|
||||
/>
|
||||
</template>
|
||||
</b-card>
|
||||
</template>
|
||||
|
||||
@@ -108,7 +107,6 @@ export default {
|
||||
|
||||
props: {
|
||||
disabled: { type: Boolean, default: false },
|
||||
canManage: { type: Boolean, default: false },
|
||||
|
||||
dal: {
|
||||
type: Object,
|
||||
@@ -119,6 +117,16 @@ export default {
|
||||
type: Array,
|
||||
default: () => ([]),
|
||||
},
|
||||
|
||||
processing: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
|
||||
success: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
|
||||
data () {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
<b-card
|
||||
data-test-id="card-connection-settings"
|
||||
:title="$t('title')"
|
||||
footer-bg-variant="white"
|
||||
footer-class="d-flex flex-wrap flex-fill-child gap-1"
|
||||
class="shadow-sm"
|
||||
>
|
||||
<b-row>
|
||||
@@ -18,7 +20,6 @@
|
||||
<b-form-input
|
||||
v-model="connection.meta.name"
|
||||
required
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('form.name.placeholder')"
|
||||
:state="nameState"
|
||||
/>
|
||||
@@ -60,7 +61,6 @@
|
||||
>
|
||||
<b-form-input
|
||||
v-model="connection.meta.location.properties.name"
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('form.location-name.placeholder')"
|
||||
/>
|
||||
</b-form-group>
|
||||
@@ -117,7 +117,6 @@
|
||||
>
|
||||
<b-form-input
|
||||
v-model="connection.meta.ownership"
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('form.ownership.placeholder')"
|
||||
/>
|
||||
</b-form-group>
|
||||
@@ -135,18 +134,37 @@
|
||||
<c-sensitivity-level-picker
|
||||
v-model="connection.config.privacy.sensitivityLevelID"
|
||||
:options="sensitivityLevels"
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('form.sensitivity-level.placeholder')"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
<template #footer>
|
||||
<confirmation-toggle
|
||||
v-if="!fresh && !isPrimary && !disabled"
|
||||
@confirmed="$emit('delete')"
|
||||
>
|
||||
{{ connection.deletedAt ? $t('general:label.undelete') : $t('general:label.delete') }}
|
||||
</confirmation-toggle>
|
||||
|
||||
<c-button-submit
|
||||
:disabled="disabled || saveDisabled"
|
||||
:processing="processing"
|
||||
:success="success"
|
||||
:text="$t('admin:general.label.submit')"
|
||||
class="ml-auto"
|
||||
@submit="$emit('submit')"
|
||||
/>
|
||||
</template>
|
||||
</b-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { NoID } from '@cortezaproject/corteza-js'
|
||||
import { components, handle } from '@cortezaproject/corteza-vue'
|
||||
import CLocation from 'corteza-webapp-admin/src/components/CLocation'
|
||||
import ConfirmationToggle from 'corteza-webapp-admin/src/components/ConfirmationToggle'
|
||||
const { CSensitivityLevelPicker } = components
|
||||
|
||||
export default {
|
||||
@@ -158,12 +176,10 @@ export default {
|
||||
components: {
|
||||
CLocation,
|
||||
CSensitivityLevelPicker,
|
||||
ConfirmationToggle,
|
||||
},
|
||||
|
||||
props: {
|
||||
disabled: { type: Boolean, default: false },
|
||||
isPrimary: { type: Boolean, required: true },
|
||||
|
||||
connection: {
|
||||
type: Object,
|
||||
required: true,
|
||||
@@ -173,9 +189,41 @@ export default {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
|
||||
processing: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
|
||||
success: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
|
||||
canCreate: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
isPrimary () {
|
||||
return this.connection.type === 'corteza::system:primary-dal-connection'
|
||||
},
|
||||
|
||||
fresh () {
|
||||
return !this.connection.connectionID || this.connection.connectionID === NoID
|
||||
},
|
||||
|
||||
editable () {
|
||||
return this.fresh ? this.canCreate : true
|
||||
},
|
||||
|
||||
nameState () {
|
||||
return this.connection.meta.name ? null : false
|
||||
},
|
||||
@@ -184,6 +232,10 @@ export default {
|
||||
return handle.handleState(this.connection.handle)
|
||||
},
|
||||
|
||||
saveDisabled () {
|
||||
return !this.editable || [this.nameState, this.handleState].includes(false)
|
||||
},
|
||||
|
||||
locationCoordinates () {
|
||||
const { coordinates: cc } = this.connection.meta.location.geometry
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<template>
|
||||
<b-card
|
||||
:title="$t('title')"
|
||||
footer-bg-variant="white"
|
||||
footer-class="d-flex flex-wrap flex-fill-child gap-1"
|
||||
class="shadow-sm"
|
||||
>
|
||||
<b-row
|
||||
@@ -10,7 +12,6 @@
|
||||
<b-col cols="12">
|
||||
<b-form-checkbox
|
||||
v-model="properties[prop].enabled"
|
||||
:disabled="disabled"
|
||||
class="mb-1"
|
||||
>
|
||||
{{ $t('form.' + kebabCase(prop) + '.checkbox.label') }}
|
||||
@@ -24,11 +25,21 @@
|
||||
>
|
||||
<b-form-textarea
|
||||
v-model="properties[prop].notes"
|
||||
:disabled="disabled"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
<template #footer>
|
||||
<c-button-submit
|
||||
:disabled="disabled"
|
||||
:processing="processing"
|
||||
:success="success"
|
||||
:text="$t('admin:general.label.submit')"
|
||||
class="ml-auto"
|
||||
@submit="$emit('submit')"
|
||||
/>
|
||||
</template>
|
||||
</b-card>
|
||||
</template>
|
||||
<script>
|
||||
@@ -41,12 +52,25 @@ export default {
|
||||
},
|
||||
|
||||
props: {
|
||||
disabled: { type: Boolean, default: false },
|
||||
|
||||
properties: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
|
||||
processing: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
|
||||
success: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
|
||||
data () {
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
v-if="connection"
|
||||
data-test-id="button-edit"
|
||||
size="sm"
|
||||
variant="link"
|
||||
variant="outline-light"
|
||||
class="d-flex align-items-center text-primary border-0"
|
||||
:to="{ name: 'system.connection.edit', params: { connectionID: (connection || {}).connectionID } }"
|
||||
>
|
||||
<font-awesome-icon
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<b-card
|
||||
class="shadow-sm"
|
||||
data-test-id="card-user-info"
|
||||
header-bg-variant="white"
|
||||
footer-bg-variant="white"
|
||||
footer-class="d-flex flex-wrap flex-fill-child gap-1"
|
||||
class="shadow-sm"
|
||||
>
|
||||
<b-form
|
||||
@submit.prevent="$emit('submit', user)"
|
||||
|
||||
@@ -13,58 +13,42 @@
|
||||
<c-connection-editor-info
|
||||
:connection="connection"
|
||||
:sensitivity-levels="sensitivityLevels"
|
||||
:processing="info.processing"
|
||||
:success="info.success"
|
||||
:can-create="canCreate"
|
||||
:disabled="disabled"
|
||||
:is-primary="isPrimary"
|
||||
@submit="updateInfo"
|
||||
@delete="toggleDelete"
|
||||
/>
|
||||
|
||||
<c-connection-editor-properties
|
||||
v-if="connectionID && connection.meta.properties"
|
||||
:properties="connection.meta.properties"
|
||||
:disabled="disabled"
|
||||
:processing="properties.processing"
|
||||
:success="properties.success"
|
||||
class="mt-4"
|
||||
@submit="updateProperties"
|
||||
/>
|
||||
|
||||
<c-connection-editor-dal
|
||||
v-if="connection.config.dal"
|
||||
v-if="connectionID && connection.config.dal && canManage"
|
||||
:dal="connection.config.dal"
|
||||
:issues="connection.issues || []"
|
||||
:disabled="disabled"
|
||||
:can-manage="connection.canManageDalConfig"
|
||||
class="mt-4"
|
||||
@submit="updateDal"
|
||||
/>
|
||||
|
||||
<b-card
|
||||
body-class="d-flex flex-wrap flex-fill-child gap-1"
|
||||
class="mt-4"
|
||||
>
|
||||
<confirmation-toggle
|
||||
v-if="connection && connectionID && !isPrimary && !disabled"
|
||||
@confirmed="toggleDelete"
|
||||
>
|
||||
{{ connection.deletedAt ? $t('general:label.undelete') : $t('general:label.delete') }}
|
||||
</confirmation-toggle>
|
||||
|
||||
<c-button-submit
|
||||
:disabled="disabled || saveDisabled"
|
||||
:processing="info.processing"
|
||||
:success="info.success"
|
||||
:text="$t('admin:general.label.submit')"
|
||||
class="ml-auto"
|
||||
@submit="onSubmit"
|
||||
/>
|
||||
</b-card>
|
||||
</b-form>
|
||||
</b-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { isEqual } from 'lodash'
|
||||
import { system, NoID } from '@cortezaproject/corteza-js'
|
||||
import { handle } from '@cortezaproject/corteza-vue'
|
||||
import { system } from '@cortezaproject/corteza-js'
|
||||
import editorHelpers from 'corteza-webapp-admin/src/mixins/editorHelpers'
|
||||
import CConnectionEditorInfo from 'corteza-webapp-admin/src/components/Connection/CConnectionEditorInfo'
|
||||
import CConnectionEditorProperties from 'corteza-webapp-admin/src/components/Connection/CConnectionEditorProperties'
|
||||
import CConnectionEditorDal from 'corteza-webapp-admin/src/components/Connection/CConnectionEditorDAL'
|
||||
import ConfirmationToggle from 'corteza-webapp-admin/src/components/ConfirmationToggle'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
@@ -72,7 +56,6 @@ export default {
|
||||
CConnectionEditorInfo,
|
||||
CConnectionEditorDal,
|
||||
CConnectionEditorProperties,
|
||||
ConfirmationToggle,
|
||||
},
|
||||
|
||||
i18nOptions: {
|
||||
@@ -98,6 +81,16 @@ export default {
|
||||
success: false,
|
||||
},
|
||||
|
||||
properties: {
|
||||
processing: false,
|
||||
success: false,
|
||||
},
|
||||
|
||||
dal: {
|
||||
processing: false,
|
||||
success: false,
|
||||
},
|
||||
|
||||
connection: undefined,
|
||||
initialConnectionState: undefined,
|
||||
|
||||
@@ -114,34 +107,13 @@ export default {
|
||||
return this.can('system/', 'dal-connection.create')
|
||||
},
|
||||
|
||||
isPrimary () {
|
||||
return this.connection.type === 'corteza::system:primary-dal-connection'
|
||||
canManage () {
|
||||
return this.connection.canManageDalConfig
|
||||
},
|
||||
|
||||
disabled () {
|
||||
return this.info.processing
|
||||
return this.info.processing || this.properties.processing || this.dal.processing
|
||||
},
|
||||
|
||||
fresh () {
|
||||
return !this.connection.connectionID || this.connection.connectionID === NoID
|
||||
},
|
||||
|
||||
editable () {
|
||||
return this.fresh ? this.canCreate : true // this.user.canUpdateUser
|
||||
},
|
||||
|
||||
nameState () {
|
||||
return this.connection.meta.name ? null : false
|
||||
},
|
||||
|
||||
handleState () {
|
||||
return handle.handleState(this.connection.handle)
|
||||
},
|
||||
|
||||
saveDisabled () {
|
||||
return !this.editable || [this.nameState, this.handleState].includes(false)
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
beforeRouteUpdate (to, from, next) {
|
||||
@@ -195,7 +167,7 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
onSubmit () {
|
||||
updateInfo () {
|
||||
const updating = !!this.connectionID
|
||||
const op = updating ? 'update' : 'create'
|
||||
const fn = updating ? 'dalConnectionUpdate' : 'dalConnectionCreate'
|
||||
@@ -203,25 +175,88 @@ export default {
|
||||
this.info.processing = true
|
||||
this.incLoader()
|
||||
|
||||
return this.$SystemAPI[fn](this.connection)
|
||||
.then(connection => {
|
||||
const { connectionID } = connection
|
||||
const connection = new system.DalConnection(this.initialConnectionState)
|
||||
connection.meta.name = this.connection.meta.name
|
||||
connection.handle = this.connection.handle
|
||||
connection.meta.location.properties.name = this.connection.meta.location.properties.name
|
||||
connection.meta.location.geometry.coordinates = this.connection.meta.location.geometry.coordinates
|
||||
connection.meta.ownership = this.connection.meta.ownership
|
||||
connection.config.privacy.sensitivityLevelID = this.connection.config.privacy.sensitivityLevelID
|
||||
|
||||
this.animateSuccess('info')
|
||||
this.toastSuccess(this.$t(`notification:connection.${op}.success`))
|
||||
if (!updating) {
|
||||
this.$router.push({ name: `system.connection.edit`, params: { connectionID } })
|
||||
} else {
|
||||
this.connection = new system.DalConnection(connection)
|
||||
this.initialConnectionState = this.connection.clone()
|
||||
}
|
||||
})
|
||||
.catch(this.toastErrorHandler(this.$t(`notification:connection.${op}.error`)))
|
||||
return this.$SystemAPI[fn](connection).then(connection => {
|
||||
this.animateSuccess('info')
|
||||
this.toastSuccess(this.$t(`notification:connection.${op}.success`))
|
||||
|
||||
if (!updating) {
|
||||
const { connectionID } = connection
|
||||
this.$router.push({ name: `system.connection.edit`, params: { connectionID } })
|
||||
} else {
|
||||
connection.config.dal = this.connection.config.dal
|
||||
connection.meta.properties = this.connection.meta.properties
|
||||
|
||||
this.connection = new system.DalConnection(connection)
|
||||
this.initialConnectionState = this.connection.clone()
|
||||
}
|
||||
}).catch(this.toastErrorHandler(this.$t('notification:connection.update.error')))
|
||||
.finally(() => {
|
||||
this.info.processing = false
|
||||
})
|
||||
},
|
||||
|
||||
updateProperties () {
|
||||
this.properties.processing = true
|
||||
this.incLoader()
|
||||
|
||||
const connection = new system.DalConnection(this.initialConnectionState)
|
||||
connection.meta.properties = this.connection.meta.properties
|
||||
|
||||
return this.$SystemAPI.dalConnectionUpdate(connection).then(connection => {
|
||||
this.animateSuccess('properties')
|
||||
this.toastSuccess(this.$t('notification:connection.update.success'))
|
||||
|
||||
connection.meta.name = this.connection.meta.name
|
||||
connection.handle = this.connection.handle
|
||||
connection.meta.location.properties.name = this.connection.meta.location.properties.name
|
||||
connection.meta.location.geometry.coordinates = this.connection.meta.location.geometry.coordinates
|
||||
connection.meta.ownership = this.connection.meta.ownership
|
||||
connection.config.privacy.sensitivityLevelID = this.connection.config.privacy.sensitivityLevelID
|
||||
connection.config.dal = this.connection.config.dal
|
||||
|
||||
this.connection = new system.DalConnection(connection)
|
||||
this.initialConnectionState = this.connection.clone()
|
||||
}).catch(this.toastErrorHandler(this.$t('notification:connection.update.error')))
|
||||
.finally(() => {
|
||||
this.properties.processing = false
|
||||
})
|
||||
},
|
||||
|
||||
updateDal () {
|
||||
this.dal.processing = true
|
||||
this.incLoader()
|
||||
|
||||
const connection = new system.DalConnection(this.initialConnectionState)
|
||||
connection.config.dal = this.connection.config.dal
|
||||
|
||||
return this.$SystemAPI.dalConnectionUpdate(connection).then(connection => {
|
||||
this.animateSuccess('dal')
|
||||
this.toastSuccess(this.$t('notification:connection.update.success'))
|
||||
|
||||
connection.meta.name = this.connection.meta.name
|
||||
connection.handle = this.connection.handle
|
||||
connection.meta.location.properties.name = this.connection.meta.location.properties.name
|
||||
connection.meta.location.geometry.coordinates = this.connection.meta.location.geometry.coordinates
|
||||
connection.meta.ownership = this.connection.meta.ownership
|
||||
connection.config.privacy.sensitivityLevelID = this.connection.config.privacy.sensitivityLevelID
|
||||
connection.meta.properties = this.connection.meta.properties
|
||||
|
||||
this.connection = new system.DalConnection(connection)
|
||||
this.initialConnectionState = this.connection.clone()
|
||||
}).catch(this.toastErrorHandler(this.$t('notification:connection.update.error')))
|
||||
.finally(() => {
|
||||
this.dal.processing = false
|
||||
})
|
||||
},
|
||||
|
||||
toggleDelete () {
|
||||
const { deletedAt } = this.connection
|
||||
const deleting = !deletedAt
|
||||
|
||||
Reference in New Issue
Block a user