Browse Source

fix/Added filter sorting for user with viewer role

pull/3251/head
Muhammed Mustafa 2 years ago
parent
commit
4ea8b6ac94
  1. 4
      packages/nc-gui-v2/components/shared-view/Grid.vue
  2. 12
      packages/nc-gui-v2/components/smartsheet-toolbar/ColumnFilter.vue
  3. 6
      packages/nc-gui-v2/components/smartsheet-toolbar/ColumnFilterMenu.vue
  4. 14
      packages/nc-gui-v2/composables/useSmartsheetStore.ts
  5. 6
      packages/nc-gui-v2/composables/useViewColumns.ts
  6. 8
      packages/nc-gui-v2/composables/useViewData.ts
  7. 86
      packages/nc-gui-v2/composables/useViewFilters.ts
  8. 25
      packages/nc-gui-v2/composables/useViewSorts.ts

4
packages/nc-gui-v2/components/shared-view/Grid.vue

@ -4,7 +4,7 @@ import type { TableType } from 'nocodb-sdk'
import { ActiveViewInj, FieldsInj, IsPublicInj, MetaInj, ReadonlyInj, ReloadViewDataHookInj } from '~/context' import { ActiveViewInj, FieldsInj, IsPublicInj, MetaInj, ReadonlyInj, ReloadViewDataHookInj } from '~/context'
const { sharedView, meta } = useSharedView() const { sharedView, meta, sorts, nestedFilters } = useSharedView()
const reloadEventHook = createEventHook<void>() const reloadEventHook = createEventHook<void>()
provide(ReloadViewDataHookInj, reloadEventHook) provide(ReloadViewDataHookInj, reloadEventHook)
@ -14,7 +14,7 @@ provide(ActiveViewInj, sharedView)
provide(FieldsInj, ref(meta.value.columns as any[])) provide(FieldsInj, ref(meta.value.columns as any[]))
provide(IsPublicInj, ref(true)) provide(IsPublicInj, ref(true))
useProvideSmartsheetStore(sharedView as Ref<TableType>, meta) useProvideSmartsheetStore(sharedView as Ref<TableType>, meta, true, sorts, nestedFilters)
</script> </script>
<template> <template>

12
packages/nc-gui-v2/components/smartsheet-toolbar/ColumnFilter.vue

