mirror of
https://github.com/nocodb/nocodb.git
synced 2026-05-02 14:47:01 +00:00
feat: Improved UI (#6222)
* feat: Improved ui (#6156) * refactor: revert Signed-off-by: Pranav C <pranavxc@gmail.com> feat: shared base Signed-off-by: Pranav C <pranavxc@gmail.com> fix: remove duplicate import statement Signed-off-by: Pranav C <pranavxc@gmail.com> fix: disable starred & license menu Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: fix airtable wait issue Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: enable mysql in ci Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: fix checkbox order for sqlite Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: disable quick tests Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: fix dbType env variable for CI Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: workspace API access error fix Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: enable SQLite CI CD Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: use DB_TYPE env variable Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: enable SQLite UT Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: isHub cleanup Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: add check for EE Timezone spec Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> chore: cleanup Signed-off-by: Pranav C <pranavxc@gmail.com> chore: cleanup Signed-off-by: Pranav C <pranavxc@gmail.com> test: EE check fix Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> chore: test correction Signed-off-by: Pranav C <pranavxc@gmail.com> chore: sync latest changes Signed-off-by: Pranav C <pranavxc@gmail.com> test: set EE=false Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: set NC Edition to community in workflow file Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> chore: update sdk build command Signed-off-by: Pranav C <pranavxc@gmail.com> refactor: i18n and other changes Signed-off-by: Pranav C <pranavxc@gmail.com> feat: new ui Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: sync tests Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: lint Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: shared view/base related bugs Signed-off-by: Pranav C <pranavxc@gmail.com> * test: checkbox verification sort order fix Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: fix sqlite reset Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: enable selfhosted runners Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * docs: table ops (draft) Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * Docs: screenshots for table-operations.md * refactor: introduce missing buttons Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: get all fields Signed-off-by: Pranav C <pranavxc@gmail.com> * test: UT fix- new data API response Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: EE is false Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: webhook lookup as string in CE Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * fix: include created_at and updated_at Signed-off-by: Pranav C <pranavxc@gmail.com> * test: fix UT newDataAPI response for PG Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * fix: separate api for webhook related plugins Signed-off-by: Pranav C <pranavxc@gmail.com> * test: msyql filter corrections Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: mysql group by test corrections Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: fix datatype for rating field in groupby spec for pg Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: kanban datatype correction Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: column edit for mysql- rating field Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: misc fixes Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: enable 4 workers Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: enable 2 workers per shard only Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * docs: table CRUD * Rename table-operations.md to table-crud.md * Create column-crud.md * docs: row CRUD * Rename row.md to row-crud.md * docs: project crud * docs: toolbar (skeleton) * refactor: single page UI and bug fixes Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: sync tests playwright Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: add missing dependency Signed-off-by: Pranav C <pranavxc@gmail.com> * feat: single page ui, test corrections Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: tests Signed-off-by: Pranav C <pranavxc@gmail.com> * test: project rename test correction Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: remove only Signed-off-by: Pranav C <pranavxc@gmail.com> * test: remove wrong import statement Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: delete option not visible in project context menu Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: move ws access within isEE() Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: fix groupby * test: groupby fix Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * docs: signup & landing page * docs: project crud * docs: project-crud misc * docs: toolbar fields * docs: toolbar / filters * docs: toolbar / group by * docs: toolbar / sort * docs: toolbar / row height * docs: filters additional options * docs: file re-order Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * docs: add links to column types * docs: code snippets * docs: links * docs: lookup * docs: rollup * docs: formula * docs: primary key * docs: display value * docs: development setup * docs: swagger * fix(nc-gui): encodeURIComponent for row id - closes: #6202 * docs: language * docs: expanded record * docs: import airtable * docs: airtable * docs: webhook * docs: revert file rename Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * docs: account settings * docs: audit * docs: meta management * docs: project settings * docs: shared base * docs: shared view * docs: meta sync * docs: team-auth * docs: views * docs: fix URL * docs: URL corrections * fix: shared base, view related bugs Signed-off-by: Pranav C <pranavxc@gmail.com> * test: EE check for WSaccess Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: exclude EE tests Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * fix: missing project delete closes #6215 Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: merge existing project meta if found closes #6216 Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: merge existing project meta if found closes #6216 Signed-off-by: Pranav C <pranavxc@gmail.com> --------- Signed-off-by: Pranav C <pranavxc@gmail.com> Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> Co-authored-by: Raju Udava <86527202+dstala@users.noreply.github.com> Co-authored-by: DarkPhoenix2704 <anbarasun123@gmail.com> Co-authored-by: Wing-Kam Wong <wingkwong.code@gmail.com> * refactor: docs and other bug fixes Signed-off-by: Pranav C <pranavxc@gmail.com> * feat: populate default project on super admin signup Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: include created project details in signup response if avail, missing Dockerfile Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: use custom function for resolving ts path aliases Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: add missing generate script Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: webpack build correction - ts path resolve Signed-off-by: Pranav C <pranavxc@gmail.com> --------- Signed-off-by: Pranav C <pranavxc@gmail.com> Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> Co-authored-by: mertmit <mertmit99@gmail.com> Co-authored-by: Raju Udava <86527202+dstala@users.noreply.github.com> Co-authored-by: DarkPhoenix2704 <anbarasun123@gmail.com> Co-authored-by: Wing-Kam Wong <wingkwong.code@gmail.com>
This commit is contained in:
502
packages/nc-gui/components/workspace/ProjectList.vue
Normal file
502
packages/nc-gui/components/workspace/ProjectList.vue
Normal file
@@ -0,0 +1,502 @@
|
||||
<script lang="ts" setup>
|
||||
import { Empty } from 'ant-design-vue'
|
||||
import type { ProjectType } from 'nocodb-sdk'
|
||||
import { ProjectStatus, WorkspaceUserRoles } from 'nocodb-sdk'
|
||||
import { nextTick } from '@vue/runtime-core'
|
||||
import { NcProjectType, isEeUI, navigateTo, storeToRefs, timeAgo, useGlobal, useWorkspace } from '#imports'
|
||||
import { useNuxtApp } from '#app'
|
||||
|
||||
const workspaceStore = useWorkspace()
|
||||
const { updateProjectTitle } = workspaceStore
|
||||
const { activePage } = storeToRefs(workspaceStore)
|
||||
|
||||
const projectsStore = useProjects()
|
||||
const { loadProjects } = projectsStore
|
||||
const { projectsList, isProjectsLoading } = storeToRefs(projectsStore)
|
||||
|
||||
const { navigateToProject } = useGlobal()
|
||||
|
||||
// const filteredProjects = computed(() => projects.value?.filter((p) => !p.deleted) || [])
|
||||
|
||||
const { $e, $jobs } = useNuxtApp()
|
||||
|
||||
const { isUIAllowed } = useUIPermission()
|
||||
|
||||
const { refreshCommandPalette } = useCommandPalette()
|
||||
|
||||
const showProjectDeleteModal = ref(false)
|
||||
const toBeDeletedProjectId = ref<string | undefined>()
|
||||
|
||||
const openProject = async (project: ProjectType) => {
|
||||
navigateToProject({
|
||||
projectId: project.id!,
|
||||
type: project.type as NcProjectType,
|
||||
})
|
||||
}
|
||||
|
||||
const roleAlias = {
|
||||
[WorkspaceUserRoles.OWNER]: 'Workspace Owner',
|
||||
[WorkspaceUserRoles.VIEWER]: 'Workspace Viewer',
|
||||
[WorkspaceUserRoles.CREATOR]: 'Workspace Creator',
|
||||
[WorkspaceUserRoles.EDITOR]: 'Workspace Editor',
|
||||
[WorkspaceUserRoles.COMMENTER]: 'Workspace Commenter',
|
||||
[ProjectRole.Creator]: 'Project Creator',
|
||||
[ProjectRole.Editor]: 'Project Editor',
|
||||
[ProjectRole.Viewer]: 'Project Viewer',
|
||||
[ProjectRole.Commenter]: 'Project Commenter',
|
||||
[ProjectRole.Owner]: 'Project Owner',
|
||||
}
|
||||
|
||||
const deleteProject = (project: ProjectType) => {
|
||||
$e('c:project:delete')
|
||||
|
||||
showProjectDeleteModal.value = true
|
||||
toBeDeletedProjectId.value = project.id
|
||||
}
|
||||
|
||||
const renameInput = ref<HTMLInputElement>()
|
||||
const enableEdit = (index: number) => {
|
||||
projectsList.value![index]!.temp_title = projectsList.value![index].title
|
||||
projectsList.value![index]!.edit = true
|
||||
nextTick(() => {
|
||||
renameInput.value?.focus()
|
||||
renameInput.value?.select()
|
||||
})
|
||||
}
|
||||
const disableEdit = (index: number) => {
|
||||
projectsList.value![index]!.temp_title = undefined
|
||||
projectsList.value![index]!.edit = false
|
||||
}
|
||||
|
||||
const customRow = (record: ProjectType) => ({
|
||||
onClick: async () => {
|
||||
openProject(record)
|
||||
|
||||
$e('a:project:open')
|
||||
},
|
||||
class: ['group'],
|
||||
})
|
||||
|
||||
const columns = computed(() => [
|
||||
{
|
||||
title: 'Project Name',
|
||||
dataIndex: 'title',
|
||||
sorter: {
|
||||
compare: (a, b) => a.title?.localeCompare(b.title),
|
||||
multiple: 5,
|
||||
},
|
||||
},
|
||||
...(isEeUI && activePage.value !== 'workspace'
|
||||
? [
|
||||
{
|
||||
title: 'Workspace Name',
|
||||
dataIndex: 'workspace_title',
|
||||
sorter: {
|
||||
compare: (a, b) => a.workspace_title?.localeCompare(b.workspace_title),
|
||||
multiple: 4,
|
||||
},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
title: 'Role',
|
||||
dataIndex: 'workspace_role',
|
||||
sorter: {
|
||||
compare: (a, b) => a - b,
|
||||
multiple: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Last Opened',
|
||||
dataIndex: 'last_accessed',
|
||||
sorter: {
|
||||
compare: (a, b) => new Date(b.last_accessed) - new Date(a.last_accessed),
|
||||
multiple: 2,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
title: '',
|
||||
dataIndex: 'id',
|
||||
hidden: true,
|
||||
width: '24px',
|
||||
style: {
|
||||
padding: 0,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const isMoveDlgOpen = ref(false)
|
||||
const selectedProjectToMove = ref()
|
||||
|
||||
const workspaceMoveProjectOnSuccess = async (workspaceId: string) => {
|
||||
isMoveDlgOpen.value = false
|
||||
navigateTo({
|
||||
query: {
|
||||
workspaceId,
|
||||
page: 'workspace',
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const moveProject = (project: ProjectType) => {
|
||||
selectedProjectToMove.value = project
|
||||
isMoveDlgOpen.value = true
|
||||
}
|
||||
|
||||
const isDuplicateDlgOpen = ref(false)
|
||||
const selectedProjectToDuplicate = ref()
|
||||
|
||||
const DlgProjectDuplicateOnOk = async (jobData: { id: string }) => {
|
||||
await loadProjects('workspace')
|
||||
|
||||
$jobs.subscribe({ id: jobData.id }, undefined, async (status: string) => {
|
||||
if (status === JobStatus.COMPLETED) {
|
||||
await loadProjects('workspace')
|
||||
refreshCommandPalette()
|
||||
} else if (status === JobStatus.FAILED) {
|
||||
message.error('Failed to duplicate project')
|
||||
await loadProjects('workspace')
|
||||
}
|
||||
})
|
||||
|
||||
$e('a:project:duplicate')
|
||||
}
|
||||
|
||||
const duplicateProject = (project: ProjectType) => {
|
||||
selectedProjectToDuplicate.value = project
|
||||
isDuplicateDlgOpen.value = true
|
||||
}
|
||||
|
||||
let clickCount = 0
|
||||
let timer: any = null
|
||||
const delay = 250
|
||||
|
||||
function onProjectTitleClick(index: number) {
|
||||
clickCount++
|
||||
if (clickCount === 1) {
|
||||
timer = setTimeout(function () {
|
||||
openProject(projectsList.value![index])
|
||||
clickCount = 0
|
||||
}, delay)
|
||||
} else {
|
||||
clearTimeout(timer)
|
||||
enableEdit(index)
|
||||
clickCount = 0
|
||||
}
|
||||
}
|
||||
|
||||
const setIcon = async (icon: string, project: ProjectType) => {
|
||||
try {
|
||||
const meta = {
|
||||
...((project.meta as object) || {}),
|
||||
icon,
|
||||
}
|
||||
|
||||
projectsStore.updateProject(project.id!, { meta: JSON.stringify(meta) })
|
||||
|
||||
$e('a:project:icon:navdraw', { icon })
|
||||
} catch (e: any) {
|
||||
message.error(await extractSdkResponseErrorMsg(e))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="!projectsList || projectsList?.length === 0 || isProjectsLoading"
|
||||
class="w-full flex flex-row justify-center items-center"
|
||||
style="height: calc(100vh - 16rem)"
|
||||
>
|
||||
<div v-if="isProjectsLoading">
|
||||
<GeneralLoader size="xlarge" />
|
||||
</div>
|
||||
<div v-else class="flex flex-col items-center gap-y-5">
|
||||
<MaterialSymbolsInboxOutlineRounded
|
||||
class="text-2xl text-primary"
|
||||
:class="{
|
||||
'h-8 w-8': activePage === 'workspace',
|
||||
'h-12 w-12': activePage !== 'workspace',
|
||||
}"
|
||||
/>
|
||||
<template v-if="activePage === 'workspace'">
|
||||
<div class="font-medium text-xl">Welcome to nocoDB</div>
|
||||
<div class="font-medium">Create your first Project!</div>
|
||||
</template>
|
||||
<template v-else-if="activePage === 'recent'">
|
||||
<div class="font-medium text-lg">No Recent Projects</div>
|
||||
</template>
|
||||
<template v-else-if="activePage === 'starred'">
|
||||
<div class="font-medium text-lg">No Starred Projects</div>
|
||||
</template>
|
||||
<template v-else-if="activePage === 'shared'">
|
||||
<div class="font-medium text-lg">No Shared Projects</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<a-table
|
||||
v-else
|
||||
v-model:data-source="projectsList"
|
||||
class="h-full"
|
||||
:class="{
|
||||
'full-height-table': activePage !== 'workspace',
|
||||
}"
|
||||
:custom-row="customRow"
|
||||
:columns="columns"
|
||||
:pagination="false"
|
||||
:scroll="{ y: 'calc(100% - 54px)' }"
|
||||
>
|
||||
<template #emptyText>
|
||||
<a-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" :description="$t('labels.noData')" />
|
||||
</template>
|
||||
|
||||
<template #bodyCell="{ column, text, record, index: i }">
|
||||
<template v-if="column.dataIndex === 'title'">
|
||||
<div class="flex items-center nc-project-title gap-2.5 max-w-full -ml-1.5">
|
||||
<div class="flex items-center gap-2 text-center">
|
||||
<LazyGeneralEmojiPicker
|
||||
:key="record.id"
|
||||
:emoji="record.meta?.icon"
|
||||
size="small"
|
||||
readonly
|
||||
@emoji-selected="setIcon($event, record)"
|
||||
>
|
||||
<GeneralProjectIcon :type="record.type" />
|
||||
</LazyGeneralEmojiPicker>
|
||||
<!-- todo: replace with switch -->
|
||||
</div>
|
||||
|
||||
<div class="min-w-10">
|
||||
<input
|
||||
v-if="record.edit"
|
||||
ref="renameInput"
|
||||
v-model="record.temp_title"
|
||||
class="!leading-none p-1 bg-transparent max-w-full !w-auto"
|
||||
autofocus
|
||||
@click.stop
|
||||
@blur="disableEdit(i)"
|
||||
@keydown.enter="updateProjectTitle(record)"
|
||||
@keydown.esc="disableEdit(i)"
|
||||
/>
|
||||
|
||||
<div
|
||||
v-else
|
||||
:title="record.title"
|
||||
class="whitespace-nowrap overflow-hidden overflow-ellipsis cursor-pointer"
|
||||
@click.stop="onProjectTitleClick(i)"
|
||||
>
|
||||
{{ record.title }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div v-if="!record.edit" class="nc-click-transition-1" @click.stop> -->
|
||||
<!-- <MdiStar v-if="record.starred" class="text-yellow-400 cursor-pointer" @click="removeFromFavourite(record.id)" /> -->
|
||||
<!-- <MdiStarOutline -->
|
||||
<!-- v-else -->
|
||||
<!-- class="opacity-0 group-hover:opacity-100 transition transition-opacity text-yellow-400 cursor-pointer" -->
|
||||
<!-- @click="addToFavourite(record.id)" -->
|
||||
<!-- /> -->
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-if="column.dataIndex === 'last_accessed'" class="text-xs text-gray-500">
|
||||
{{ text ? timeAgo(text) : 'Newly invited' }}
|
||||
</div>
|
||||
|
||||
<div v-if="column.dataIndex === 'workspace_title'" class="text-xs text-gray-500">
|
||||
<span v-if="text" class="text-xs text-gray-500 whitespace-nowrap overflow-hidden overflow-ellipsis">
|
||||
<nuxt-link
|
||||
:to="{
|
||||
query: {
|
||||
page: 'workspace',
|
||||
workspaceId: 'default',
|
||||
},
|
||||
}"
|
||||
class="!text-gray-500 !no-underline !hover:underline !hover:text-gray-500"
|
||||
@click.stop
|
||||
>
|
||||
{{ text }}
|
||||
</nuxt-link>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div v-if="column.dataIndex === 'workspace_role'" class="flex flex-row text-xs justify-between text-gray-500">
|
||||
<div class="flex">
|
||||
{{ roleAlias[record.workspace_role || record.project_role] }}
|
||||
</div>
|
||||
<div class="flex items-center gap-2"></div>
|
||||
</div>
|
||||
|
||||
<template v-if="column.dataIndex === 'id'">
|
||||
<a-dropdown
|
||||
v-if="isUIAllowed('projectActionMenu', true, [record.workspace_role, record.project_role].join())"
|
||||
:trigger="['click']"
|
||||
>
|
||||
<div @click.stop>
|
||||
<template v-if="record.status === ProjectStatus.JOB">
|
||||
<component :is="iconMap.reload" class="animate-infinite animate-spin" />
|
||||
</template>
|
||||
<GeneralIcon v-else icon="threeDotVertical" class="outline-0 nc-workspace-menu nc-click-transition" />
|
||||
</div>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item @click="enableEdit(i)">
|
||||
<div class="nc-menu-item-wrapper">
|
||||
<GeneralIcon icon="edit" class="text-gray-700" />
|
||||
{{ $t('general.rename') }} {{ $t('objects.project') }}
|
||||
</div>
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
v-if="
|
||||
record.type === NcProjectType.DB &&
|
||||
isUIAllowed('duplicateProject', true, [record.workspace_role, record.project_role].join())
|
||||
"
|
||||
@click="duplicateProject(record)"
|
||||
>
|
||||
<div class="nc-menu-item-wrapper">
|
||||
<GeneralIcon icon="duplicate" class="text-gray-700" />
|
||||
{{ $t('general.duplicate') }} {{ $t('objects.project') }}
|
||||
</div>
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
v-if="false && isUIAllowed('moveProject', true, [record.workspace_role, record.project_role].join())"
|
||||
@click="moveProject(record)"
|
||||
>
|
||||
<div class="nc-menu-item-wrapper">
|
||||
<GeneralIcon icon="move" class="text-gray-700" />
|
||||
{{ $t('general.move') }} {{ $t('objects.project') }}
|
||||
</div>
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
v-if="isUIAllowed('projectDelete', true, [record.workspace_role, record.project_role].join())"
|
||||
@click="deleteProject(record)"
|
||||
>
|
||||
<div class="nc-menu-item-wrapper text-red-500">
|
||||
<GeneralIcon icon="delete" />
|
||||
{{ $t('general.delete') }} {{ $t('objects.project') }}
|
||||
</div>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
<div v-else></div>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<DlgProjectDelete v-if="toBeDeletedProjectId" v-model:visible="showProjectDeleteModal" :project-id="toBeDeletedProjectId" />
|
||||
<WorkspaceMoveProjectDlg
|
||||
v-if="selectedProjectToMove"
|
||||
v-model="isMoveDlgOpen"
|
||||
:project="selectedProjectToMove"
|
||||
@success="workspaceMoveProjectOnSuccess"
|
||||
/>
|
||||
<DlgProjectDuplicate
|
||||
v-if="selectedProjectToDuplicate"
|
||||
v-model="isDuplicateDlgOpen"
|
||||
:project="selectedProjectToDuplicate"
|
||||
:on-ok="DlgProjectDuplicateOnOk"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.ant-table-cell:first-child) {
|
||||
@apply !pl-6;
|
||||
}
|
||||
|
||||
:deep(.ant-table-cell:lst-child) {
|
||||
@apply !plr6;
|
||||
}
|
||||
|
||||
:deep(th.ant-table-cell) {
|
||||
@apply font-weight-400;
|
||||
}
|
||||
|
||||
:deep(.ant-table-wrapper) {
|
||||
.ant-spin-nested-loading,
|
||||
.ant-spin-container,
|
||||
.ant-table,
|
||||
.ant-table-container {
|
||||
@apply h-full;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-table-row) {
|
||||
@apply cursor-pointer;
|
||||
}
|
||||
|
||||
:deep(th.ant-table-cell) {
|
||||
@apply !text-gray-500;
|
||||
}
|
||||
|
||||
:deep(.ant-table-cell:last-child) {
|
||||
@apply !p-0;
|
||||
}
|
||||
:deep(.ant-table-row:last-child > td) {
|
||||
@apply !border-b-0;
|
||||
}
|
||||
|
||||
:deep(.ant-table-cell:nth-child(2)) {
|
||||
@apply !p-0;
|
||||
}
|
||||
|
||||
:deep(.ant-table-body) {
|
||||
@apply !p-0 w-full !overflow-y-auto;
|
||||
}
|
||||
|
||||
:deep(.ant-table-thead > tr > th) {
|
||||
@apply !bg-transparent;
|
||||
}
|
||||
|
||||
:deep(.ant-table-cell::before) {
|
||||
width: 0 !important;
|
||||
}
|
||||
|
||||
:deep(.ant-table-column-sorter) {
|
||||
@apply text-gray-100 !hover:text-gray-300;
|
||||
}
|
||||
|
||||
:deep(.ant-table-column-sorters) {
|
||||
@apply !justify-start !gap-x-2;
|
||||
}
|
||||
:deep(.ant-table-column-sorters > .ant-table-column-title) {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
:deep(.full-height-table .ant-table-body) {
|
||||
height: calc(100vh - var(--topbar-height) - 9rem) !important;
|
||||
}
|
||||
:deep(.ant-table-body) {
|
||||
overflow-y: overlay;
|
||||
height: calc(100vh - var(--topbar-height) - 13.45rem);
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #f6f6f600 !important;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #f6f6f600;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background: #f6f6f600;
|
||||
}
|
||||
}
|
||||
:deep(.ant-table-body) {
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #f6f6f600 !important;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: rgb(215, 215, 215);
|
||||
}
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background: rgb(203, 203, 203);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user