diff --git a/cypress/e2e/list/list-history.spec.ts b/cypress/e2e/list/list-history.spec.ts deleted file mode 100644 index 69592a84b..000000000 --- a/cypress/e2e/list/list-history.spec.ts +++ /dev/null @@ -1,57 +0,0 @@ -import {createFakeUserAndLogin} from '../../support/authenticateUser' - -import {ListFactory} from '../../factories/list' -import {prepareLists} from './prepareLists' - -describe('List History', () => { - createFakeUserAndLogin() - prepareLists() - - it('should show a list history on the home page', () => { - cy.intercept(Cypress.env('API_URL') + '/namespaces*').as('loadNamespaces') - cy.intercept(Cypress.env('API_URL') + '/lists/*').as('loadList') - - const lists = ListFactory.create(6) - - cy.visit('/') - cy.wait('@loadNamespaces') - cy.get('body') - .should('not.contain', 'Last viewed') - - cy.visit(`/lists/${lists[0].id}`) - cy.wait('@loadNamespaces') - cy.wait('@loadList') - cy.visit(`/lists/${lists[1].id}`) - cy.wait('@loadNamespaces') - cy.wait('@loadList') - cy.visit(`/lists/${lists[2].id}`) - cy.wait('@loadNamespaces') - cy.wait('@loadList') - cy.visit(`/lists/${lists[3].id}`) - cy.wait('@loadNamespaces') - cy.wait('@loadList') - cy.visit(`/lists/${lists[4].id}`) - cy.wait('@loadNamespaces') - cy.wait('@loadList') - cy.visit(`/lists/${lists[5].id}`) - cy.wait('@loadNamespaces') - cy.wait('@loadList') - - // cy.visit('/') - // cy.wait('@loadNamespaces') - // Not using cy.visit here to work around the redirect issue fixed in #1337 - cy.get('nav.menu.top-menu a') - .contains('Overview') - .click() - - cy.get('body') - .should('contain', 'Last viewed') - cy.get('[data-cy="listCardGrid"]') - .should('not.contain', lists[0].title) - .should('contain', lists[1].title) - .should('contain', lists[2].title) - .should('contain', lists[3].title) - .should('contain', lists[4].title) - .should('contain', lists[5].title) - }) -}) \ No newline at end of file diff --git a/cypress/e2e/list/prepareLists.ts b/cypress/e2e/list/prepareLists.ts deleted file mode 100644 index 8fa70e9c7..000000000 --- a/cypress/e2e/list/prepareLists.ts +++ /dev/null @@ -1,19 +0,0 @@ -import {ListFactory} from '../../factories/list' -import {NamespaceFactory} from '../../factories/namespace' -import {TaskFactory} from '../../factories/task' - -export function createLists() { - NamespaceFactory.create(1) - const lists = ListFactory.create(1, { - title: 'First List' - }) - TaskFactory.truncate() - return lists -} - -export function prepareLists(setLists = () => {}) { - beforeEach(() => { - const lists = createLists() - setLists(lists) - }) -} \ No newline at end of file diff --git a/cypress/e2e/misc/editor.spec.ts b/cypress/e2e/misc/editor.spec.ts index c1edb37e3..9ee25a70c 100644 --- a/cypress/e2e/misc/editor.spec.ts +++ b/cypress/e2e/misc/editor.spec.ts @@ -1,18 +1,18 @@ import {createFakeUserAndLogin} from '../../support/authenticateUser' import {TaskFactory} from '../../factories/task' -import {ListFactory} from '../../factories/list' +import {ProjectFactory} from '../../factories/project' import {NamespaceFactory} from '../../factories/namespace' -import {UserListFactory} from '../../factories/users_list' +import {UserProjectFactory} from '../../factories/users_project' describe('Editor', () => { createFakeUserAndLogin() beforeEach(() => { NamespaceFactory.create(1) - ListFactory.create(1) + ProjectFactory.create(1) TaskFactory.truncate() - UserListFactory.truncate() + UserProjectFactory.truncate() }) it('Has a preview with checkable checkboxes', () => { diff --git a/cypress/e2e/list/namespaces.spec.ts b/cypress/e2e/project/namespaces.spec.ts similarity index 94% rename from cypress/e2e/list/namespaces.spec.ts rename to cypress/e2e/project/namespaces.spec.ts index 58d57159b..080cf56e9 100644 --- a/cypress/e2e/list/namespaces.spec.ts +++ b/cypress/e2e/project/namespaces.spec.ts @@ -1,6 +1,6 @@ import {createFakeUserAndLogin} from '../../support/authenticateUser' -import {ListFactory} from '../../factories/list' +import {ProjectFactory} from '../../factories/project' import {NamespaceFactory} from '../../factories/namespace' describe('Namepaces', () => { @@ -10,7 +10,7 @@ describe('Namepaces', () => { beforeEach(() => { namespaces = NamespaceFactory.create(1) - ListFactory.create(1) + ProjectFactory.create(1) }) it('Should be all there', () => { @@ -99,17 +99,17 @@ describe('Namepaces', () => { .should('not.contain', newNamespaces[0].title) }) - it('Should not show archived lists & namespaces if the filter is not checked', () => { + it('Should not show archived projects & namespaces if the filter is not checked', () => { const n = NamespaceFactory.create(1, { id: 2, is_archived: true, }, false) - ListFactory.create(1, { + ProjectFactory.create(1, { id: 2, namespace_id: n[0].id, }, false) - ListFactory.create(1, { + ProjectFactory.create(1, { id: 3, is_archived: true, }, false) diff --git a/cypress/e2e/project/prepareProjects.ts b/cypress/e2e/project/prepareProjects.ts new file mode 100644 index 000000000..19b924175 --- /dev/null +++ b/cypress/e2e/project/prepareProjects.ts @@ -0,0 +1,19 @@ +import {ProjectFactory} from '../../factories/project' +import {NamespaceFactory} from '../../factories/namespace' +import {TaskFactory} from '../../factories/task' + +export function createProjects() { + NamespaceFactory.create(1) + const projects = ProjectFactory.create(1, { + title: 'First Project' + }) + TaskFactory.truncate() + return projects +} + +export function prepareProjects(setProjects = () => {}) { + beforeEach(() => { + const projects = createProjects() + setProjects(projects) + }) +} \ No newline at end of file diff --git a/cypress/e2e/project/project-history.spec.ts b/cypress/e2e/project/project-history.spec.ts new file mode 100644 index 000000000..91ab258c1 --- /dev/null +++ b/cypress/e2e/project/project-history.spec.ts @@ -0,0 +1,57 @@ +import {createFakeUserAndLogin} from '../../support/authenticateUser' + +import {ProjectFactory} from '../../factories/project' +import {prepareProjects} from './prepareProjects' + +describe('Project History', () => { + createFakeUserAndLogin() + prepareProjects() + + it('should show a project history on the home page', () => { + cy.intercept(Cypress.env('API_URL') + '/namespaces*').as('loadNamespaces') + cy.intercept(Cypress.env('API_URL') + '/projects/*').as('loadProject') + + const projects = ProjectFactory.create(6) + + cy.visit('/') + cy.wait('@loadNamespaces') + cy.get('body') + .should('not.contain', 'Last viewed') + + cy.visit(`/projects/${projects[0].id}`) + cy.wait('@loadNamespaces') + cy.wait('@loadProject') + cy.visit(`/projects/${projects[1].id}`) + cy.wait('@loadNamespaces') + cy.wait('@loadProject') + cy.visit(`/projects/${projects[2].id}`) + cy.wait('@loadNamespaces') + cy.wait('@loadProject') + cy.visit(`/projects/${projects[3].id}`) + cy.wait('@loadNamespaces') + cy.wait('@loadProject') + cy.visit(`/projects/${projects[4].id}`) + cy.wait('@loadNamespaces') + cy.wait('@loadProject') + cy.visit(`/projects/${projects[5].id}`) + cy.wait('@loadNamespaces') + cy.wait('@loadProject') + + // cy.visit('/') + // cy.wait('@loadNamespaces') + // Not using cy.visit here to work around the redirect issue fixed in #1337 + cy.get('nav.menu.top-menu a') + .contains('Overview') + .click() + + cy.get('body') + .should('contain', 'Last viewed') + cy.get('[data-cy="projectCardGrid"]') + .should('not.contain', projects[0].title) + .should('contain', projects[1].title) + .should('contain', projects[2].title) + .should('contain', projects[3].title) + .should('contain', projects[4].title) + .should('contain', projects[5].title) + }) +}) \ No newline at end of file diff --git a/cypress/e2e/list/list-view-gantt.spec.ts b/cypress/e2e/project/project-view-gantt.spec.ts similarity index 84% rename from cypress/e2e/list/list-view-gantt.spec.ts rename to cypress/e2e/project/project-view-gantt.spec.ts index 177f791ad..5a67c7081 100644 --- a/cypress/e2e/list/list-view-gantt.spec.ts +++ b/cypress/e2e/project/project-view-gantt.spec.ts @@ -3,15 +3,15 @@ import {formatISO, format} from 'date-fns' import {createFakeUserAndLogin} from '../../support/authenticateUser' import {TaskFactory} from '../../factories/task' -import {prepareLists} from './prepareLists' +import {prepareProjects} from './prepareProjects' -describe('List View Gantt', () => { +describe('Project View Gantt', () => { createFakeUserAndLogin() - prepareLists() + prepareProjects() it('Hides tasks with no dates', () => { const tasks = TaskFactory.create(1) - cy.visit('/lists/1/gantt') + cy.visit('/projects/1/gantt') cy.get('.g-gantt-rows-container') .should('not.contain', tasks[0].title) @@ -25,7 +25,7 @@ describe('List View Gantt', () => { nextMonth.setDate(1) nextMonth.setMonth(9) - cy.visit('/lists/1/gantt') + cy.visit('/projects/1/gantt') cy.get('.g-timeunits-container') .should('contain', format(now, 'MMMM')) @@ -38,7 +38,7 @@ describe('List View Gantt', () => { start_date: now.toISOString(), end_date: new Date(new Date(now).setDate(now.getDate() + 4)).toISOString(), }) - cy.visit('/lists/1/gantt') + cy.visit('/projects/1/gantt') cy.get('.g-gantt-rows-container') .should('not.be.empty') @@ -50,7 +50,7 @@ describe('List View Gantt', () => { start_date: null, end_date: null, }) - cy.visit('/lists/1/gantt') + cy.visit('/projects/1/gantt') cy.get('.gantt-options .fancycheckbox') .contains('Show tasks which don\'t have dates set') @@ -69,7 +69,7 @@ describe('List View Gantt', () => { start_date: now.toISOString(), end_date: new Date(new Date(now).setDate(now.getDate() + 4)).toISOString(), }) - cy.visit('/lists/1/gantt') + cy.visit('/projects/1/gantt') cy.get('.g-gantt-rows-container .g-gantt-row .g-gantt-row-bars-container div .g-gantt-bar') .first() @@ -83,9 +83,9 @@ describe('List View Gantt', () => { const now = Date.UTC(2022, 10, 9) cy.clock(now, ['Date']) - cy.visit('/lists/1/gantt') + cy.visit('/projects/1/gantt') - cy.get('.list-gantt .gantt-options .field .control input.input.form-control') + cy.get('.project-gantt .gantt-options .field .control input.input.form-control') .click() cy.get('.flatpickr-calendar .flatpickr-innerContainer .dayContainer .flatpickr-day') .first() @@ -99,13 +99,13 @@ describe('List View Gantt', () => { }) it('Should change the date range based on date query parameters', () => { - cy.visit('/lists/1/gantt?dateFrom=2022-09-25&dateTo=2022-11-05') + cy.visit('/projects/1/gantt?dateFrom=2022-09-25&dateTo=2022-11-05') cy.get('.g-timeunits-container') .should('contain', 'September 2022') .should('contain', 'October 2022') .should('contain', 'November 2022') - cy.get('.list-gantt .gantt-options .field .control input.input.form-control') + cy.get('.project-gantt .gantt-options .field .control input.input.form-control') .should('have.value', '25 Sep 2022 to 5 Nov 2022') }) @@ -115,7 +115,7 @@ describe('List View Gantt', () => { start_date: formatISO(now), end_date: formatISO(now.setDate(now.getDate() + 4)), }) - cy.visit('/lists/1/gantt') + cy.visit('/projects/1/gantt') cy.get('.gantt-container .g-gantt-chart .g-gantt-row-bars-container .g-gantt-bar') .dblclick() diff --git a/cypress/e2e/list/list-view-kanban.spec.ts b/cypress/e2e/project/project-view-kanban.spec.ts similarity index 85% rename from cypress/e2e/list/list-view-kanban.spec.ts rename to cypress/e2e/project/project-view-kanban.spec.ts index c2677c689..719319373 100644 --- a/cypress/e2e/list/list-view-kanban.spec.ts +++ b/cypress/e2e/project/project-view-kanban.spec.ts @@ -1,13 +1,13 @@ import {createFakeUserAndLogin} from '../../support/authenticateUser' import {BucketFactory} from '../../factories/bucket' -import {ListFactory} from '../../factories/list' +import {ProjectFactory} from '../../factories/project' import {TaskFactory} from '../../factories/task' -import {prepareLists} from './prepareLists' +import {prepareProjects} from './prepareProjects' -describe('List View Kanban', () => { +describe('Project View Kanban', () => { createFakeUserAndLogin() - prepareLists() + prepareProjects() let buckets beforeEach(() => { @@ -16,10 +16,10 @@ describe('List View Kanban', () => { it('Shows all buckets with their tasks', () => { const data = TaskFactory.create(10, { - list_id: 1, + project_id: 1, bucket_id: 1, }) - cy.visit('/lists/1/kanban') + cy.visit('/projects/1/kanban') cy.get('.kanban .bucket .title') .contains(buckets[0].title) @@ -34,10 +34,10 @@ describe('List View Kanban', () => { it('Can add a new task to a bucket', () => { TaskFactory.create(2, { - list_id: 1, + project_id: 1, bucket_id: 1, }) - cy.visit('/lists/1/kanban') + cy.visit('/projects/1/kanban') cy.get('.kanban .bucket') .contains(buckets[0].title) @@ -55,7 +55,7 @@ describe('List View Kanban', () => { }) it('Can create a new bucket', () => { - cy.visit('/lists/1/kanban') + cy.visit('/projects/1/kanban') cy.get('.kanban .bucket.new-bucket .button') .click() @@ -69,7 +69,7 @@ describe('List View Kanban', () => { }) it('Can set a bucket limit', () => { - cy.visit('/lists/1/kanban') + cy.visit('/projects/1/kanban') cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger') .first() @@ -90,7 +90,7 @@ describe('List View Kanban', () => { }) it('Can rename a bucket', () => { - cy.visit('/lists/1/kanban') + cy.visit('/projects/1/kanban') cy.get('.kanban .bucket .bucket-header .title') .first() @@ -101,7 +101,7 @@ describe('List View Kanban', () => { }) it('Can delete a bucket', () => { - cy.visit('/lists/1/kanban') + cy.visit('/projects/1/kanban') cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger') .first() @@ -125,10 +125,10 @@ describe('List View Kanban', () => { it('Can drag tasks around', () => { const tasks = TaskFactory.create(2, { - list_id: 1, + project_id: 1, bucket_id: 1, }) - cy.visit('/lists/1/kanban') + cy.visit('/projects/1/kanban') cy.get('.kanban .bucket .tasks .task') .contains(tasks[0].title) @@ -144,10 +144,10 @@ describe('List View Kanban', () => { it('Should navigate to the task when the task card is clicked', () => { const tasks = TaskFactory.create(5, { id: '{increment}', - list_id: 1, + project_id: 1, bucket_id: 1, }) - cy.visit('/lists/1/kanban') + cy.visit('/projects/1/kanban') cy.get('.kanban .bucket .tasks .task') .contains(tasks[0].title) @@ -158,18 +158,18 @@ describe('List View Kanban', () => { .should('contain', `/tasks/${tasks[0].id}`, { timeout: 1000 }) }) - it('Should remove a task from the kanban board when moving it to another list', () => { - const lists = ListFactory.create(2) + it('Should remove a task from the kanban board when moving it to another project', () => { + const projects = ProjectFactory.create(2) BucketFactory.create(2, { - list_id: '{increment}', + project_id: '{increment}', }) const tasks = TaskFactory.create(5, { id: '{increment}', - list_id: 1, + project_id: 1, bucket_id: 1, }) const task = tasks[0] - cy.visit('/lists/1/kanban') + cy.visit('/projects/1/kanban') cy.get('.kanban .bucket .tasks .task') .contains(task.title) @@ -180,7 +180,7 @@ describe('List View Kanban', () => { .contains('Move') .click() cy.get('.task-view .content.details .field .multiselect.control .input-wrapper input') - .type(`${lists[1].title}{enter}`) + .type(`${projects[1].title}{enter}`) // The requests happen with a 200ms timeout. Because of that, the results are not yet there when cypress // presses enter and we can't simulate pressing on enter to select the item. cy.get('.task-view .content.details .field .multiselect.control .search-results') @@ -197,26 +197,26 @@ describe('List View Kanban', () => { it('Shows a button to filter the kanban board', () => { const data = TaskFactory.create(10, { - list_id: 1, + project_id: 1, bucket_id: 1, }) - cy.visit('/lists/1/kanban') + cy.visit('/projects/1/kanban') - cy.get('.list-kanban .filter-container .base-button') + cy.get('.project-kanban .filter-container .base-button') .should('exist') }) it('Should remove a task from the board when deleting it', () => { - const lists = ListFactory.create(1) + const projects = ProjectFactory.create(1) const buckets = BucketFactory.create(2, { - list_id: lists[0].id, + project_id: projects[0].id, }) const tasks = TaskFactory.create(5, { - list_id: 1, + project_id: 1, bucket_id: buckets[0].id, }) const task = tasks[0] - cy.visit('/lists/1/kanban') + cy.visit('/projects/1/kanban') cy.get('.kanban .bucket .tasks .task') .contains(task.title) diff --git a/cypress/e2e/list/list-view-list.spec.ts b/cypress/e2e/project/project-view-list.spec.ts similarity index 61% rename from cypress/e2e/list/list-view-list.spec.ts rename to cypress/e2e/project/project-view-list.spec.ts index 0601894d4..9c26bd91e 100644 --- a/cypress/e2e/list/list-view-list.spec.ts +++ b/cypress/e2e/project/project-view-list.spec.ts @@ -1,32 +1,32 @@ import {createFakeUserAndLogin} from '../../support/authenticateUser' -import {UserListFactory} from '../../factories/users_list' +import {UserProjectFactory} from '../../factories/users_project' import {TaskFactory} from '../../factories/task' import {UserFactory} from '../../factories/user' -import {ListFactory} from '../../factories/list' -import {prepareLists} from './prepareLists' +import {ProjectFactory} from '../../factories/project' +import {prepareProjects} from './prepareProjects' -describe('List View List', () => { +describe('Project View Project', () => { createFakeUserAndLogin() - prepareLists() + prepareProjects() - it('Should be an empty list', () => { - cy.visit('/lists/1') + it('Should be an empty project', () => { + cy.visit('/projects/1') cy.url() - .should('contain', '/lists/1/list') - cy.get('.list-title h1') - .should('contain', 'First List') - cy.get('.list-title .dropdown') + .should('contain', '/projects/1/list') + cy.get('.project-title h1') + .should('contain', 'First Project') + cy.get('.project-title .dropdown') .should('exist') cy.get('p') - .contains('This list is currently empty.') + .contains('This project is currently empty.') .should('exist') }) it('Should create a new task', () => { const newTaskTitle = 'New task' - cy.visit('/lists/1') + cy.visit('/projects/1') cy.get('.task-add textarea') .type(newTaskTitle+'{enter}') cy.get('.tasks') @@ -36,9 +36,9 @@ describe('List View List', () => { it('Should navigate to the task when the title is clicked', () => { const tasks = TaskFactory.create(5, { id: '{increment}', - list_id: 1, + project_id: 1, }) - cy.visit('/lists/1/list') + cy.visit('/projects/1/list') cy.get('.tasks .task .tasktext') .contains(tasks[0].title) @@ -49,33 +49,33 @@ describe('List View List', () => { .should('contain', `/tasks/${tasks[0].id}`) }) - it('Should not see any elements for a list which is shared read only', () => { + it('Should not see any elements for a project which is shared read only', () => { UserFactory.create(2) - UserListFactory.create(1, { - list_id: 2, + UserProjectFactory.create(1, { + project_id: 2, user_id: 1, right: 0, }) - const lists = ListFactory.create(2, { + const projects = ProjectFactory.create(2, { owner_id: '{increment}', namespace_id: '{increment}', }) - cy.visit(`/lists/${lists[1].id}/`) + cy.visit(`/projects/${projects[1].id}/`) - cy.get('.list-title .icon') + cy.get('.project-title .icon') .should('not.exist') cy.get('input.input[placeholder="Add a new task..."') .should('not.exist') }) - it('Should only show the color of a list in the navigation and not in the list view', () => { - const lists = ListFactory.create(1, { + it('Should only show the color of a project in the navigation and not in the project view', () => { + const projects = ProjectFactory.create(1, { hex_color: '00db60', }) TaskFactory.create(10, { - list_id: lists[0].id, + project_id: projects[0].id, }) - cy.visit(`/lists/${lists[0].id}/`) + cy.visit(`/projects/${projects[0].id}/`) cy.get('.menu-list li .list-menu-link .color-bubble') .should('have.css', 'background-color', 'rgb(0, 219, 96)') @@ -87,9 +87,9 @@ describe('List View List', () => { const tasks = TaskFactory.create(100, { id: '{increment}', title: i => `task${i}`, - list_id: 1, + project_id: 1, }) - cy.visit('/lists/1/list') + cy.visit('/projects/1/list') cy.get('.tasks') .should('contain', tasks[1].title) diff --git a/cypress/e2e/list/list-view-table.spec.ts b/cypress/e2e/project/project-view-table.spec.ts similarity index 56% rename from cypress/e2e/list/list-view-table.spec.ts rename to cypress/e2e/project/project-view-table.spec.ts index dac79224d..ce52fb9bf 100644 --- a/cypress/e2e/list/list-view-table.spec.ts +++ b/cypress/e2e/project/project-view-table.spec.ts @@ -2,37 +2,37 @@ import {createFakeUserAndLogin} from '../../support/authenticateUser' import {TaskFactory} from '../../factories/task' -describe('List View Table', () => { +describe('Project View Table', () => { createFakeUserAndLogin() it('Should show a table with tasks', () => { const tasks = TaskFactory.create(1) - cy.visit('/lists/1/table') + cy.visit('/projects/1/table') - cy.get('.list-table table.table') + cy.get('.project-table table.table') .should('exist') - cy.get('.list-table table.table') + cy.get('.project-table table.table') .should('contain', tasks[0].title) }) it('Should have working column switches', () => { TaskFactory.create(1) - cy.visit('/lists/1/table') + cy.visit('/projects/1/table') - cy.get('.list-table .filter-container .items .button') + cy.get('.project-table .filter-container .items .button') .contains('Columns') .click() - cy.get('.list-table .filter-container .card.columns-filter .card-content .fancycheckbox .check') + cy.get('.project-table .filter-container .card.columns-filter .card-content .fancycheckbox .check') .contains('Priority') .click() - cy.get('.list-table .filter-container .card.columns-filter .card-content .fancycheckbox .check') + cy.get('.project-table .filter-container .card.columns-filter .card-content .fancycheckbox .check') .contains('Done') .click() - cy.get('.list-table table.table th') + cy.get('.project-table table.table th') .contains('Priority') .should('exist') - cy.get('.list-table table.table th') + cy.get('.project-table table.table th') .contains('Done') .should('not.exist') }) @@ -40,11 +40,11 @@ describe('List View Table', () => { it('Should navigate to the task when the title is clicked', () => { const tasks = TaskFactory.create(5, { id: '{increment}', - list_id: 1, + project_id: 1, }) - cy.visit('/lists/1/table') + cy.visit('/projects/1/table') - cy.get('.list-table table.table') + cy.get('.project-table table.table') .contains(tasks[0].title) .click() diff --git a/cypress/e2e/list/list.spec.ts b/cypress/e2e/project/project.spec.ts similarity index 53% rename from cypress/e2e/list/list.spec.ts rename to cypress/e2e/project/project.spec.ts index 6f7c0b3a4..f5e2a792b 100644 --- a/cypress/e2e/list/list.spec.ts +++ b/cypress/e2e/project/project.spec.ts @@ -1,58 +1,58 @@ import {createFakeUserAndLogin} from '../../support/authenticateUser' import {TaskFactory} from '../../factories/task' -import {prepareLists} from './prepareLists' +import {prepareProjects} from './prepareProjects' -describe('Lists', () => { +describe('Projects', () => { createFakeUserAndLogin() - let lists - prepareLists((newLists) => (lists = newLists)) + let projects + prepareProjects((newProjects) => (projects = newProjects)) - it('Should create a new list', () => { + it('Should create a new project', () => { cy.visit('/') cy.get('.namespace-title .dropdown-trigger') .click() cy.get('.namespace-title .dropdown .dropdown-item') - .contains('New list') + .contains('New project') .click() cy.url() - .should('contain', '/lists/new/1') + .should('contain', '/projects/new/1') cy.get('.card-header-title') - .contains('New list') + .contains('New project') cy.get('input.input') - .type('New List') + .type('New Project') cy.get('.button') .contains('Create') .click() - cy.get('.global-notification', { timeout: 1000 }) // Waiting until the request to create the new list is done + cy.get('.global-notification', { timeout: 1000 }) // Waiting until the request to create the new project is done .should('contain', 'Success') cy.url() - .should('contain', '/lists/') - cy.get('.list-title h1') - .should('contain', 'New List') + .should('contain', '/projects/') + cy.get('.project-title h1') + .should('contain', 'New Project') }) - it('Should redirect to a specific list view after visited', () => { - cy.visit('/lists/1/kanban') + it('Should redirect to a specific project view after visited', () => { + cy.visit('/projects/1/kanban') cy.url() - .should('contain', '/lists/1/kanban') - cy.visit('/lists/1') + .should('contain', '/projects/1/kanban') + cy.visit('/projects/1') cy.url() - .should('contain', '/lists/1/kanban') + .should('contain', '/projects/1/kanban') }) - it('Should rename the list in all places', () => { + it('Should rename the project in all places', () => { TaskFactory.create(5, { id: '{increment}', - list_id: 1, + project_id: 1, }) - const newListName = 'New list name' + const newProjectName = 'New project name' - cy.visit('/lists/1') - cy.get('.list-title h1') - .should('contain', 'First List') + cy.visit('/projects/1') + cy.get('.project-title h1') + .should('contain', 'First Project') cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .menu-list-dropdown-trigger') .click() @@ -60,27 +60,27 @@ describe('Lists', () => { .contains('Edit') .click() cy.get('#title') - .type(`{selectall}${newListName}`) + .type(`{selectall}${newProjectName}`) cy.get('footer.card-footer .button') .contains('Save') .click() cy.get('.global-notification') .should('contain', 'Success') - cy.get('.list-title h1') - .should('contain', newListName) - .should('not.contain', lists[0].title) + cy.get('.project-title h1') + .should('contain', newProjectName) + .should('not.contain', projects[0].title) cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child') - .should('contain', newListName) - .should('not.contain', lists[0].title) + .should('contain', newProjectName) + .should('not.contain', projects[0].title) cy.visit('/') cy.get('.card-content') - .should('contain', newListName) - .should('not.contain', lists[0].title) + .should('contain', newProjectName) + .should('not.contain', projects[0].title) }) - it('Should remove a list', () => { - cy.visit(`/lists/${lists[0].id}`) + it('Should remove a project', () => { + cy.visit(`/projects/${projects[0].id}`) cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .menu-list-dropdown-trigger') .click() @@ -96,27 +96,27 @@ describe('Lists', () => { cy.get('.global-notification') .should('contain', 'Success') cy.get('.namespace-container .menu.namespaces-lists .menu-list') - .should('not.contain', lists[0].title) + .should('not.contain', projects[0].title) cy.location('pathname') .should('equal', '/') }) - it('Should archive a list', () => { - cy.visit(`/lists/${lists[0].id}`) + it('Should archive a project', () => { + cy.visit(`/projects/${projects[0].id}`) - cy.get('.list-title .dropdown') + cy.get('.project-title .dropdown') .click() - cy.get('.list-title .dropdown .dropdown-menu .dropdown-item') + cy.get('.project-title .dropdown .dropdown-menu .dropdown-item') .contains('Archive') .click() cy.get('.modal-content') - .should('contain.text', 'Archive this list') + .should('contain.text', 'Archive this project') cy.get('.modal-content [data-cy=modalPrimary]') .click() cy.get('.namespace-container .menu.namespaces-lists .menu-list') - .should('not.contain', lists[0].title) + .should('not.contain', projects[0].title) cy.get('main.app-content') - .should('contain.text', 'This list is archived. It is not possible to create new or edit tasks for it.') + .should('contain.text', 'This project is archived. It is not possible to create new or edit tasks for it.') }) }) diff --git a/cypress/e2e/sharing/linkShare.spec.ts b/cypress/e2e/sharing/linkShare.spec.ts index bc616cc6f..de825f183 100644 --- a/cypress/e2e/sharing/linkShare.spec.ts +++ b/cypress/e2e/sharing/linkShare.spec.ts @@ -1,22 +1,22 @@ import {LinkShareFactory} from '../../factories/link_sharing' -import {ListFactory} from '../../factories/list' +import {ProjectFactory} from '../../factories/project' import {TaskFactory} from '../../factories/task' describe('Link shares', () => { it('Can view a link share', () => { - const lists = ListFactory.create(1) + const projects = ProjectFactory.create(1) const tasks = TaskFactory.create(10, { - list_id: lists[0].id + project_id: projects[0].id }) const linkShares = LinkShareFactory.create(1, { - list_id: lists[0].id, + project_id: projects[0].id, right: 0, }) cy.visit(`/share/${linkShares[0].hash}/auth`) cy.get('h1.title') - .should('contain', lists[0].title) + .should('contain', projects[0].title) cy.get('input.input[placeholder="Add a new task..."') .should('not.exist') cy.get('.tasks') diff --git a/cypress/e2e/task/overview.spec.ts b/cypress/e2e/task/overview.spec.ts index 39153c191..6103f7a31 100644 --- a/cypress/e2e/task/overview.spec.ts +++ b/cypress/e2e/task/overview.spec.ts @@ -1,6 +1,6 @@ import {createFakeUserAndLogin} from '../../support/authenticateUser' -import {ListFactory} from '../../factories/list' +import {ProjectFactory} from '../../factories/project' import {seed} from '../../support/seed' import {TaskFactory} from '../../factories/task' import {NamespaceFactory} from '../../factories/namespace' @@ -9,9 +9,9 @@ import {updateUserSettings} from '../../support/updateUserSettings' function seedTasks(numberOfTasks = 50, startDueDate = new Date()) { NamespaceFactory.create(1) - const list = ListFactory.create()[0] + const project = ProjectFactory.create()[0] BucketFactory.create(1, { - list_id: list.id, + project_id: project.id, }) const tasks = [] let dueDate = startDueDate @@ -20,7 +20,7 @@ function seedTasks(numberOfTasks = 50, startDueDate = new Date()) { dueDate = new Date(new Date(dueDate).setDate(dueDate.getDate() + 2)) tasks.push({ id: i + 1, - list_id: list.id, + project_id: project.id, done: false, created_by_id: 1, title: 'Test Task ' + i, @@ -31,7 +31,7 @@ function seedTasks(numberOfTasks = 50, startDueDate = new Date()) { }) } seed(TaskFactory.table, tasks) - return {tasks, list} + return {tasks, project} } describe('Home Page Task Overview', () => { @@ -73,7 +73,7 @@ describe('Home Page Task Overview', () => { due_date: new Date().toISOString(), }, false) - cy.visit(`/lists/${tasks[0].list_id}/list`) + cy.visit(`/projects/${tasks[0].project_id}/list`) cy.get('.tasks .task') .first() .should('contain.text', newTaskTitle) @@ -90,7 +90,7 @@ describe('Home Page Task Overview', () => { cy.visit('/') - cy.visit(`/lists/${tasks[0].list_id}/list`) + cy.visit(`/projects/${tasks[0].project_id}/list`) cy.get('.task-add textarea') .type(newTaskTitle+'{enter}') cy.visit('/') @@ -113,10 +113,10 @@ describe('Home Page Task Overview', () => { .should('contain.text', newTaskTitle) }) - it('Should show a task without a due date added via default list at the bottom', () => { - const {list} = seedTasks(40) + it('Should show a task without a due date added via default project at the bottom', () => { + const {project} = seedTasks(40) updateUserSettings({ - default_list_id: list.id, + default_project_id: project.id, overdue_tasks_reminders_time: '9:00', }) @@ -131,23 +131,23 @@ describe('Home Page Task Overview', () => { .should('contain.text', newTaskTitle) }) - it('Should show the cta buttons for new list when there are no tasks', () => { + it('Should show the cta buttons for new project when there are no tasks', () => { TaskFactory.truncate() cy.visit('/') cy.get('.home.app-content .content') - .should('contain.text', 'You can create a new list for your new tasks:') - .should('contain.text', 'Or import your lists and tasks from other services into Vikunja:') + .should('contain.text', 'You can create a new project for your new tasks:') + .should('contain.text', 'Or import your projects and tasks from other services into Vikunja:') }) - it('Should not show the cta buttons for new list when there are tasks', () => { + it('Should not show the cta buttons for new project when there are tasks', () => { seedTasks() cy.visit('/') cy.get('.home.app-content .content') - .should('not.contain.text', 'You can create a new list for your new tasks:') - .should('not.contain.text', 'Or import your lists and tasks from other services into Vikunja:') + .should('not.contain.text', 'You can create a new project for your new tasks:') + .should('not.contain.text', 'Or import your projects and tasks from other services into Vikunja:') }) }) diff --git a/cypress/e2e/task/task.spec.ts b/cypress/e2e/task/task.spec.ts index f441dc742..ce2ae88bc 100644 --- a/cypress/e2e/task/task.spec.ts +++ b/cypress/e2e/task/task.spec.ts @@ -1,11 +1,11 @@ import {createFakeUserAndLogin} from '../../support/authenticateUser' import {TaskFactory} from '../../factories/task' -import {ListFactory} from '../../factories/list' +import {ProjectFactory} from '../../factories/project' import {TaskCommentFactory} from '../../factories/task_comment' import {UserFactory} from '../../factories/user' import {NamespaceFactory} from '../../factories/namespace' -import {UserListFactory} from '../../factories/users_list' +import {UserProjectFactory} from '../../factories/users_project' import {TaskAssigneeFactory} from '../../factories/task_assignee' import {LabelFactory} from '../../factories/labels' import {LabelTaskFactory} from '../../factories/label_task' @@ -48,22 +48,22 @@ describe('Task', () => { createFakeUserAndLogin() let namespaces - let lists + let projects let buckets beforeEach(() => { // UserFactory.create(1) namespaces = NamespaceFactory.create(1) - lists = ListFactory.create(1) + projects = ProjectFactory.create(1) buckets = BucketFactory.create(1, { - list_id: lists[0].id, + project_id: projects[0].id, }) TaskFactory.truncate() - UserListFactory.truncate() + UserProjectFactory.truncate() }) it('Should be created new', () => { - cy.visit('/lists/1/list') + cy.visit('/projects/1/list') cy.get('.input[placeholder="Add a new task…"') .type('New Task') cy.get('.button') @@ -74,11 +74,11 @@ describe('Task', () => { .should('contain', 'New Task') }) - it('Inserts new tasks at the top of the list', () => { + it('Inserts new tasks at the top of the project', () => { TaskFactory.create(1) - cy.visit('/lists/1/list') - cy.get('.list-is-empty-notice') + cy.visit('/projects/1/list') + cy.get('.project-is-empty-notice') .should('not.exist') cy.get('.input[placeholder="Add a new task…"') .type('New Task') @@ -95,7 +95,7 @@ describe('Task', () => { it('Marks a task as done', () => { TaskFactory.create(1) - cy.visit('/lists/1/list') + cy.visit('/projects/1/list') cy.get('.tasks .task .fancycheckbox label.check') .first() .click() @@ -106,7 +106,7 @@ describe('Task', () => { it('Can add a task to favorites', () => { TaskFactory.create(1) - cy.visit('/lists/1/list') + cy.visit('/projects/1/list') cy.get('.tasks .task .favorite') .first() .click() @@ -134,7 +134,7 @@ describe('Task', () => { .should('contain', '#1') cy.get('.task-view h6.subtitle') .should('contain', namespaces[0].title) - .should('contain', lists[0].title) + .should('contain', projects[0].title) cy.get('.task-view .details.content.description') .should('contain', tasks[0].description) cy.get('.task-view .action-buttons p.created') @@ -179,21 +179,21 @@ describe('Task', () => { .should('contain', 'Mark as undone') }) - it('Shows a task identifier since the list has one', () => { - const lists = ListFactory.create(1, { + it('Shows a task identifier since the project has one', () => { + const projects = ProjectFactory.create(1, { id: 1, identifier: 'TEST', }) const tasks = TaskFactory.create(1, { id: 1, - list_id: lists[0].id, + project_id: projects[0].id, index: 1, }) cy.visit(`/tasks/${tasks[0].id}`) cy.get('.task-view h1.title.task-id') - .should('contain', `${lists[0].identifier}-${tasks[0].index}`) + .should('contain', `${projects[0].identifier}-${tasks[0].index}`) }) it('Can edit the description', () => { @@ -236,14 +236,14 @@ describe('Task', () => { .should('contain', 'Success') }) - it('Can move a task to another list', () => { - const lists = ListFactory.create(2) + it('Can move a task to another project', () => { + const projects = ProjectFactory.create(2) BucketFactory.create(2, { - list_id: '{increment}' + project_id: '{increment}' }) const tasks = TaskFactory.create(1, { id: 1, - list_id: lists[0].id, + project_id: projects[0].id, }) cy.visit(`/tasks/${tasks[0].id}`) @@ -251,7 +251,7 @@ describe('Task', () => { .contains('Move') .click() cy.get('.task-view .content.details .field .multiselect.control .input-wrapper input') - .type(`${lists[1].title}{enter}`) + .type(`${projects[1].title}{enter}`) // The requests happen with a 200ms timeout. Because of that, the results are not yet there when cypress // presses enter and we can't simulate pressing on enter to select the item. cy.get('.task-view .content.details .field .multiselect.control .search-results') @@ -261,7 +261,7 @@ describe('Task', () => { cy.get('.task-view h6.subtitle') .should('contain', namespaces[0].title) - .should('contain', lists[1].title) + .should('contain', projects[1].title) cy.get('.global-notification') .should('contain', 'Success') }) @@ -269,7 +269,7 @@ describe('Task', () => { it('Can delete a task', () => { const tasks = TaskFactory.create(1, { id: 1, - list_id: 1, + project_id: 1, }) cy.visit(`/tasks/${tasks[0].id}`) @@ -286,17 +286,17 @@ describe('Task', () => { cy.get('.global-notification') .should('contain', 'Success') cy.url() - .should('contain', `/lists/${tasks[0].list_id}/`) + .should('contain', `/projects/${tasks[0].project_id}/`) }) it('Can add an assignee to a task', () => { const users = UserFactory.create(5) const tasks = TaskFactory.create(1, { id: 1, - list_id: 1, + project_id: 1, }) - UserListFactory.create(5, { - list_id: 1, + UserProjectFactory.create(5, { + project_id: 1, user_id: '{increment}', }) @@ -321,10 +321,10 @@ describe('Task', () => { const users = UserFactory.create(2) const tasks = TaskFactory.create(1, { id: 1, - list_id: 1, + project_id: 1, }) - UserListFactory.create(5, { - list_id: 1, + UserProjectFactory.create(5, { + project_id: 1, user_id: '{increment}', }) TaskAssigneeFactory.create(1, { @@ -347,7 +347,7 @@ describe('Task', () => { it('Can add a new label to a task', () => { const tasks = TaskFactory.create(1, { id: 1, - list_id: 1, + project_id: 1, }) LabelFactory.truncate() const newLabelText = 'some new label' @@ -375,7 +375,7 @@ describe('Task', () => { it('Can add an existing label to a task', () => { const tasks = TaskFactory.create(1, { id: 1, - list_id: 1, + project_id: 1, }) const labels = LabelFactory.create(1) LabelTaskFactory.truncate() @@ -388,13 +388,13 @@ describe('Task', () => { it('Can add a label to a task and it shows up on the kanban board afterwards', () => { const tasks = TaskFactory.create(1, { id: 1, - list_id: lists[0].id, + project_id: projects[0].id, bucket_id: buckets[0].id, }) const labels = LabelFactory.create(1) LabelTaskFactory.truncate() - cy.visit(`/lists/${lists[0].id}/kanban`) + cy.visit(`/projects/${projects[0].id}/kanban`) cy.get('.bucket .task') .contains(tasks[0].title) @@ -412,7 +412,7 @@ describe('Task', () => { it('Can remove a label from a task', () => { const tasks = TaskFactory.create(1, { id: 1, - list_id: 1, + project_id: 1, }) const labels = LabelFactory.create(1) LabelTaskFactory.create(1, { @@ -527,13 +527,13 @@ describe('Task', () => { TaskAttachmentFactory.truncate() const tasks = TaskFactory.create(1, { id: 1, - list_id: lists[0].id, + project_id: projects[0].id, bucket_id: buckets[0].id, }) const labels = LabelFactory.create(1) LabelTaskFactory.truncate() - cy.visit(`/lists/${lists[0].id}/kanban`) + cy.visit(`/projects/${projects[0].id}/kanban`) cy.get('.bucket .task') .contains(tasks[0].title) diff --git a/cypress/e2e/user/logout.spec.ts b/cypress/e2e/user/logout.spec.ts index aeb07e587..0dc69798e 100644 --- a/cypress/e2e/user/logout.spec.ts +++ b/cypress/e2e/user/logout.spec.ts @@ -1,5 +1,5 @@ import {createFakeUserAndLogin} from '../../support/authenticateUser' -import {createLists} from '../list/prepareLists' +import {createProjects} from '../project/prepareProjects' function logout() { cy.get('.navbar .user .username') @@ -26,21 +26,21 @@ describe('Log out', () => { }) }) - it.skip('Should clear the list history after logging the user out', () => { - const lists = createLists() - cy.visit(`/lists/${lists[0].id}`) + it.skip('Should clear the project history after logging the user out', () => { + const projects = createProjects() + cy.visit(`/projects/${projects[0].id}`) .then(() => { - expect(localStorage.getItem('listHistory')).to.not.eq(null) + expect(localStorage.getItem('projectHistory')).to.not.eq(null) }) logout() - cy.wait(1000) // This makes re-loading of the list and associated entities (and the resulting error) visible + cy.wait(1000) // This makes re-loading of the project and associated entities (and the resulting error) visible cy.url() .should('contain', '/login') .then(() => { - expect(localStorage.getItem('listHistory')).to.eq(null) + expect(localStorage.getItem('projectHistory')).to.eq(null) }) }) }) diff --git a/cypress/factories/bucket.ts b/cypress/factories/bucket.ts index d333531bf..2e0e91077 100644 --- a/cypress/factories/bucket.ts +++ b/cypress/factories/bucket.ts @@ -10,7 +10,7 @@ export class BucketFactory extends Factory { return { id: '{increment}', title: faker.lorem.words(3), - list_id: 1, + project_id: 1, created_by_id: 1, created: now.toISOString(), updated: now.toISOString(), diff --git a/cypress/factories/link_sharing.ts b/cypress/factories/link_sharing.ts index 672d2fc14..465dcd240 100644 --- a/cypress/factories/link_sharing.ts +++ b/cypress/factories/link_sharing.ts @@ -10,7 +10,7 @@ export class LinkShareFactory extends Factory { return { id: '{increment}', hash: faker.random.word(32), - list_id: 1, + project_id: 1, right: 0, sharing_type: 0, shared_by_id: 1, diff --git a/cypress/factories/list.ts b/cypress/factories/project.ts similarity index 80% rename from cypress/factories/list.ts rename to cypress/factories/project.ts index aff7167c5..6de5d48fc 100644 --- a/cypress/factories/list.ts +++ b/cypress/factories/project.ts @@ -1,8 +1,8 @@ import {Factory} from '../support/factory' import {faker} from '@faker-js/faker' -export class ListFactory extends Factory { - static table = 'lists' +export class ProjectFactory extends Factory { + static table = 'projects' static factory() { const now = new Date() diff --git a/cypress/factories/task.ts b/cypress/factories/task.ts index e7c5769eb..bc97446a8 100644 --- a/cypress/factories/task.ts +++ b/cypress/factories/task.ts @@ -11,7 +11,7 @@ export class TaskFactory extends Factory { id: '{increment}', title: faker.lorem.words(3), done: false, - list_id: 1, + project_id: 1, created_by_id: 1, index: '{increment}', position: '{increment}', diff --git a/cypress/factories/users_list.ts b/cypress/factories/users_project.ts similarity index 68% rename from cypress/factories/users_list.ts rename to cypress/factories/users_project.ts index 60b08be50..53eb0180e 100644 --- a/cypress/factories/users_list.ts +++ b/cypress/factories/users_project.ts @@ -1,14 +1,14 @@ import {Factory} from '../support/factory' -export class UserListFactory extends Factory { - static table = 'users_lists' +export class UserProjectFactory extends Factory { + static table = 'users_projects' static factory() { const now = new Date() return { id: '{increment}', - list_id: 1, + project_id: 1, user_id: 1, right: 0, created: now.toISOString(), diff --git a/docs/models-services.md b/docs/models-services.md index e69af85cb..6b74866f9 100644 --- a/docs/models-services.md +++ b/docs/models-services.md @@ -30,21 +30,21 @@ A basic service can look like this: ```javascript import AbstractService from './abstractService' -import ListModel from '../models/list' +import ProjectModel from '../models/project' -export default class ListService extends AbstractService { +export default class ProjectService extends AbstractService { constructor() { super({ - getAll: '/lists', - get: '/lists/{id}', - create: '/namespaces/{namespaceID}/lists', - update: '/lists/{id}', - delete: '/lists/{id}', + getAll: '/projects', + get: '/projects/{id}', + create: '/namespaces/{namespaceID}/projects', + update: '/projects/{id}', + delete: '/projects/{id}', }) } modelFactory(data) { - return new ListModel(data) + return new ProjectModel(data) } } ``` @@ -132,7 +132,7 @@ import AbstractModel from './abstractModel' import TaskModel from './task' import UserModel from './user' -export default class ListModel extends AbstractModel { +export default class ProjectModel extends AbstractModel { constructor(data) { // The constructor of AbstractModel handles all the default parsing. diff --git a/src/components/home/TheNavigation.vue b/src/components/home/TheNavigation.vue index 77d0b6e0e..de7784526 100644 --- a/src/components/home/TheNavigation.vue +++ b/src/components/home/TheNavigation.vue @@ -8,19 +8,19 @@ -
- + + + + \ No newline at end of file diff --git a/src/components/list/partials/ListCard.vue b/src/components/project/partials/ProjectCard.vue similarity index 61% rename from src/components/list/partials/ListCard.vue rename to src/components/project/partials/ProjectCard.vue index ca7484b3d..7da3b1fba 100644 --- a/src/components/list/partials/ListCard.vue +++ b/src/components/project/partials/ProjectCard.vue @@ -1,39 +1,39 @@ @@ -41,30 +41,30 @@ \ No newline at end of file diff --git a/src/components/list/partials/filter-popup.vue b/src/components/project/partials/filter-popup.vue similarity index 96% rename from src/components/list/partials/filter-popup.vue rename to src/components/project/partials/filter-popup.vue index 66e130149..acc543c7b 100644 --- a/src/components/list/partials/filter-popup.vue +++ b/src/components/project/partials/filter-popup.vue @@ -32,7 +32,7 @@ \ No newline at end of file diff --git a/src/components/quick-actions/quick-actions.vue b/src/components/quick-actions/quick-actions.vue index 61bcc1cce..730c3e1fc 100644 --- a/src/components/quick-actions/quick-actions.vue +++ b/src/components/quick-actions/quick-actions.vue @@ -63,18 +63,18 @@ import TeamService from '@/services/team' import NamespaceModel from '@/models/namespace' import TeamModel from '@/models/team' -import ListModel from '@/models/list' +import ProjectModel from '@/models/project' import BaseButton from '@/components/base/BaseButton.vue' import QuickAddMagic from '@/components/tasks/partials/quick-add-magic.vue' import {useBaseStore} from '@/stores/base' -import {useListStore} from '@/stores/lists' +import {useProjectStore} from '@/stores/projects' import {useNamespaceStore} from '@/stores/namespaces' import {useLabelStore} from '@/stores/labels' import {useTaskStore} from '@/stores/tasks' -import {getHistory} from '@/modules/listHistory' +import {getHistory} from '@/modules/projectHistory' import {parseTaskText, PrefixMode, PREFIXES} from '@/modules/parseTaskText' import {getQuickAddMagicMode} from '@/helpers/quickAddMagicMode' import {success} from '@/message' @@ -82,13 +82,13 @@ import {success} from '@/message' import type {ITeam} from '@/modelTypes/ITeam' import type {ITask} from '@/modelTypes/ITask' import type {INamespace} from '@/modelTypes/INamespace' -import type {IList} from '@/modelTypes/IList' +import type {IProject} from '@/modelTypes/IProject' const {t} = useI18n({useScope: 'global'}) const router = useRouter() const baseStore = useBaseStore() -const listStore = useListStore() +const projectStore = useProjectStore() const namespaceStore = useNamespaceStore() const labelStore = useLabelStore() const taskStore = useTaskStore() @@ -98,13 +98,13 @@ type DoAction = { type: ACTION_TYPE } & Type enum ACTION_TYPE { CMD = 'cmd', TASK = 'task', - LIST = 'list', + PROJECT = 'project', TEAM = 'team', } enum COMMAND_TYPE { NEW_TASK = 'newTask', - NEW_LIST = 'newList', + NEW_PROJECT = 'newProject', NEW_NAMESPACE = 'newNamespace', NEW_TEAM = 'newTeam', } @@ -112,7 +112,7 @@ enum COMMAND_TYPE { enum SEARCH_MODE { ALL = 'all', TASKS = 'tasks', - LISTS = 'lists', + PROJECTS = 'projects', TEAMS = 'teams', } @@ -137,26 +137,26 @@ function closeQuickActions() { baseStore.setQuickActionsActive(false) } -const foundLists = computed(() => { - const { list } = parsedQuery.value +const foundProjects = computed(() => { + const { project } = parsedQuery.value if ( searchMode.value === SEARCH_MODE.ALL || - searchMode.value === SEARCH_MODE.LISTS || - list === null + searchMode.value === SEARCH_MODE.PROJECTS || + project === null ) { return [] } - const ncache: { [id: ListModel['id']]: INamespace } = {} + const ncache: { [id: ProjectModel['id']]: INamespace } = {} const history = getHistory() - const allLists = [ + const allProjects = [ ...new Set([ - ...history.map((l) => listStore.getListById(l.id)), - ...listStore.searchList(list), + ...history.map((l) => projectStore.getProjectById(l.id)), + ...projectStore.searchProject(project), ]), ] - return allLists.filter((l) => { + return allProjects.filter((l) => { if (typeof l === 'undefined' || l === null) { return false } @@ -191,9 +191,9 @@ const results = computed(() => { items: foundTasks.value, }, { - type: ACTION_TYPE.LIST, - title: t('quickActions.lists'), - items: foundLists.value, + type: ACTION_TYPE.PROJECT, + title: t('quickActions.projects'), + items: foundProjects.value, }, { type: ACTION_TYPE.TEAM, @@ -206,7 +206,7 @@ const results = computed(() => { const loading = computed(() => taskService.loading || namespaceStore.isLoading || - listStore.isLoading || + projectStore.isLoading || teamService.loading, ) @@ -224,11 +224,11 @@ const commands = computed<{ [key in COMMAND_TYPE]: Command }>(() => ({ placeholder: t('quickActions.newTask'), action: newTask, }, - newList: { - type: COMMAND_TYPE.NEW_LIST, - title: t('quickActions.cmds.newList'), - placeholder: t('quickActions.newList'), - action: newList, + newProject: { + type: COMMAND_TYPE.NEW_PROJECT, + title: t('quickActions.cmds.newProject'), + placeholder: t('quickActions.newProject'), + action: newProject, }, newNamespace: { type: COMMAND_TYPE.NEW_NAMESPACE, @@ -246,24 +246,24 @@ const commands = computed<{ [key in COMMAND_TYPE]: Command }>(() => ({ const placeholder = computed(() => selectedCmd.value?.placeholder || t('quickActions.placeholder')) -const currentList = computed(() => Object.keys(baseStore.currentList).length === 0 +const currentProject = computed(() => Object.keys(baseStore.currentProject).length === 0 ? null - : baseStore.currentList, + : baseStore.currentProject, ) const hintText = computed(() => { let namespace - if (selectedCmd.value !== null && currentList.value !== null) { + if (selectedCmd.value !== null && currentProject.value !== null) { switch (selectedCmd.value.type) { case COMMAND_TYPE.NEW_TASK: return t('quickActions.createTask', { - title: currentList.value.title, + title: currentProject.value.title, }) - case COMMAND_TYPE.NEW_LIST: + case COMMAND_TYPE.NEW_PROJECT: namespace = namespaceStore.getNamespaceById( - currentList.value.namespaceId, + currentProject.value.namespaceId, ) - return t('quickActions.createList', { + return t('quickActions.createProject', { title: namespace?.title, }) } @@ -275,8 +275,8 @@ const hintText = computed(() => { const availableCmds = computed(() => { const cmds = [] - if (currentList.value !== null) { - cmds.push(commands.value.newTask, commands.value.newList) + if (currentProject.value !== null) { + cmds.push(commands.value.newTask, commands.value.newProject) } cmds.push(commands.value.newNamespace, commands.value.newTeam) return cmds @@ -288,21 +288,21 @@ const searchMode = computed(() => { if (query.value === '') { return SEARCH_MODE.ALL } - const { text, list, labels, assignees } = parsedQuery.value + const { text, project, labels, assignees } = parsedQuery.value if (assignees.length === 0 && text !== '') { return SEARCH_MODE.TASKS } if ( assignees.length === 0 && - list !== null && + project !== null && text === '' && labels.length === 0 ) { - return SEARCH_MODE.LISTS + return SEARCH_MODE.PROJECTS } if ( assignees.length > 0 && - list === null && + project === null && text === '' && labels.length === 0 ) { @@ -356,7 +356,7 @@ function searchTasks() { taskSearchTimeout.value = null } - const { text, list: listName, labels } = parsedQuery.value + const { text, project: projectName, labels } = parsedQuery.value const filters: Filter[] = [] @@ -373,10 +373,10 @@ function searchTasks() { }) } - if (listName !== null) { - const list = listStore.findListByExactname(listName) - if (list !== null) { - addFilter('listId', list.id, 'equals') + if (projectName !== null) { + const project = projectStore.findProjectByExactname(projectName) + if (project !== null) { + addFilter('projectId', project.id, 'equals') } } @@ -396,9 +396,9 @@ function searchTasks() { const r = await taskService.getAll({}, params) as DoAction[] foundTasks.value = r.map((t) => { t.type = ACTION_TYPE.TASK - const list = listStore.getListById(t.listId) - if (list !== null) { - t.title = `${t.title} (${list.title})` + const project = projectStore.getProjectById(t.projectId) + if (project !== null) { + t.title = `${t.title} (${project.title})` } return t }) @@ -444,11 +444,11 @@ const searchInput = ref(null) async function doAction(type: ACTION_TYPE, item: DoAction) { switch (type) { - case ACTION_TYPE.LIST: + case ACTION_TYPE.PROJECT: closeQuickActions() await router.push({ - name: 'list.index', - params: { listId: (item as DoAction).id }, + name: 'project.index', + params: { projectId: (item as DoAction).id }, }) break case ACTION_TYPE.TASK: @@ -482,29 +482,29 @@ async function doCmd() { } async function newTask() { - if (currentList.value === null) { + if (currentProject.value === null) { return } const task = await taskStore.createNewTask({ title: query.value, - listId: currentList.value.id, + projectId: currentProject.value.id, }) success({ message: t('task.createSuccess') }) await router.push({ name: 'task.detail', params: { id: task.id } }) } -async function newList() { - if (currentList.value === null) { +async function newProject() { + if (currentProject.value === null) { return } - const newList = await listStore.createList(new ListModel({ + const newProject = await projectStore.createProject(new ProjectModel({ title: query.value, - namespaceId: currentList.value.namespaceId, + namespaceId: currentProject.value.namespaceId, })) - success({ message: t('list.create.createdSuccess')}) + success({ message: t('project.create.createdSuccess')}) await router.push({ - name: 'list.index', - params: { listId: newList.id }, + name: 'project.index', + params: { projectId: newProject.id }, }) } diff --git a/src/components/sharing/linkSharing.vue b/src/components/sharing/linkSharing.vue index f6c3c7219..5f763aa1a 100644 --- a/src/components/sharing/linkSharing.vue +++ b/src/components/sharing/linkSharing.vue @@ -1,39 +1,39 @@

@@ -172,14 +172,14 @@
@@ -193,19 +193,19 @@ import {RIGHTS} from '@/constants/rights' import LinkShareModel from '@/models/linkShare' import type {ILinkShare} from '@/modelTypes/ILinkShare' -import type {IList} from '@/modelTypes/IList' +import type {IProject} from '@/modelTypes/IProject' import LinkShareService from '@/services/linkShare' import {useCopyToClipboard} from '@/composables/useCopyToClipboard' import {success} from '@/message' import {getDisplayName} from '@/models/user' -import type {ListView} from '@/types/ListView' -import {LIST_VIEWS} from '@/types/ListView' +import type {ProjectView} from '@/types/ProjectView' +import {PROJECT_VIEWS} from '@/types/ProjectView' import {useConfigStore} from '@/stores/config' const props = defineProps({ - listId: { + projectId: { default: 0, required: true, }, @@ -222,20 +222,20 @@ const showDeleteModal = ref(false) const linkIdToDelete = ref(0) const showNewForm = ref(false) -type SelectedViewMapper = Record +type SelectedViewMapper = Record const selectedView = ref({}) -const availableViews = computed>(() => ({ - list: t('list.list.title'), - gantt: t('list.gantt.title'), - table: t('list.table.title'), - kanban: t('list.kanban.title'), +const availableViews = computed>(() => ({ + list: t('project.list.title'), + gantt: t('project.gantt.title'), + table: t('project.table.title'), + kanban: t('project.kanban.title'), })) const copy = useCopyToClipboard() watch( - () => props.listId, + () => props.projectId, load, {immediate: true}, ) @@ -243,23 +243,23 @@ watch( const configStore = useConfigStore() const frontendUrl = computed(() => configStore.frontendUrl) -async function load(listId: IList['id']) { - // If listId == 0 the list on the calling component wasn't already loaded, so we just bail out here - if (listId === 0) { +async function load(projectId: IProject['id']) { + // If projectId == 0 the project on the calling component wasn't already loaded, so we just bail out here + if (projectId === 0) { return } - const links = await linkShareService.getAll({listId}) + const links = await linkShareService.getAll({projectId}) links.forEach((l: ILinkShare) => { - selectedView.value[l.id] = 'list' + selectedView.value[l.id] = 'project' }) linkShares.value = links } -async function add(listId: IList['id']) { +async function add(projectId: IProject['id']) { const newLinkShare = new LinkShareModel({ right: selectedRight.value, - listId, + projectId, name: name.value, password: password.value, }) @@ -268,31 +268,31 @@ async function add(listId: IList['id']) { name.value = '' password.value = '' showNewForm.value = false - success({message: t('list.share.links.createSuccess')}) - await load(listId) + success({message: t('project.share.links.createSuccess')}) + await load(projectId) } -async function remove(listId: IList['id']) { +async function remove(projectId: IProject['id']) { try { await linkShareService.delete(new LinkShareModel({ id: linkIdToDelete.value, - listId, + projectId, })) - success({message: t('list.share.links.deleteSuccess')}) - await load(listId) + success({message: t('project.share.links.deleteSuccess')}) + await load(projectId) } finally { showDeleteModal.value = false } } -function getShareLink(hash: string, view: ListView = LIST_VIEWS.LIST) { +function getShareLink(hash: string, view: ProjectView = PROJECT_VIEWS.LIST) { return frontendUrl.value + 'share/' + hash + '/auth?view=' + view } \ No newline at end of file diff --git a/src/components/sharing/userTeam.vue b/src/components/sharing/userTeam.vue index 90ef38978..099887f71 100644 --- a/src/components/sharing/userTeam.vue +++ b/src/components/sharing/userTeam.vue @@ -1,7 +1,7 @@ @@ -52,19 +52,19 @@ - {{ $t('list.share.right.admin') }} + {{ $t('project.share.right.admin') }} @@ -78,19 +78,19 @@ :selected="s.right === RIGHTS.READ" :value="RIGHTS.READ" > - {{ $t('list.share.right.read') }} + {{ $t('project.share.right.read') }} @@ -110,7 +110,7 @@ - {{ $t('list.share.userTeam.notShared', {type: shareTypeNames}) }} + {{ $t('project.share.userTeam.notShared', {type: shareTypeNames}) }} @@ -143,9 +143,9 @@ import UserNamespaceService from '@/services/userNamespace' import UserNamespaceModel from '@/models/userNamespace' import type {IUserNamespace} from '@/modelTypes/IUserNamespace' -import UserListService from '@/services/userList' -import UserListModel from '@/models/userList' -import type {IUserList} from '@/modelTypes/IUserList' +import UserProjectService from '@/services/userProject' +import UserProjectModel from '@/models/userProject' +import type {IUserProject} from '@/modelTypes/IUserProject' import UserService from '@/services/user' import UserModel, { getDisplayName } from '@/models/user' @@ -155,9 +155,9 @@ import TeamNamespaceService from '@/services/teamNamespace' import TeamNamespaceModel from '@/models/teamNamespace' import type { ITeamNamespace } from '@/modelTypes/ITeamNamespace' -import TeamListService from '@/services/teamList' -import TeamListModel from '@/models/teamList' -import type { ITeamList } from '@/modelTypes/ITeamList' +import TeamProjectService from '@/services/teamProject' +import TeamProjectModel from '@/models/teamProject' +import type { ITeamProject } from '@/modelTypes/ITeamProject' import TeamService from '@/services/team' import TeamModel from '@/models/team' @@ -172,7 +172,7 @@ import {useAuthStore} from '@/stores/auth' const props = defineProps({ type: { - type: String as PropType<'list' | 'namespace'>, + type: String as PropType<'project' | 'namespace'>, default: '', }, shareType: { @@ -191,9 +191,9 @@ const props = defineProps({ const {t} = useI18n({useScope: 'global'}) -// This user service is either a userNamespaceService or a userListService, depending on the type we are using -let stuffService: UserNamespaceService | UserListService | TeamListService | TeamNamespaceService -let stuffModel: IUserNamespace | IUserList | ITeamList | ITeamNamespace +// This user service is either a userNamespaceService or a userProjectService, depending on the type we are using +let stuffService: UserNamespaceService | UserProjectService | TeamProjectService | TeamNamespaceService +let stuffModel: IUserNamespace | IUserProject | ITeamProject | ITeamNamespace let searchService: UserService | TeamService let sharable: Ref @@ -201,7 +201,7 @@ const searchLabel = ref('') const selectedRight = ref({}) -// This holds either teams or users who this namepace or list is shared with +// This holds either teams or users who this namepace or project is shared with const sharables = ref([]) const showDeleteModal = ref(false) @@ -212,11 +212,11 @@ const userInfo = computed(() => authStore.info) function createShareTypeNameComputed(count: number) { return computed(() => { if (props.shareType === 'user') { - return t('list.share.userTeam.typeUser', count) + return t('project.share.userTeam.typeUser', count) } if (props.shareType === 'team') { - return t('list.share.userTeam.typeTeam', count) + return t('project.share.userTeam.typeTeam', count) } return '' @@ -227,8 +227,8 @@ const shareTypeNames = createShareTypeNameComputed(2) const shareTypeName = createShareTypeNameComputed(1) const sharableName = computed(() => { - if (props.type === 'list') { - return t('list.list.title') + if (props.type === 'project') { + return t('project.list.title') } if (props.shareType === 'namespace') { @@ -244,9 +244,9 @@ if (props.shareType === 'user') { sharable = ref(new UserModel()) searchLabel.value = 'username' - if (props.type === 'list') { - stuffService = shallowReactive(new UserListService()) - stuffModel = reactive(new UserListModel({listId: props.id})) + if (props.type === 'project') { + stuffService = shallowReactive(new UserProjectService()) + stuffModel = reactive(new UserProjectModel({projectId: props.id})) } else if (props.type === 'namespace') { stuffService = shallowReactive(new UserNamespaceService()) stuffModel = reactive(new UserNamespaceModel({ @@ -261,9 +261,9 @@ if (props.shareType === 'user') { sharable = ref(new TeamModel()) searchLabel.value = 'name' - if (props.type === 'list') { - stuffService = shallowReactive(new TeamListService()) - stuffModel = reactive(new TeamListModel({listId: props.id})) + if (props.type === 'project') { + stuffService = shallowReactive(new TeamProjectService()) + stuffModel = reactive(new TeamProjectModel({projectId: props.id})) } else if (props.type === 'namespace') { stuffService = shallowReactive(new TeamNamespaceService()) stuffModel = reactive(new TeamNamespaceModel({ @@ -303,7 +303,7 @@ async function deleteSharable() { } } success({ - message: t('list.share.userTeam.removeSuccess', { + message: t('project.share.userTeam.removeSuccess', { type: shareTypeName.value, sharable: sharableName.value, }), @@ -326,7 +326,7 @@ async function add(admin) { } await stuffService.create(stuffModel) - success({message: t('list.share.userTeam.addedSuccess', {type: shareTypeName.value})}) + success({message: t('project.share.userTeam.addedSuccess', {type: shareTypeName.value})}) await load() } @@ -358,7 +358,7 @@ async function toggleType(sharable) { sharables.value[i].right = r.right } } - success({message: t('list.share.userTeam.updatedSuccess', {type: shareTypeName.value})}) + success({message: t('project.share.userTeam.updatedSuccess', {type: shareTypeName.value})}) } const found = ref([]) diff --git a/src/components/tasks/GanttChart.vue b/src/components/tasks/GanttChart.vue index 5cca40c93..e9ea8f999 100644 --- a/src/components/tasks/GanttChart.vue +++ b/src/components/tasks/GanttChart.vue @@ -50,7 +50,7 @@ import {parseKebabDate} from '@/helpers/time/parseKebabDate' import type {ITask, ITaskPartialWithId} from '@/modelTypes/ITask' import type {DateISO} from '@/types/DateISO' -import type {GanttFilters} from '@/views/list/helpers/useGanttFilters' +import type {GanttFilters} from '@/views/project/helpers/useGanttFilters' import { extendDayjs, diff --git a/src/components/tasks/add-task.vue b/src/components/tasks/add-task.vue index 96b7a8156..834709f70 100644 --- a/src/components/tasks/add-task.vue +++ b/src/components/tasks/add-task.vue @@ -5,7 +5,7 @@