@ -41,6 +41,7 @@ const reloadDataHook = inject(ReloadViewDataHookInj)!
const { $e } = useNuxtApp() const { $e } = useNuxtApp()
const { nestedFilters } = useSmartsheetStoreOrThrow()
const { filters, deleteFilter, saveOrUpdate, loadFilters, addFilter, addFilterGroup, sync } = useViewFilters( const { filters, deleteFilter, saveOrUpdate, loadFilters, addFilter, addFilterGroup, sync } = useViewFilters(
activeView, activeView,
parentId, parentId,
@ -48,10 +49,11 @@ const { filters, deleteFilter, saveOrUpdate, loadFilters, addFilter, addFilterGr
() => { () => {
reloadDataHook.trigger() reloadDataHook.trigger()
}, },
modelValue, modelValue || nestedFilters.value,
!modelValue,
) )
const nestedFilters = ref() const localNestedFilters = ref()
const filterUpdateCondition = (filter: FilterType, i: number) => { const filterUpdateCondition = (filter: FilterType, i: number) => {
saveOrUpdate(filter, i) saveOrUpdate(filter, i)
@ -115,9 +117,9 @@ watch(
const applyChanges = async (hookId?: string) => { const applyChanges = async (hookId?: string) => {
await sync(hookId) await sync(hookId)
if (!nestedFilters.value?.length) return if (!localNestedFilters.value?.length) return
for (const nestedFilter of nestedFilters.value) { for (const nestedFilter of localNestedFilters.value) {
if (nestedFilter.parentId) { if (nestedFilter.parentId) {
await nestedFilter.applyChanges(hookId, true) await nestedFilter.applyChanges(hookId, true)
} }
@ -166,7 +168,7 @@ defineExpose({
<div class="col-span-5"> <div class="col-span-5">
<SmartsheetToolbarColumnFilter <SmartsheetToolbarColumnFilter
v-if="filter.id || filter.children" v-if="filter.id || filter.children"
ref="nestedFilters" ref="localNestedFilters"
v-model="filter.children" v-model="filter.children"
:parent-id="filter.id" :parent-id="filter.id"
nested nested

6
packages/nc-gui-v2/components/smartsheet-toolbar/ColumnFilterMenu.vue

@ -12,11 +12,15 @@ const { filterAutoSave } = useGlobal()
const filterComp = ref<typeof ColumnFilter>() const filterComp = ref<typeof ColumnFilter>()
const { nestedFilters } = useSmartsheetStoreOrThrow()
// todo: avoid duplicate api call by keeping a filter store // todo: avoid duplicate api call by keeping a filter store
const { filters, loadFilters } = useViewFilters( const { filters, loadFilters } = useViewFilters(
activeView, activeView,
undefined, undefined,
computed(() => false), computed(() => true),
() => false,
nestedFilters.value,
true,
) )
const filtersLength = ref(0) const filtersLength = ref(0)

14
packages/nc-gui-v2/composables/useSmartsheetStore.ts

@ -1,10 +1,16 @@
import { ViewTypes } from 'nocodb-sdk' import { ViewTypes } from 'nocodb-sdk'
import type { TableType, ViewType } from 'nocodb-sdk' import type { FilterType, SortType, TableType, ViewType } from 'nocodb-sdk'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { computed, reactive, useInjectionState, useNuxtApp, useProject, useTemplateRefsList } from '#imports' import { computed, reactive, useInjectionState, useNuxtApp, useProject, useTemplateRefsList } from '#imports'
const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState( const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState(
(view: Ref<ViewType>, meta: Ref<TableType>, shared = false) => { (
view: Ref<ViewType>,
meta: Ref<TableType>,
shared = false,
initalSorts?: Ref<SortType[]>,
initialFilters?: Ref<FilterType[]>,
) => {
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const { sqlUi } = useProject() const { sqlUi } = useProject()
@ -37,6 +43,8 @@ const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState(
} }
return where return where
}) })
const sorts = initalSorts ?? ref<SortType[]>([])
const nestedFilters: Ref<FilterType[]> = initialFilters ?? ref<FilterType[]>([])
return { return {
view, view,
@ -51,6 +59,8 @@ const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState(
isGallery, isGallery,
cellRefs, cellRefs,
isSharedForm, isSharedForm,
sorts,
nestedFilters,
} }
}, },
'smartsheet-store', 'smartsheet-store',

6
packages/nc-gui-v2/composables/useViewColumns.ts

@ -52,7 +52,7 @@ export function useViewColumns(view: Ref<ViewType> | undefined, meta: ComputedRe
} }
const showAll = async (ignoreIds?: any) => { const showAll = async (ignoreIds?: any) => {
if (isPublic.value || isSharedBase) { if (isPublic.value || isSharedBase.value) {
fields.value = fields.value?.map((field: Field) => ({ fields.value = fields.value?.map((field: Field) => ({
...field, ...field,
show: true, show: true,
@ -75,7 +75,7 @@ export function useViewColumns(view: Ref<ViewType> | undefined, meta: ComputedRe
reloadData?.() reloadData?.()
} }
const hideAll = async (ignoreIds?: any) => { const hideAll = async (ignoreIds?: any) => {
if (isPublic.value || isSharedBase) { if (isPublic.value || isSharedBase.value) {
fields.value = fields.value?.map((field: Field) => ({ fields.value = fields.value?.map((field: Field) => ({
...field, ...field,
show: false, show: false,
@ -144,7 +144,7 @@ export function useViewColumns(view: Ref<ViewType> | undefined, meta: ComputedRe
}, },
set(v: boolean) { set(v: boolean) {
if (view?.value?.id) { if (view?.value?.id) {
if (!isPublic.value && !isSharedBase) { if (!isPublic.value && !isSharedBase.value) {
$api.dbView $api.dbView
.update(view.value.id, { .update(view.value.id, {
show_system_fields: v, show_system_fields: v,

8
packages/nc-gui-v2/composables/useViewData.ts

@ -39,10 +39,10 @@ export function useViewData(
const formattedData = ref<Row[]>([]) const formattedData = ref<Row[]>([])
const isPublic = inject(IsPublicInj, ref(false)) const isPublic = inject(IsPublicInj, ref(false))
const { project } = useProject() const { project, isSharedBase } = useProject()
const { fetchSharedViewData, paginationData: sharedPaginationData } = useSharedView() const { fetchSharedViewData, paginationData: sharedPaginationData } = useSharedView()
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const { sorts, nestedFilters: filters } = useSharedView() const { sorts, nestedFilters } = useSmartsheetStoreOrThrow()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useUIPermission()
const paginationData = computed({ const paginationData = computed({
@ -84,7 +84,7 @@ export function useViewData(
/** load row comments count */ /** load row comments count */
const loadAggCommentsCount = async () => { const loadAggCommentsCount = async () => {
// todo: handle in public api // todo: handle in public api
if (isPublic.value) return if (isPublic.value || isSharedBase.value) return
const ids = formattedData.value const ids = formattedData.value
?.filter(({ rowMeta: { new: isNew } }) => !isNew) ?.filter(({ rowMeta: { new: isNew } }) => !isNew)
@ -112,7 +112,7 @@ export function useViewData(
? await $api.dbViewRow.list('noco', project.value.id!, meta.value.id!, viewMeta!.value.id, { ? await $api.dbViewRow.list('noco', project.value.id!, meta.value.id!, viewMeta!.value.id, {
...params, ...params,
...(isUIAllowed('sortSync') ? {} : { sortArrJson: JSON.stringify(sorts.value) }), ...(isUIAllowed('sortSync') ? {} : { sortArrJson: JSON.stringify(sorts.value) }),
...(isUIAllowed('filterSync') ? {} : { filterArrJson: JSON.stringify(filters.value) }), ...(isUIAllowed('filterSync') ? {} : { filterArrJson: JSON.stringify(nestedFilters.value) }),
where: where?.value, where: where?.value,
}) })
: await fetchSharedViewData() : await fetchSharedViewData()

86
packages/nc-gui-v2/composables/useViewFilters.ts

@ -1,17 +1,6 @@
import type { ViewType } from 'nocodb-sdk' import type { ViewType } from 'nocodb-sdk'
import type { ComputedRef, Ref } from 'vue' import type { ComputedRef, Ref } from 'vue'
import { import { IsPublicInj, ReloadViewDataHookInj, computed, inject, ref, useMetas, useNuxtApp, useUIPermission, watch } from '#imports'
IsPublicInj,
ReloadViewDataHookInj,
computed,
inject,
ref,
useMetas,
useNuxtApp,
useSharedView,
useUIPermission,
watch,
} from '#imports'
import type { Filter } from '~/lib' import type { Filter } from '~/lib'
export function useViewFilters( export function useViewFilters(
@ -19,13 +8,12 @@ export function useViewFilters(
parentId?: string, parentId?: string,
autoApply?: ComputedRef<boolean>, autoApply?: ComputedRef<boolean>,
reloadData?: () => void, reloadData?: () => void,
siblingFilters?: Filter[], currentFilters?: Filter[],
isNestedRoot?: boolean,
) { ) {
const { nestedFilters } = useSharedView()
const reloadHook = inject(ReloadViewDataHookInj) const reloadHook = inject(ReloadViewDataHookInj)
const _filters = ref<Filter[]>([]) const { nestedFilters } = useSmartsheetStoreOrThrow()
const isPublic = inject(IsPublicInj, ref(false)) const isPublic = inject(IsPublicInj, ref(false))
@ -34,21 +22,23 @@ export function useViewFilters(
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useUIPermission()
const { metas } = useMetas() const { metas } = useMetas()
const _filters = ref<Filter[]>([])
const nestedMode = computed(() => isPublic.value || !isUIAllowed('filterSync' || !isUIAllowed('filterChildrenRead')))
const filters = computed<Filter[]>({
get: () => (nestedMode.value ? currentFilters! : _filters.value),
set: (value: Filter[]) => {
if (nestedMode.value) {
currentFilters = value
if (isNestedRoot) nestedFilters.value = value
const filters = computed({
get: () => (isPublic.value ? siblingFilters || nestedFilters.value : _filters.value) ?? [],
set: (value) => {
if (isPublic.value) {
if (siblingFilters) {
siblingFilters = value
} else {
nestedFilters.value = value
}
nestedFilters.value = [...nestedFilters.value] nestedFilters.value = [...nestedFilters.value]
reloadHook?.trigger() reloadHook?.trigger()
} else { return
_filters.value = value
} }
_filters.value = value
}, },
}) })
@ -60,18 +50,24 @@ export function useViewFilters(
} }
const loadFilters = async (hookId?: string) => { const loadFilters = async (hookId?: string) => {
if (hookId) { if (nestedMode.value) return
if (parentId) {
filters.value = await $api.dbTableFilter.childrenRead(parentId) try {
} else { if (hookId) {
filters.value = (await $api.dbTableWebhookFilter.read(hookId as string)) as any if (parentId) {
} filters.value = await $api.dbTableFilter.childrenRead(parentId)
} else { } else {
if (parentId) { filters.value = (await $api.dbTableWebhookFilter.read(hookId as string)) as any
filters.value = await $api.dbTableFilter.childrenRead(parentId) }
} else { } else {
filters.value = await $api.dbTableFilter.read(view?.value?.id as string) if (parentId) {
filters.value = await $api.dbTableFilter.childrenRead(parentId)
} else {
filters.value = await $api.dbTableFilter.read(view?.value?.id as string)
}
} }
} catch (e) {
console.log(e)
} }
} }
@ -104,7 +100,7 @@ export function useViewFilters(
const deleteFilter = async (filter: Filter, i: number) => { const deleteFilter = async (filter: Filter, i: number) => {
// if shared or sync permission not allowed simply remove it from array // if shared or sync permission not allowed simply remove it from array
if (isPublic.value || !isUIAllowed('filterSync')) { if (nestedMode.value) {
filters.value.splice(i, 1) filters.value.splice(i, 1)
reloadData?.() reloadData?.()
@ -129,17 +125,11 @@ export function useViewFilters(
} }
const saveOrUpdate = async (filter: Filter, i: number, force = false) => { const saveOrUpdate = async (filter: Filter, i: number, force = false) => {
if (isPublic.value) {
filters.value[i] = { ...filter }
filters.value = [...filters.value]
return
}
if (!view?.value) return if (!view?.value) return
if (!isUIAllowed('filterSync')) { if (nestedMode.value) {
// skip filters.value[i] = { ...filter }
filters.value = [...filters.value]
} else if (!autoApply?.value && !force) { } else if (!autoApply?.value && !force) {
filter.status = filter.id ? 'update' : 'create' filter.status = filter.id ? 'update' : 'create'
} else if (filter.id) { } else if (filter.id) {
@ -168,7 +158,7 @@ export function useViewFilters(
logical_op: 'and', logical_op: 'and',
} }
if (isPublic.value) placeHolderGroupFilter.children = [child] if (nestedMode.value) placeHolderGroupFilter.children = [child]
filters.value.push(placeHolderGroupFilter) filters.value.push(placeHolderGroupFilter)

25
packages/nc-gui-v2/composables/useViewSorts.ts

@ -6,31 +6,17 @@ export function useViewSorts(
view: Ref<(GridType | KanbanType | GalleryType) & { id?: string }> | undefined, view: Ref<(GridType | KanbanType | GalleryType) & { id?: string }> | undefined,
reloadData?: () => void, reloadData?: () => void,
) { ) {
const _sorts = ref<SortType[]>([]) const { sharedView } = useSharedView()
const { sorts } = useSmartsheetStoreOrThrow()
const { sorts: sharedViewSorts, sharedView } = useSharedView()
const reloadHook = inject(ReloadViewDataHookInj) const reloadHook = inject(ReloadViewDataHookInj)
const isPublic = inject(IsPublicInj, ref(false)) const isPublic = inject(IsPublicInj, ref(false))
const { isSharedBase } = useProject()
const sorts = computed<SortType[]>({
get: () => (isPublic.value || isSharedBase.value ? sharedViewSorts.value : _sorts.value),
set: (value) => {
if (isPublic.value || isSharedBase.value) {
sharedViewSorts.value = value
} else {
_sorts.value = value
}
reloadHook?.trigger()
},
})
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useUIPermission()
const { isSharedBase } = useProject()
const loadSorts = async () => { const loadSorts = async () => {
if (isPublic.value) { if (isPublic.value) {
@ -74,5 +60,10 @@ export function useViewSorts(
sorts.value.splice(i, 1) sorts.value.splice(i, 1)
sorts.value = [...sorts.value] sorts.value = [...sorts.value]
} }
watch(sorts, () => {
reloadHook?.trigger()
})
return { sorts, loadSorts, addSort, deleteSort, saveOrUpdate } return { sorts, loadSorts, addSort, deleteSort, saveOrUpdate }
} }

Loading…
Cancel
Save