From 2c6521c7e4657303befe42ef166024079f371565 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Wed, 11 Jan 2023 18:16:32 +0800 Subject: [PATCH 1/2] fix(nc-gui): single select behaviours based on roles --- .../nc-gui/components/cell/SingleSelect.vue | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/packages/nc-gui/components/cell/SingleSelect.vue b/packages/nc-gui/components/cell/SingleSelect.vue index 5258ffe327..60c6387fba 100644 --- a/packages/nc-gui/components/cell/SingleSelect.vue +++ b/packages/nc-gui/components/cell/SingleSelect.vue @@ -14,6 +14,7 @@ import { extractSdkResponseErrorMsg, inject, ref, + useRoles, useSelectedCellKeyupListener, watch, } from '#imports' @@ -49,6 +50,8 @@ const searchVal = ref() const { getMeta } = useMetas() +const { hasRole } = useRoles() + const { isPg, isMysql } = useProject() // a variable to keep newly created option value @@ -73,6 +76,10 @@ const isOptionMissing = computed(() => { return (options.value ?? []).every((op) => op.title !== searchVal.value) }) +const hasEditRoles = computed(() => hasRole('owner', true) || hasRole('creator', true) || hasRole('editor', true)) + +const editAllowed = computed(() => hasEditRoles.value && (active.value || editable.value)) + const vModel = computed({ get: () => tempSelectedOptState.value ?? modelValue, set: (val) => { @@ -87,10 +94,12 @@ const vModel = computed({ }) watch(isOpen, (n, _o) => { - if (!n) { - aselect.value?.$el?.querySelector('input')?.blur() - } else { - aselect.value?.$el?.querySelector('input')?.focus() + if (editAllowed.value) { + if (!n) { + aselect.value?.$el?.querySelector('input')?.blur() + } else { + aselect.value?.$el?.querySelector('input')?.focus() + } } }) @@ -100,11 +109,15 @@ useSelectedCellKeyupListener(active, (e) => { isOpen.value = false break case 'Enter': - if (active.value && !isOpen.value) { + if (editAllowed.value && active.value && !isOpen.value) { isOpen.value = true } break default: + if (!editAllowed.value) { + e.preventDefault() + break + } // toggle only if char key pressed if (!(e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) && e.key?.length === 1) { e.stopPropagation() @@ -174,7 +187,7 @@ const toggleMenu = (e: Event) => { vModel.value = '' return } - isOpen.value = (active.value || editable.value) && !isOpen.value + isOpen.value = editAllowed.value && !isOpen.value } @@ -183,11 +196,12 @@ const toggleMenu = (e: Event) => { ref="aselect" v-model:value="vModel" class="w-full" - :allow-clear="!column.rqd && active" + :class="{ 'caret-transparent': !hasEditRoles }" + :allow-clear="!column.rqd && editAllowed" :bordered="false" - :open="isOpen && (active || editable)" + :open="isOpen" :disabled="readOnly" - :show-arrow="!readOnly && (active || editable || vModel === null)" + :show-arrow="hasEditRoles && !readOnly && (editable || (active && vModel === null))" :dropdown-class-name="`nc-dropdown-single-select-cell ${isOpen ? 'active' : ''}`" show-search @select="isOpen = false" @@ -216,8 +230,11 @@ const toggleMenu = (e: Event) => { - - +
@@ -240,4 +257,4 @@ const toggleMenu = (e: Event) => { :deep(.ant-select-clear) { opacity: 1; } - + \ No newline at end of file From 183a123cae6740f50a38d3a024312c7509809242 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Wed, 11 Jan 2023 18:16:43 +0800 Subject: [PATCH 2/2] fix(nc-gui): multi select behaviours based on roles --- .../nc-gui/components/cell/MultiSelect.vue | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/packages/nc-gui/components/cell/MultiSelect.vue b/packages/nc-gui/components/cell/MultiSelect.vue index 3815933e49..7b7d69c191 100644 --- a/packages/nc-gui/components/cell/MultiSelect.vue +++ b/packages/nc-gui/components/cell/MultiSelect.vue @@ -19,6 +19,7 @@ import { useEventListener, useMetas, useProject, + useRoles, useSelectedCellKeyupListener, watch, } from '#imports' @@ -57,6 +58,8 @@ const { $api } = useNuxtApp() const { getMeta } = useMetas() +const { hasRole } = useRoles() + const { isPg, isMysql } = useProject() // a variable to keep newly created options value @@ -80,6 +83,10 @@ const isOptionMissing = computed(() => { return (options.value ?? []).every((op) => op.title !== searchVal.value) }) +const hasEditRoles = computed(() => hasRole('owner', true) || hasRole('creator', true) || hasRole('editor', true)) + +const editAllowed = computed(() => hasEditRoles.value && (active.value || editable.value)) + const vModel = computed({ get: () => { const selected = selectedIds.value.reduce((acc, id) => { @@ -154,10 +161,12 @@ watch( ) watch(isOpen, (n, _o) => { - if (!n) { - aselect.value?.$el?.querySelector('input')?.blur() - } else { - aselect.value?.$el?.querySelector('input')?.focus() + if (editAllowed.value) { + if (!n) { + aselect.value?.$el?.querySelector('input')?.blur() + } else { + aselect.value?.$el?.querySelector('input')?.focus() + } } }) @@ -167,7 +176,7 @@ useSelectedCellKeyupListener(active, (e) => { isOpen.value = false break case 'Enter': - if (active.value && !isOpen.value) { + if (editAllowed.value && active.value && !isOpen.value) { isOpen.value = true } break @@ -179,6 +188,10 @@ useSelectedCellKeyupListener(active, (e) => { // skip break default: + if (!editAllowed.value) { + e.preventDefault() + break + } // toggle only if char key pressed if (!(e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) && e.key?.length === 1) { e.stopPropagation() @@ -272,14 +285,14 @@ const onTagClick = (e: Event, onClose: Function) => { :bordered="false" clear-icon show-search - :show-arrow="!readOnly" + :show-arrow="hasEditRoles && !readOnly && (editable || (active && vModel.length === 0))" :open="isOpen && (active || editable)" :disabled="readOnly" - :class="{ '!ml-[-8px]': readOnly }" + :class="{ '!ml-[-8px]': readOnly, 'caret-transparent': !hasEditRoles }" :dropdown-class-name="`nc-dropdown-multi-select-cell ${isOpen ? 'active' : ''}`" @search="search" @keydown.stop - @click="isOpen = (active || editable) && !isOpen" + @click="isOpen = editAllowed && !isOpen" > { - +
@@ -318,7 +335,7 @@ const onTagClick = (e: Event, onClose: Function) => { class="rounded-tag nc-selected-option" :style="{ display: 'flex', alignItems: 'center' }" :color="options.find((el) => el.title === val)?.color" - :closable="(active || editable) && (vModel.length > 1 || !column?.rqd)" + :closable="editAllowed && (active || editable) && (vModel.length > 1 || !column?.rqd)" :close-icon="h(MdiCloseCircle, { class: ['ms-close-icon'] })" @click="onTagClick($event, onClose)" @close="onClose"