Browse Source

Merge pull request #3381 from dolsem/shared-view-url-customization

feat(gui-v2): customizable urls in shared views
pull/3611/head
navi 2 years ago committed by GitHub
parent
commit
f94ddc323c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 21
      packages/nc-gui/components/cell/Url.vue
  2. 14
      packages/nc-gui/components/smartsheet/Grid.vue
  3. 3
      packages/nc-gui/components/virtual-cell/Lookup.vue
  4. 1
      packages/nc-gui/composables/index.ts
  5. 48
      packages/nc-gui/composables/useCellUrlConfig.ts
  6. 1
      packages/nc-gui/context/index.ts
  7. 3
      packages/nc-gui/pages/[projectType]/view/[viewId].vue

21
packages/nc-gui/components/cell/Url.vue

@ -2,7 +2,7 @@
import type { VNodeRef } from '@vue/runtime-core'
import { message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import { ColumnInj, EditModeInj, computed, inject, isValidURL } from '#imports'
import { CellUrlDisableOverlayInj, ColumnInj, EditModeInj, computed, inject, isValidURL, ref } from '#imports'
import MiCircleWarning from '~icons/mi/circle-warning'
const { modelValue: value } = defineProps<Props>()
@ -16,6 +16,7 @@ const column = inject(ColumnInj)!
const editEnabled = inject(EditModeInj)!
const disableOverlay = inject(CellUrlDisableOverlayInj)
// Used in the logic of when to display error since we are not storing the url if its not valid
const localState = ref(value)
@ -39,6 +40,7 @@ const url = computed(() => {
return `https://${value}`
})
const urlOptions = useCellUrlConfig(url)
const focus: VNodeRef = (el) => (el as HTMLInputElement)?.focus()
@ -59,7 +61,22 @@ watch(
<div class="flex flex-row items-center justify-between">
<input v-if="editEnabled" :ref="focus" v-model="vModel" class="outline-none text-sm w-full" @blur="editEnabled = false" />
<nuxt-link v-else-if="isValid" class="text-sm underline hover:opacity-75" :to="url" target="_blank">{{ value }} </nuxt-link>
<nuxt-link
v-else-if="isValid && !urlOptions?.overlay"
class="z-3 text-sm underline hover:opacity-75"
:to="url"
:target="urlOptions?.behavior === 'replace' ? undefined : '_blank'"
>
{{ value }}
</nuxt-link>
<nuxt-link
v-else-if="isValid && !disableOverlay && urlOptions?.overlay"
class="z-3 w-full h-full text-center !no-underline hover:opacity-75"
:to="url"
:target="urlOptions?.behavior === 'replace' ? undefined : '_blank'"
>
{{ urlOptions.overlay }}
</nuxt-link>
<span v-else class="w-9/10 overflow-ellipsis overflow-hidden">{{ value }}</span>

14
packages/nc-gui/components/smartsheet/Grid.vue

@ -5,6 +5,7 @@ import { message } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import {
ActiveViewInj,
CellUrlDisableOverlayInj,
ChangePageInj,
FieldsInj,
IsFormInj,
@ -109,6 +110,9 @@ provide(ChangePageInj, changePage)
provide(ReadonlyInj, !hasEditPermission)
const disableUrlOverlay = ref(false)
provide(CellUrlDisableOverlayInj, disableUrlOverlay)
reloadViewDataHook?.on(async () => {
await loadData()
})
@ -201,6 +205,10 @@ const makeEditable = (row: Row, col: ColumnType) => {
/** handle keypress events */
const onKeyDown = async (e: KeyboardEvent) => {
if (e.key === 'Alt') {
disableUrlOverlay.value = true
return
}
if (selected.row === null || selected.col === null) return
/** on tab key press navigate through cells */
switch (e.key) {
@ -284,8 +292,14 @@ const onKeyDown = async (e: KeyboardEvent) => {
break
}
}
const onKeyUp = async (e: KeyboardEvent) => {
if (e.key === 'Alt') {
disableUrlOverlay.value = false
}
}
useEventListener(document, 'keydown', onKeyDown)
useEventListener(document, 'keyup', onKeyUp)
/** On clicking outside of table reset active cell */
const smartTable = ref(null)

3
packages/nc-gui/components/virtual-cell/Lookup.vue

@ -2,7 +2,7 @@
import type { ColumnType, LinkToAnotherRecordType, LookupType } from 'nocodb-sdk'
import { RelationTypes, UITypes, isVirtualCol } from 'nocodb-sdk'
import type { Ref } from 'vue'
import { CellValueInj, ColumnInj, MetaInj, ReadonlyInj, computed, inject, provide, useColumn, useMetas } from '#imports'
import { CellUrlDisableOverlayInj, CellValueInj, ColumnInj, MetaInj, ReadonlyInj, computed, inject, provide, useColumn, useMetas } from '#imports'
const { metas, getMeta } = useMetas()
@ -32,6 +32,7 @@ const lookupColumn = computed<any>(
)
provide(MetaInj, lookupTableMeta)
provide(CellUrlDisableOverlayInj, ref(true))
const lookupColumnMetaProps = useColumn(lookupColumn)
</script>

1
packages/nc-gui/composables/index.ts

@ -24,3 +24,4 @@ export * from './useSmartsheetStore'
export * from './useLTARStore'
export * from './useExpandedFormStore'
export * from './useSharedFormViewStore'
export * from './useCellUrlConfig'

48
packages/nc-gui/composables/useCellUrlConfig.ts

@ -0,0 +1,48 @@
import type { ComputedRef } from 'vue'
import { useRoute } from '#imports'
export interface CellUrlOptions {
behavior?: string
overlay?: string
}
const parseUrlRules = (serialized: string | undefined): Array<[RegExp, CellUrlOptions]> | undefined => {
if (!serialized) return undefined
try {
const rules: Array<[RegExp, {}]> = Object.entries(JSON.parse(serialized)).map(([key, value]) => [
new RegExp(key),
value as {},
])
return rules
} catch (err) {
console.error(err)
return undefined
}
}
const [useProvideCellUrlConfig, useCellUrlGeneralConfig] = useInjectionState(() => {
const route = useRoute()
return {
behavior: route.query.url_behavior as string | undefined,
overlay: route.query.url_overlay as string | undefined,
rules: parseUrlRules(route.query.url_rules as string),
}
}, 'cell-url-config')
export { useProvideCellUrlConfig }
export function useCellUrlConfig(url: ComputedRef<string>) {
const config = useCellUrlGeneralConfig()
if (!config) return undefined
return computed(() => {
const { behavior, overlay, rules } = config
const options = { behavior, overlay }
if (rules && (!behavior || !overlay)) {
for (const [regex, value] of rules) {
if (url.value.match(regex)) return Object.assign(options, value)
}
}
return options
})
}

1
packages/nc-gui/context/index.ts

@ -28,3 +28,4 @@ export const FieldsInj: InjectionKey<Ref<any[]>> = Symbol('fields-injection')
export const ViewListInj: InjectionKey<Ref<ViewType[]>> = Symbol('view-list-injection')
export const EditModeInj: InjectionKey<Ref<boolean>> = Symbol('edit-mode-injection')
export const SharedViewPasswordInj: InjectionKey<Ref<string | null>> = Symbol('shared-view-password-injection')
export const CellUrlDisableOverlayInj: InjectionKey<Ref<boolean>> = Symbol('cell-url-disable-url')

3
packages/nc-gui/pages/[projectType]/view/[viewId].vue

@ -8,6 +8,7 @@ import {
extractSdkResponseErrorMsg,
provide,
ref,
useProvideCellUrlConfig,
useRoute,
useSharedView,
} from '#imports'
@ -24,6 +25,8 @@ const reloadEventHook = createEventHook<void>()
provide(ReloadViewDataHookInj, reloadEventHook)
provide(ReadonlyInj, true)
useProvideCellUrlConfig()
const { loadSharedView } = useSharedView()
const showPassword = ref(false)

Loading…
Cancel
Save