2023-11-10 20:34:36 +08:00
|
|
|
<template>
|
2023-12-01 07:01:08 +08:00
|
|
|
<DataTable :columnDefs="columnDefs"
|
2024-01-15 21:44:14 +08:00
|
|
|
tableId="ProjectList"
|
2023-12-01 07:01:08 +08:00
|
|
|
:dataUrl="dataSource"
|
|
|
|
:reloadingTable="reloadingTable"
|
|
|
|
:toolbarActions="toolbarActions"
|
|
|
|
:actionsUrl="actionsUrl"
|
|
|
|
:activePageUrl="activePageUrl"
|
|
|
|
:archivedPageUrl="archivedPageUrl"
|
|
|
|
:currentViewMode="currentViewMode"
|
2024-01-23 18:08:42 +08:00
|
|
|
scrollMode="infinite"
|
2023-12-01 07:01:08 +08:00
|
|
|
:filters="filters"
|
|
|
|
:viewRenders="viewRenders"
|
|
|
|
@tableReloaded="reloadingTable = false"
|
|
|
|
@comments="openComments"
|
|
|
|
@archive="archive"
|
|
|
|
@restore="restore"
|
|
|
|
@edit="edit"
|
|
|
|
@create="create"
|
|
|
|
@create_folder="createFolder"
|
|
|
|
@delete_folders="deleteFolder"
|
|
|
|
@export="exportProjects"
|
|
|
|
@move="move"
|
2023-12-05 03:59:16 +08:00
|
|
|
@access="access"
|
2023-12-01 07:01:08 +08:00
|
|
|
>
|
|
|
|
<template #card="data">
|
|
|
|
<ProjectCard :params="data.params" :dtComponent="data.dtComponent" ></ProjectCard>
|
|
|
|
</template>
|
|
|
|
</DataTable>
|
2023-12-11 16:18:22 +08:00
|
|
|
<a href="#" ref="commentButton" class="open-comments-sidebar hidden"
|
|
|
|
data-turbolinks="false" data-object-type="Project" data-object-id=""></a>
|
2023-12-01 07:01:08 +08:00
|
|
|
<ConfirmationModal
|
|
|
|
:title="i18n.t('projects.index.modal_delete_folders.title')"
|
|
|
|
:description="folderDeleteDescription"
|
2023-12-05 03:59:16 +08:00
|
|
|
confirmClass="btn btn-danger"
|
2023-12-01 07:01:08 +08:00
|
|
|
:confirmText="i18n.t('projects.index.modal_delete_folders.confirm_button')"
|
|
|
|
ref="deleteFolderModal"
|
|
|
|
></ConfirmationModal>
|
|
|
|
<ConfirmationModal
|
|
|
|
:title="i18n.t('projects.export_projects.modal_title')"
|
|
|
|
:description="exportDescription"
|
2023-12-05 03:59:16 +08:00
|
|
|
confirmClass="btn btn-primary"
|
2023-12-01 07:01:08 +08:00
|
|
|
:confirmText="i18n.t('projects.export_projects.export_button')"
|
|
|
|
ref="exportModal"
|
|
|
|
></ConfirmationModal>
|
2024-05-23 21:10:45 +08:00
|
|
|
<ExportLimitExceededModal v-if="exportLimitExceded" :description="exportDescription" @close="exportLimitExceded = false"/>
|
2023-12-11 16:18:22 +08:00
|
|
|
<EditProjectModal v-if="editProject" :userRolesUrl="userRolesUrl"
|
2024-03-04 23:04:11 +08:00
|
|
|
:project="editProject" @close="editProject = null" @update="updateTable(); updateNavigator()" />
|
2023-12-11 16:18:22 +08:00
|
|
|
<EditFolderModal v-if="editFolder" :folder="editFolder"
|
2024-03-04 23:04:11 +08:00
|
|
|
@close="editFolder = null" @update="updateTable(); updateNavigator()" />
|
2023-12-11 16:18:22 +08:00
|
|
|
<NewProjectModal v-if="newProject" :createUrl="createUrl"
|
|
|
|
:currentFolderId="currentFolderId" :userRolesUrl="userRolesUrl"
|
2024-03-04 23:04:11 +08:00
|
|
|
@close="newProject = false" @create="updateTable(); updateNavigator()" />
|
2023-12-11 16:18:22 +08:00
|
|
|
<NewFolderModal v-if="newFolder" :createFolderUrl="createFolderUrl"
|
|
|
|
:currentFolderId="currentFolderId" :viewMode="currentViewMode"
|
2024-03-04 23:04:11 +08:00
|
|
|
@close="newFolder = false" @create="updateTable(); updateNavigator()" />
|
2023-12-11 16:18:22 +08:00
|
|
|
<MoveModal v-if="objectsToMove" :moveToUrl="moveToUrl"
|
|
|
|
:selectedObjects="objectsToMove" :foldersTreeUrl="foldersTreeUrl"
|
2024-03-04 23:04:11 +08:00
|
|
|
@close="objectsToMove = null" @move="updateTable(); updateNavigator(true)" />
|
2023-12-11 16:18:22 +08:00
|
|
|
<AccessModal v-if="accessModalParams" :params="accessModalParams"
|
|
|
|
@close="accessModalParams = null" @refresh="this.reloadingTable = true" />
|
2023-11-10 20:34:36 +08:00
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
2023-12-11 16:18:22 +08:00
|
|
|
/* global HelperModule */
|
|
|
|
|
2023-11-10 20:34:36 +08:00
|
|
|
import axios from '../../packs/custom_axios.js';
|
|
|
|
|
2023-12-11 16:18:22 +08:00
|
|
|
import DataTable from '../shared/datatable/table.vue';
|
|
|
|
import UsersRenderer from './renderers/users.vue';
|
2024-09-03 19:22:57 +08:00
|
|
|
import NameRenderer from './renderers/name.vue';
|
2024-02-28 20:31:42 +08:00
|
|
|
import CommentsRenderer from '../shared/datatable/renderers/comments.vue';
|
2023-12-11 16:18:22 +08:00
|
|
|
import ProjectCard from './card.vue';
|
|
|
|
import ConfirmationModal from '../shared/confirmation_modal.vue';
|
|
|
|
import EditProjectModal from './modals/edit.vue';
|
|
|
|
import EditFolderModal from './modals/edit_folder.vue';
|
|
|
|
import NewProjectModal from './modals/new.vue';
|
|
|
|
import NewFolderModal from './modals/new_folder.vue';
|
|
|
|
import MoveModal from './modals/move.vue';
|
|
|
|
import AccessModal from '../shared/access_modal/modal.vue';
|
2024-05-23 21:10:45 +08:00
|
|
|
import ExportLimitExceededModal from './modals/export_limit_exceeded_modal.vue';
|
2023-11-10 20:34:36 +08:00
|
|
|
|
|
|
|
export default {
|
|
|
|
name: 'ProjectsList',
|
|
|
|
components: {
|
|
|
|
DataTable,
|
|
|
|
UsersRenderer,
|
2024-09-03 19:22:57 +08:00
|
|
|
NameRenderer,
|
2023-12-01 07:01:08 +08:00
|
|
|
ProjectCard,
|
|
|
|
ConfirmationModal,
|
|
|
|
EditProjectModal,
|
|
|
|
EditFolderModal,
|
|
|
|
NewProjectModal,
|
|
|
|
NewFolderModal,
|
2023-12-05 03:59:16 +08:00
|
|
|
MoveModal,
|
2024-05-23 21:10:45 +08:00
|
|
|
AccessModal,
|
|
|
|
ExportLimitExceededModal
|
2023-11-10 20:34:36 +08:00
|
|
|
},
|
|
|
|
props: {
|
2023-12-01 07:01:08 +08:00
|
|
|
dataSource: { type: String, required: true },
|
|
|
|
actionsUrl: { type: String, required: true },
|
|
|
|
createUrl: { type: String },
|
|
|
|
createFolderUrl: { type: String },
|
|
|
|
activePageUrl: { type: String },
|
|
|
|
archivedPageUrl: { type: String },
|
|
|
|
currentViewMode: { type: String, required: true },
|
|
|
|
usersFilterUrl: { type: String },
|
|
|
|
userRolesUrl: { type: String },
|
|
|
|
currentFolderId: { type: String },
|
|
|
|
foldersTreeUrl: { type: String },
|
2024-02-19 20:01:37 +08:00
|
|
|
moveToUrl: { type: String }
|
2023-11-10 20:34:36 +08:00
|
|
|
},
|
|
|
|
data() {
|
|
|
|
return {
|
2023-12-05 03:59:16 +08:00
|
|
|
accessModalParams: null,
|
2023-12-01 07:01:08 +08:00
|
|
|
newProject: false,
|
|
|
|
newFolder: false,
|
|
|
|
editProject: null,
|
|
|
|
editFolder: null,
|
|
|
|
objectsToMove: null,
|
2023-11-10 20:34:36 +08:00
|
|
|
reloadingTable: false,
|
2024-05-23 21:10:45 +08:00
|
|
|
exportLimitExceded: false,
|
2023-12-01 07:01:08 +08:00
|
|
|
folderDeleteDescription: '',
|
2024-02-20 07:35:38 +08:00
|
|
|
exportDescription: ''
|
2023-12-11 16:18:22 +08:00
|
|
|
};
|
2023-11-10 20:34:36 +08:00
|
|
|
},
|
|
|
|
computed: {
|
2024-02-20 07:35:38 +08:00
|
|
|
columnDefs() {
|
|
|
|
const columns = [{
|
|
|
|
field: 'name',
|
|
|
|
flex: 1,
|
|
|
|
headerName: this.i18n.t('projects.index.card.name'),
|
|
|
|
sortable: true,
|
2024-09-03 19:22:57 +08:00
|
|
|
cellRenderer: 'NameRenderer'
|
2024-02-20 07:35:38 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
field: 'code',
|
|
|
|
headerName: this.i18n.t('projects.index.card.id'),
|
2024-02-20 17:37:17 +08:00
|
|
|
sortable: true
|
2024-02-20 07:35:38 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
field: 'created_at',
|
|
|
|
headerName: this.i18n.t('projects.index.card.start_date'),
|
2024-02-20 17:37:17 +08:00
|
|
|
sortable: true
|
2024-02-20 07:35:38 +08:00
|
|
|
},
|
2024-02-28 20:31:42 +08:00
|
|
|
{
|
|
|
|
field: 'updated_at',
|
|
|
|
headerName: this.i18n.t('projects.index.card.updated_at'),
|
|
|
|
sortable: true
|
|
|
|
},
|
2024-02-20 07:35:38 +08:00
|
|
|
{
|
|
|
|
field: 'users',
|
|
|
|
headerName: this.i18n.t('projects.index.card.users'),
|
|
|
|
cellRenderer: 'UsersRenderer',
|
2024-03-04 17:56:46 +08:00
|
|
|
sortable: true,
|
2024-02-20 07:35:38 +08:00
|
|
|
minWidth: 210,
|
|
|
|
notSelectable: true
|
2024-02-28 20:31:42 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
field: 'comments',
|
|
|
|
headerName: this.i18n.t('projects.index.card.comments'),
|
2024-03-04 17:56:46 +08:00
|
|
|
sortable: true,
|
2024-02-28 20:31:42 +08:00
|
|
|
cellRenderer: CommentsRenderer,
|
|
|
|
notSelectable: true
|
2024-02-20 17:37:17 +08:00
|
|
|
}];
|
2024-02-20 07:35:38 +08:00
|
|
|
|
|
|
|
if (this.currentViewMode === 'archived') {
|
|
|
|
columns.push({
|
|
|
|
field: 'archived_on',
|
|
|
|
headerName: this.i18n.t('projects.index.card.archived_date'),
|
|
|
|
sortable: true
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return columns;
|
|
|
|
},
|
2023-12-01 07:01:08 +08:00
|
|
|
viewRenders() {
|
|
|
|
return [
|
2023-12-11 16:18:22 +08:00
|
|
|
{ type: 'table' },
|
2024-02-19 20:01:37 +08:00
|
|
|
{ type: 'cards' }
|
2023-12-11 16:18:22 +08:00
|
|
|
];
|
2023-12-01 07:01:08 +08:00
|
|
|
},
|
2023-11-10 20:34:36 +08:00
|
|
|
toolbarActions() {
|
2023-12-11 16:18:22 +08:00
|
|
|
const left = [];
|
2023-12-01 07:01:08 +08:00
|
|
|
if (this.createUrl && this.currentViewMode !== 'archived') {
|
2023-11-10 20:34:36 +08:00
|
|
|
left.push({
|
|
|
|
name: 'create',
|
|
|
|
icon: 'sn-icon sn-icon-new-task',
|
|
|
|
label: this.i18n.t('projects.index.new'),
|
|
|
|
type: 'emit',
|
|
|
|
path: this.createUrl,
|
2024-02-19 20:01:37 +08:00
|
|
|
buttonStyle: 'btn btn-primary'
|
2023-12-11 16:18:22 +08:00
|
|
|
});
|
2023-11-10 20:34:36 +08:00
|
|
|
}
|
|
|
|
if (this.createFolderUrl) {
|
|
|
|
left.push({
|
|
|
|
name: 'create_folder',
|
|
|
|
icon: 'sn-icon sn-icon-folder',
|
|
|
|
label: this.i18n.t('projects.index.new_folder'),
|
|
|
|
type: 'emit',
|
|
|
|
path: this.createFolderUrl,
|
2024-02-19 20:01:37 +08:00
|
|
|
buttonStyle: 'btn btn-light'
|
2023-12-11 16:18:22 +08:00
|
|
|
});
|
2023-11-10 20:34:36 +08:00
|
|
|
}
|
|
|
|
return {
|
2023-12-11 16:18:22 +08:00
|
|
|
left,
|
2024-02-19 20:01:37 +08:00
|
|
|
right: []
|
2023-12-11 16:18:22 +08:00
|
|
|
};
|
2023-11-24 18:08:28 +08:00
|
|
|
},
|
|
|
|
filters() {
|
2023-12-11 16:18:22 +08:00
|
|
|
const filters = [
|
|
|
|
{
|
|
|
|
key: 'query',
|
2024-02-19 20:01:37 +08:00
|
|
|
type: 'Text'
|
2023-12-11 16:18:22 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
key: 'created_at',
|
|
|
|
type: 'DateRange',
|
2024-02-19 20:01:37 +08:00
|
|
|
label: this.i18n.t('filters_modal.created_on.label')
|
|
|
|
}
|
2023-12-11 16:18:22 +08:00
|
|
|
];
|
2023-11-24 18:08:28 +08:00
|
|
|
|
|
|
|
if (this.currentViewMode === 'archived') {
|
|
|
|
filters.push({
|
|
|
|
key: 'archived_at',
|
|
|
|
type: 'DateRange',
|
2024-02-19 20:01:37 +08:00
|
|
|
label: this.i18n.t('filters_modal.archived_on.label')
|
2023-12-11 16:18:22 +08:00
|
|
|
});
|
2023-11-24 18:08:28 +08:00
|
|
|
}
|
|
|
|
|
2023-12-01 07:01:08 +08:00
|
|
|
filters.push({
|
|
|
|
key: 'members',
|
|
|
|
type: 'Select',
|
|
|
|
optionsUrl: this.usersFilterUrl,
|
|
|
|
optionRenderer: this.usersFilterRenderer,
|
|
|
|
labelRenderer: this.usersFilterRenderer,
|
2023-12-11 16:18:22 +08:00
|
|
|
label: this.i18n.t('projects.index.filters_modal.members.label'),
|
2024-02-19 20:01:37 +08:00
|
|
|
placeholder: this.i18n.t('projects.index.filters_modal.members.placeholder')
|
2023-12-11 16:18:22 +08:00
|
|
|
});
|
2023-12-01 07:01:08 +08:00
|
|
|
|
2023-11-24 18:08:28 +08:00
|
|
|
filters.push({
|
|
|
|
key: 'folder_search',
|
|
|
|
type: 'Checkbox',
|
2024-02-19 20:01:37 +08:00
|
|
|
label: this.i18n.t('projects.index.filters_modal.folders.label')
|
2023-12-11 16:18:22 +08:00
|
|
|
});
|
2023-11-24 18:08:28 +08:00
|
|
|
|
2023-12-11 16:18:22 +08:00
|
|
|
return filters;
|
2023-12-12 19:17:38 +08:00
|
|
|
}
|
2023-11-10 20:34:36 +08:00
|
|
|
},
|
|
|
|
methods: {
|
2023-12-01 07:01:08 +08:00
|
|
|
usersFilterRenderer(option) {
|
|
|
|
return `<div class="flex items-center gap-2">
|
|
|
|
<img src="${option[2].avatar_url}" class="rounded-full w-6 h-6" />
|
2024-03-04 01:13:09 +08:00
|
|
|
<span title="${option[1]}" class="truncate">${option[1]}</span>
|
2023-12-11 16:18:22 +08:00
|
|
|
</div>`;
|
2023-12-01 07:01:08 +08:00
|
|
|
},
|
|
|
|
openComments(_params, rows) {
|
2024-02-27 18:23:23 +08:00
|
|
|
$(this.$refs.commentButton).data('objectId', rows[0].id);
|
2023-12-01 07:01:08 +08:00
|
|
|
this.$refs.commentButton.click();
|
|
|
|
},
|
2023-12-05 03:59:16 +08:00
|
|
|
access(event, rows) {
|
|
|
|
this.accessModalParams = {
|
|
|
|
object: rows[0],
|
2024-02-19 20:01:37 +08:00
|
|
|
roles_path: this.userRolesUrl
|
2023-12-11 16:18:22 +08:00
|
|
|
};
|
2023-12-05 03:59:16 +08:00
|
|
|
},
|
2023-12-01 07:01:08 +08:00
|
|
|
async archive(event, rows) {
|
2024-01-18 08:41:57 +08:00
|
|
|
axios.post(event.path, { project_ids: rows.map((row) => row.id) }).then((response) => {
|
|
|
|
this.reloadingTable = true;
|
|
|
|
HelperModule.flashAlertMsg(response.data.message, 'success');
|
2024-03-12 20:59:47 +08:00
|
|
|
this.updateNavigator(false);
|
2024-01-18 08:41:57 +08:00
|
|
|
}).catch((error) => {
|
|
|
|
HelperModule.flashAlertMsg(error.response.data.error, 'danger');
|
|
|
|
});
|
2023-12-01 07:01:08 +08:00
|
|
|
},
|
|
|
|
restore(event, rows) {
|
|
|
|
axios.post(event.path, { project_ids: rows.map((row) => row.id) }).then((response) => {
|
2023-12-11 16:18:22 +08:00
|
|
|
this.reloadingTable = true;
|
2023-12-01 07:01:08 +08:00
|
|
|
HelperModule.flashAlertMsg(response.data.message, 'success');
|
2024-03-12 20:59:47 +08:00
|
|
|
this.updateNavigator(false);
|
2023-12-01 07:01:08 +08:00
|
|
|
}).catch((error) => {
|
|
|
|
HelperModule.flashAlertMsg(error.response.data.error, 'danger');
|
|
|
|
});
|
|
|
|
},
|
|
|
|
edit(event, rows) {
|
|
|
|
if (rows[0].folder) {
|
2023-12-11 16:18:22 +08:00
|
|
|
[this.editFolder] = rows;
|
|
|
|
return;
|
2023-12-01 07:01:08 +08:00
|
|
|
}
|
2023-12-11 16:18:22 +08:00
|
|
|
[this.editProject] = rows;
|
2023-12-01 07:01:08 +08:00
|
|
|
},
|
|
|
|
create() {
|
|
|
|
this.newProject = true;
|
|
|
|
},
|
|
|
|
createFolder() {
|
|
|
|
this.newFolder = true;
|
|
|
|
},
|
|
|
|
updateTable() {
|
|
|
|
this.editProject = null;
|
|
|
|
this.editFolder = null;
|
|
|
|
this.newProject = false;
|
|
|
|
this.newFolder = false;
|
|
|
|
this.objectsToMove = null;
|
|
|
|
this.reloadingTable = true;
|
2024-05-23 21:10:45 +08:00
|
|
|
this.exportLimitExceded = false;
|
2023-12-01 07:01:08 +08:00
|
|
|
},
|
2024-03-04 23:04:11 +08:00
|
|
|
updateNavigator(withExpanedChildren = false) {
|
|
|
|
window.navigatorContainer.reloadNavigator(withExpanedChildren);
|
|
|
|
},
|
2023-12-01 07:01:08 +08:00
|
|
|
async deleteFolder(event, rows) {
|
2023-12-11 16:18:22 +08:00
|
|
|
const description = `
|
|
|
|
<p>${this.i18n.t('projects.index.modal_delete_folders.description_1_html', { number: rows.length })}</p>
|
|
|
|
<p>${this.i18n.t('projects.index.modal_delete_folders.description_2')}</p>`;
|
2023-12-01 07:01:08 +08:00
|
|
|
this.folderDeleteDescription = description;
|
|
|
|
const ok = await this.$refs.deleteFolderModal.show();
|
|
|
|
if (ok) {
|
|
|
|
axios.post(event.path, { project_folder_ids: rows.map((row) => row.id) }).then((response) => {
|
2023-12-11 16:18:22 +08:00
|
|
|
this.reloadingTable = true;
|
2023-12-01 07:01:08 +08:00
|
|
|
HelperModule.flashAlertMsg(response.data.message, 'success');
|
|
|
|
}).catch((error) => {
|
|
|
|
HelperModule.flashAlertMsg(error.response.data.error, 'danger');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
async exportProjects(event, rows) {
|
2024-03-13 23:23:38 +08:00
|
|
|
if (event.number_of_projects === 0) {
|
|
|
|
HelperModule.flashAlertMsg(this.i18n.t('projects.export_projects.zero_projects_flash'), 'danger');
|
2024-05-23 21:10:45 +08:00
|
|
|
} else if (event.number_of_request_left > 0) {
|
2024-03-13 23:23:38 +08:00
|
|
|
this.exportDescription = event.message;
|
|
|
|
const ok = await this.$refs.exportModal.show();
|
|
|
|
if (ok) {
|
|
|
|
axios.post(event.path, {
|
|
|
|
project_ids: rows.filter((row) => !row.folder).map((row) => row.id),
|
|
|
|
project_folder_ids: rows.filter((row) => row.folder).map((row) => row.id)
|
|
|
|
}).then((response) => {
|
|
|
|
this.reloadingTable = true;
|
2024-03-27 20:31:29 +08:00
|
|
|
HelperModule.flashAlertMsg(response.data.flash, 'success');
|
2024-03-13 23:23:38 +08:00
|
|
|
}).catch((error) => {
|
|
|
|
HelperModule.flashAlertMsg(error.response.data.error, 'danger');
|
|
|
|
});
|
|
|
|
}
|
2024-05-23 21:10:45 +08:00
|
|
|
} else {
|
|
|
|
this.exportDescription = event.message;
|
|
|
|
this.exportLimitExceded = true;
|
2023-12-01 07:01:08 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
move(event, rows) {
|
|
|
|
this.objectsToMove = rows;
|
2023-12-28 03:09:36 +08:00
|
|
|
}
|
|
|
|
}
|
2023-12-11 16:18:22 +08:00
|
|
|
};
|
2023-11-10 20:34:36 +08:00
|
|
|
|
|
|
|
</script>
|