mirror of
https://github.com/nocodb/nocodb.git
synced 2026-02-01 23:58:31 +00:00
Merge pull request #3690 from nocodb/fix/copy-to-clipboard
Fix: Add a fallback function copy to clipboard
This commit is contained in:
1
packages/nc-gui/components.d.ts
vendored
1
packages/nc-gui/components.d.ts
vendored
@@ -232,6 +232,7 @@ declare module '@vue/runtime-core' {
|
|||||||
MdiUpload: typeof import('~icons/mdi/upload')['default']
|
MdiUpload: typeof import('~icons/mdi/upload')['default']
|
||||||
MdiUploadOutline: typeof import('~icons/mdi/upload-outline')['default']
|
MdiUploadOutline: typeof import('~icons/mdi/upload-outline')['default']
|
||||||
MdiViewListOutline: typeof import('~icons/mdi/view-list-outline')['default']
|
MdiViewListOutline: typeof import('~icons/mdi/view-list-outline')['default']
|
||||||
|
MdiWarning: typeof import('~icons/mdi/warning')['default']
|
||||||
MdiWhatsapp: typeof import('~icons/mdi/whatsapp')['default']
|
MdiWhatsapp: typeof import('~icons/mdi/whatsapp')['default']
|
||||||
MdiXml: typeof import('~icons/mdi/xml')['default']
|
MdiXml: typeof import('~icons/mdi/xml')['default']
|
||||||
MiCircleWarning: typeof import('~icons/mi/circle-warning')['default']
|
MiCircleWarning: typeof import('~icons/mi/circle-warning')['default']
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { message } from 'ant-design-vue'
|
|||||||
import {
|
import {
|
||||||
computed,
|
computed,
|
||||||
extractSdkResponseErrorMsg,
|
extractSdkResponseErrorMsg,
|
||||||
useClipboard,
|
useCopy,
|
||||||
useI18n,
|
useI18n,
|
||||||
useNuxtApp,
|
useNuxtApp,
|
||||||
useProject,
|
useProject,
|
||||||
@@ -17,7 +17,7 @@ const { t } = useI18n()
|
|||||||
|
|
||||||
const { view, $api } = useSmartsheetStoreOrThrow()
|
const { view, $api } = useSmartsheetStoreOrThrow()
|
||||||
|
|
||||||
const { copy } = useClipboard()
|
const { copy } = useCopy()
|
||||||
|
|
||||||
const { $e } = useNuxtApp()
|
const { $e } = useNuxtApp()
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ViewTypes } from 'nocodb-sdk'
|
import { ViewTypes } from 'nocodb-sdk'
|
||||||
import { Empty, message } from 'ant-design-vue'
|
import { Empty, message } from 'ant-design-vue'
|
||||||
import { extractSdkResponseErrorMsg, onMounted, useClipboard, useI18n, useSmartsheetStoreOrThrow } from '#imports'
|
import { extractSdkResponseErrorMsg, onMounted, useCopy, useI18n, useSmartsheetStoreOrThrow } from '#imports'
|
||||||
import MdiVisibilityOnIcon from '~icons/mdi/visibility'
|
import MdiVisibilityOnIcon from '~icons/mdi/visibility'
|
||||||
import MdiVisibilityOffIcon from '~icons/mdi/visibility-off'
|
import MdiVisibilityOffIcon from '~icons/mdi/visibility-off'
|
||||||
import MdiCopyIcon from '~icons/mdi/content-copy'
|
import MdiCopyIcon from '~icons/mdi/content-copy'
|
||||||
@@ -20,7 +20,7 @@ const { t } = useI18n()
|
|||||||
|
|
||||||
const { $api, meta } = useSmartsheetStoreOrThrow()
|
const { $api, meta } = useSmartsheetStoreOrThrow()
|
||||||
|
|
||||||
const { copy } = useClipboard()
|
const { copy } = useCopy()
|
||||||
|
|
||||||
const { dashboardUrl } = useDashboard()
|
const { dashboardUrl } = useDashboard()
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
ActiveViewInj,
|
ActiveViewInj,
|
||||||
MetaInj,
|
MetaInj,
|
||||||
inject,
|
inject,
|
||||||
useClipboard,
|
useCopy,
|
||||||
useGlobal,
|
useGlobal,
|
||||||
useI18n,
|
useI18n,
|
||||||
useProject,
|
useProject,
|
||||||
@@ -36,7 +36,7 @@ const { xWhere } = useSmartsheetStoreOrThrow()
|
|||||||
|
|
||||||
const { queryParams } = $(useViewData($$(meta), $$(view), xWhere))
|
const { queryParams } = $(useViewData($$(meta), $$(view), xWhere))
|
||||||
|
|
||||||
const { copy } = useClipboard()
|
const { copy } = useCopy()
|
||||||
|
|
||||||
let vModel = $(useVModel(props, 'modelValue', emits))
|
let vModel = $(useVModel(props, 'modelValue', emits))
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import {
|
|||||||
provide,
|
provide,
|
||||||
reactive,
|
reactive,
|
||||||
ref,
|
ref,
|
||||||
useClipboard,
|
useCopy,
|
||||||
useEventListener,
|
useEventListener,
|
||||||
useGridViewColumnWidth,
|
useGridViewColumnWidth,
|
||||||
useI18n,
|
useI18n,
|
||||||
@@ -97,7 +97,7 @@ const {
|
|||||||
|
|
||||||
const { loadGridViewColumns, updateWidth, resizingColWidth, resizingCol } = useGridViewColumnWidth(view)
|
const { loadGridViewColumns, updateWidth, resizingColWidth, resizingCol } = useGridViewColumnWidth(view)
|
||||||
|
|
||||||
const { copy } = useClipboard()
|
const { copy } = useCopy()
|
||||||
|
|
||||||
onMounted(loadGridViewColumns)
|
onMounted(loadGridViewColumns)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { ApiTokenType } from 'nocodb-sdk'
|
import type { ApiTokenType } from 'nocodb-sdk'
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import { extractSdkResponseErrorMsg, useClipboard, useI18n } from '#imports'
|
import { extractSdkResponseErrorMsg, useCopy, useI18n } from '#imports'
|
||||||
import KebabIcon from '~icons/ic/baseline-more-vert'
|
import KebabIcon from '~icons/ic/baseline-more-vert'
|
||||||
import MdiPlusIcon from '~icons/mdi/plus'
|
import MdiPlusIcon from '~icons/mdi/plus'
|
||||||
import CloseIcon from '~icons/material-symbols/close-rounded'
|
import CloseIcon from '~icons/material-symbols/close-rounded'
|
||||||
@@ -21,7 +21,7 @@ const { $api, $e } = useNuxtApp()
|
|||||||
|
|
||||||
const { project } = $(useProject())
|
const { project } = $(useProject())
|
||||||
|
|
||||||
const { copy } = useClipboard()
|
const { copy } = useCopy()
|
||||||
|
|
||||||
let tokensInfo = $ref<ApiToken[] | undefined>([])
|
let tokensInfo = $ref<ApiToken[] | undefined>([])
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
onBeforeMount,
|
onBeforeMount,
|
||||||
ref,
|
ref,
|
||||||
useApi,
|
useApi,
|
||||||
useClipboard,
|
useCopy,
|
||||||
useDashboard,
|
useDashboard,
|
||||||
useI18n,
|
useI18n,
|
||||||
useNuxtApp,
|
useNuxtApp,
|
||||||
@@ -26,7 +26,7 @@ const { api } = useApi()
|
|||||||
|
|
||||||
const { project } = useProject()
|
const { project } = useProject()
|
||||||
|
|
||||||
const { copy } = useClipboard()
|
const { copy } = useCopy()
|
||||||
|
|
||||||
const { isUIAllowed } = useUIPermission()
|
const { isUIAllowed } = useUIPermission()
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import { extractSdkResponseErrorMsg, onMounted, useClipboard, useI18n, useNuxtApp, useProject } from '#imports'
|
import { extractSdkResponseErrorMsg, onMounted, useCopy, useI18n, useNuxtApp, useProject } from '#imports'
|
||||||
|
|
||||||
interface ShareBase {
|
interface ShareBase {
|
||||||
uuid?: string
|
uuid?: string
|
||||||
@@ -25,7 +25,7 @@ const showEditBaseDropdown = $ref(false)
|
|||||||
|
|
||||||
const { project } = useProject()
|
const { project } = useProject()
|
||||||
|
|
||||||
const { copy } = useClipboard()
|
const { copy } = useCopy()
|
||||||
|
|
||||||
const url = $computed(() => (base && base.uuid ? `${dashboardUrl}#/base/${base.uuid}` : null))
|
const url = $computed(() => (base && base.uuid ? `${dashboardUrl}#/base/${base.uuid}` : null))
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
projectRoleTagColors,
|
projectRoleTagColors,
|
||||||
projectRoles,
|
projectRoles,
|
||||||
ref,
|
ref,
|
||||||
useClipboard,
|
useCopy,
|
||||||
useDashboard,
|
useDashboard,
|
||||||
useI18n,
|
useI18n,
|
||||||
useNuxtApp,
|
useNuxtApp,
|
||||||
@@ -37,7 +37,7 @@ const { t } = useI18n()
|
|||||||
|
|
||||||
const { project } = useProject()
|
const { project } = useProject()
|
||||||
const { $api, $e } = useNuxtApp()
|
const { $api, $e } = useNuxtApp()
|
||||||
const { copy } = useClipboard()
|
const { copy } = useCopy()
|
||||||
const { dashboardUrl } = $(useDashboard())
|
const { dashboardUrl } = $(useDashboard())
|
||||||
|
|
||||||
const usersData = $ref<Users>({ emails: undefined, role: ProjectRole.Viewer, invitationToken: undefined })
|
const usersData = $ref<Users>({ emails: undefined, role: ProjectRole.Viewer, invitationToken: undefined })
|
||||||
|
|||||||
@@ -25,3 +25,4 @@ export * from './useLTARStore'
|
|||||||
export * from './useExpandedFormStore'
|
export * from './useExpandedFormStore'
|
||||||
export * from './useSharedFormViewStore'
|
export * from './useSharedFormViewStore'
|
||||||
export * from './useCellUrlConfig'
|
export * from './useCellUrlConfig'
|
||||||
|
export * from './useCopy'
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import type { ColumnType, TableType } from 'nocodb-sdk'
|
|||||||
import { UITypes } from 'nocodb-sdk'
|
import { UITypes } from 'nocodb-sdk'
|
||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useColumn } from './useColumn'
|
|
||||||
import { computed, createInjectionState, extractSdkResponseErrorMsg, useNuxtApp } from '#imports'
|
import { computed, createInjectionState, extractSdkResponseErrorMsg, useNuxtApp } from '#imports'
|
||||||
|
|
||||||
const useForm = Form.useForm
|
const useForm = Form.useForm
|
||||||
|
|||||||
26
packages/nc-gui/composables/useCopy.ts
Normal file
26
packages/nc-gui/composables/useCopy.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { useClipboard } from '#imports'
|
||||||
|
|
||||||
|
export const useCopy = () => {
|
||||||
|
/** fallback for copy if clipboard api is not supported */
|
||||||
|
const copyFallback = (text: string) => {
|
||||||
|
const textAreaEl = document.createElement('textarea')
|
||||||
|
textAreaEl.innerHTML = text
|
||||||
|
document.body.appendChild(textAreaEl)
|
||||||
|
textAreaEl.select()
|
||||||
|
const result = document.execCommand('copy')
|
||||||
|
document.body.removeChild(textAreaEl)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
const { copy: _copy, isSupported } = useClipboard()
|
||||||
|
|
||||||
|
const copy = async (text: string) => {
|
||||||
|
if (isSupported) {
|
||||||
|
await _copy(text)
|
||||||
|
} else {
|
||||||
|
copyFallback(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { copy }
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
projectThemeColors,
|
projectThemeColors,
|
||||||
provide,
|
provide,
|
||||||
ref,
|
ref,
|
||||||
useClipboard,
|
useCopy,
|
||||||
useGlobal,
|
useGlobal,
|
||||||
useI18n,
|
useI18n,
|
||||||
useProject,
|
useProject,
|
||||||
@@ -42,7 +42,7 @@ const { clearTabs, addTab } = useTabs()
|
|||||||
|
|
||||||
const { isUIAllowed } = useUIPermission()
|
const { isUIAllowed } = useUIPermission()
|
||||||
|
|
||||||
const { copy } = useClipboard()
|
const { copy } = useCopy()
|
||||||
|
|
||||||
const isLocked = ref(false)
|
const isLocked = ref(false)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user