mirror of https://github.com/nocodb/nocodb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
4.4 KiB
136 lines
4.4 KiB
<script lang="ts" setup> |
|
import { Modal } from 'ant-design-vue' |
|
import type { ProjectType } from 'nocodb-sdk' |
|
import { useToast } from 'vue-toastification' |
|
import { computed, onMounted } from '#imports' |
|
import { extractSdkResponseErrorMsg } from '~/utils/errorUtils' |
|
|
|
import MdiDeleteOutline from '~icons/mdi/delete-outline' |
|
import MdiEditOutline from '~icons/mdi/edit-outline' |
|
import MdiRefresh from '~icons/mdi/refresh' |
|
import MdiMenuDown from '~icons/mdi/menu-down' |
|
import MdiPlus from '~icons/mdi/plus' |
|
import MdiDatabaseOutline from '~icons/mdi/database-outline' |
|
|
|
const { $api } = useNuxtApp() |
|
const toast = useToast() |
|
|
|
const filterQuery = ref('') |
|
const loading = ref(true) |
|
const projects = ref() |
|
|
|
const loadProjects = async () => { |
|
loading.value = true |
|
const response = await $api.project.list({}) |
|
projects.value = response.list |
|
loading.value = false |
|
} |
|
|
|
const filteredProjects = computed(() => { |
|
return projects.value.filter( |
|
(project) => !filterQuery.value || project.title?.toLowerCase?.().includes(filterQuery.value.toLowerCase()), |
|
) |
|
}) |
|
|
|
const deleteProject = (project: ProjectType) => { |
|
Modal.confirm({ |
|
title: 'Do you want to delete the project?', |
|
content: 'Some descriptions', |
|
okText: 'Yes', |
|
okType: 'danger', |
|
cancelText: 'No', |
|
async onOk() { |
|
try { |
|
await $api.project.delete(project.id as string) |
|
projects.splice(projects.indexOf(project), 1) |
|
} catch (e) { |
|
toast.error(await extractSdkResponseErrorMsg(e)) |
|
} |
|
}, |
|
}) |
|
} |
|
|
|
onMounted(() => { |
|
loadProjects() |
|
}) |
|
</script> |
|
|
|
<template> |
|
<NuxtLayout> |
|
<a-card class="mx-auto mt-5 !max-w-[600px] shadow-lg"> |
|
<h1 class="text-center text-4xl pa-2 nc-project-page-title flex align-center justify-center gap-2"> |
|
<!-- My Projects --> |
|
<b>{{ $t('title.myProject') }}</b> |
|
|
|
<MdiRefresh class="text-sm text-gray-500 hover:text-primary mt-1 cursor-pointer" @click="loadProjects"></MdiRefresh> |
|
</h1> |
|
|
|
<div class="flex mb-6"> |
|
<a-input-search |
|
v-model:value="filterQuery" |
|
class="max-w-[200px] nc-project-page-search" |
|
:placeholder="$t('activity.searchProject')" |
|
></a-input-search> |
|
<div class="flex-grow"></div> |
|
|
|
<a-dropdown @click.stop> |
|
<a-button |
|
> |
|
<div class="flex align-center" >{{ $t('title.newProj') }} |
|
<MdiMenuDown class="menu-icon" /> |
|
</div> |
|
</a-button> |
|
|
|
<template #overlay> |
|
<a-menu> |
|
<div |
|
class="grid grid-cols-12 cursor-pointer hover:bg-gray-200 flex items-center p-2" |
|
@click="navigateTo('/project/create')" |
|
> |
|
<MdiPlus class="col-span-2 mr-1 mt-[1px] text-primary text-lg" /> |
|
<div class="col-span-10 text-sm xl:text-md">{{ $t('activity.createProject') }}</div> |
|
</div> |
|
<div |
|
class="grid grid-cols-12 cursor-pointer hover:bg-gray-200 flex items-center p-2" |
|
@click="navigateTo('/project/create-external')" |
|
> |
|
<MdiDatabaseOutline class="col-span-2 mr-1 mt-[1px] text-green-500 text-lg" /> |
|
<div class="col-span-10 text-sm xl:text-md" v-html="$t('activity.createProjectExtended.extDB')" /> |
|
</div> |
|
</a-menu> |
|
</template> |
|
</a-dropdown> |
|
</div> |
|
|
|
<div v-if="loading"> |
|
<a-skeleton /> |
|
</div> |
|
|
|
<a-table v-else :data-source="filteredProjects" :pagination="{ position: ['bottomCenter'] }"> |
|
<a-table-column key="title" title="Title" data-index="title"> |
|
<template #default="{ text }"> |
|
<div class="capitalize !w-[400px] overflow-hidden overflow-ellipsis whitespace-nowrap" :title="text">{{ text }}</div> |
|
</template> |
|
</a-table-column> |
|
<a-table-column key="id" title="Actions" data-index="id"> |
|
<template #default="{ text }"> |
|
<div class="flex align-center"> |
|
<MdiEditOutline class="nc-action-btn" @click.stop="navigateTo(`/project/${text}`)" /> |
|
<MdiDeleteOutline class="nc-action-btn" @click.stop="deleteProject(text)" /> |
|
</div> |
|
</template> |
|
</a-table-column> |
|
</a-table> |
|
</a-card> |
|
</NuxtLayout> |
|
</template> |
|
|
|
<style scoped> |
|
.nc-action-btn { |
|
@apply text-gray-500 hover:text-primary mr-2 cursor-pointer p-2 w-[30px] h-[30px] hover:bg-gray-300/50 rounded-full; |
|
} |
|
|
|
:deep(.ant-table-cell) { |
|
@apply py-1; |
|
} |
|
</style>
|
|
|