Browse Source

feat(gui-v2): customizable urls in shared views

pull/3381/head
Denis 2 years ago
parent
commit
1ea56db61c
  1. 39
      packages/nc-gui/components/cell/Url.vue
  2. 14
      packages/nc-gui/components/smartsheet/Grid.vue
  3. 7
      packages/nc-gui/context/index.ts
  4. 20
      packages/nc-gui/pages/[projectType]/view/[viewId].vue

39
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 { CellUrlConfigInj, CellUrlDisableOverlayInj, ColumnInj, EditModeInj, computed, inject, isValidURL, ref } from '#imports'
import MiCircleWarning from '~icons/mi/circle-warning'
const { modelValue: value } = defineProps<Props>()
@ -16,6 +16,8 @@ const column = inject(ColumnInj)!
const editEnabled = inject(EditModeInj)!
const config = inject(CellUrlConfigInj, {})
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)
@ -40,6 +42,17 @@ const url = computed(() => {
return `https://${value}`
})
const urlOptions = 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
})
const focus: VNodeRef = (el) => (el as HTMLInputElement)?.focus()
watch(
@ -59,7 +72,20 @@ 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 url-overlay 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>
@ -74,6 +100,15 @@ watch(
</div>
</template>
<style scoped lang="scss">
.url-overlay {
width: 100%;
height: 100%;
text-align: center;
text-decoration-line: none !important;
}
</style>
<!--
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd

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()
})
@ -198,6 +202,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) {
@ -281,8 +289,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)

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

@ -27,3 +27,10 @@ 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')
interface CellUrlOptions {
behavior?: string
overlay?: string
}
export const CellUrlConfigInj: InjectionKey<CellUrlOptions & { rules?: Array<[RegExp, CellUrlOptions]> }> =
Symbol('cell-url-config')
export const CellUrlDisableOverlayInj: InjectionKey<Ref<boolean>> = Symbol('cell-url-disable-url')

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

@ -1,6 +1,7 @@
<script setup lang="ts">
import { message } from 'ant-design-vue'
import {
CellUrlConfigInj,
ReadonlyInj,
ReloadViewDataHookInj,
createEventHook,
@ -24,6 +25,25 @@ const reloadEventHook = createEventHook<void>()
provide(ReloadViewDataHookInj, reloadEventHook)
provide(ReadonlyInj, true)
const parseUrlRules = (serialized: string | 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
}
}
provide(CellUrlConfigInj, {
behavior: route.query.url_behavior as string,
overlay: route.query.url_overlay as string,
rules: parseUrlRules(route.query.url_rules as string),
})
const { loadSharedView } = useSharedView()
const showPassword = ref(false)

Loading…
Cancel
Save