From 6178f20330179074d1df5a93deec57669aa3e26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20=C3=96hlerking?= <103562092+MarvinOehlerkingCap@users.noreply.github.com> Date: Thu, 22 Aug 2024 10:25:38 +0200 Subject: [PATCH] N21-2031 Placeholder element for deleted tools in boards (#3363) --- config/webpack/webpack.common.js | 3 + .../ExternalToolSelectionRow.vue | 2 +- src/locales/de.ts | 3 + src/locales/en.ts | 3 + src/locales/es.ts | 4 + src/locales/uk.ts | 3 + .../DeletedElement.unit.ts | 188 ++++++++++ .../board-deleted-element/DeletedElement.vue | 71 ++++ .../DeletedElementMenu.unit.ts | 47 +++ .../DeletedElementMenu.vue | 20 ++ .../feature/board-deleted-element/index.ts | 3 + src/modules/feature/board/card/CardHost.vue | 8 +- .../board/card/ContentElementList.unit.ts | 5 + .../feature/board/card/ContentElementList.vue | 326 ++++++++---------- src/modules/ui/board/BoardMenu.vue | 7 +- src/modules/ui/board/board-menu-scope.ts | 3 +- src/serverApi/v3/api.ts | 67 +++- tsconfig.json | 1 + 18 files changed, 573 insertions(+), 191 deletions(-) create mode 100644 src/modules/feature/board-deleted-element/DeletedElement.unit.ts create mode 100644 src/modules/feature/board-deleted-element/DeletedElement.vue create mode 100644 src/modules/feature/board-deleted-element/DeletedElementMenu.unit.ts create mode 100644 src/modules/feature/board-deleted-element/DeletedElementMenu.vue create mode 100644 src/modules/feature/board-deleted-element/index.ts diff --git a/config/webpack/webpack.common.js b/config/webpack/webpack.common.js index 3aa8238d8d..72f1228b4c 100644 --- a/config/webpack/webpack.common.js +++ b/config/webpack/webpack.common.js @@ -144,6 +144,9 @@ module.exports = { "@feature-board-collaborative-text-editor-element": getDir( "src/modules/feature/board-collaborative-text-editor-element" ), + "@feature-board-deleted-element": getDir( + "src/modules/feature/board-deleted-element" + ), "@feature-course-sync": getDir("src/modules/feature/course-sync"), "@feature-board": getDir("src/modules/feature/board"), "@feature-editor": getDir("src/modules/feature/editor"), diff --git a/src/components/external-tools/configuration/ExternalToolSelectionRow.vue b/src/components/external-tools/configuration/ExternalToolSelectionRow.vue index 2b2674d381..845d18aaf4 100644 --- a/src/components/external-tools/configuration/ExternalToolSelectionRow.vue +++ b/src/components/external-tools/configuration/ExternalToolSelectionRow.vue @@ -16,7 +16,7 @@ diff --git a/src/modules/feature/board-deleted-element/DeletedElementMenu.unit.ts b/src/modules/feature/board-deleted-element/DeletedElementMenu.unit.ts new file mode 100644 index 0000000000..899868624b --- /dev/null +++ b/src/modules/feature/board-deleted-element/DeletedElementMenu.unit.ts @@ -0,0 +1,47 @@ +import { + createTestingI18n, + createTestingVuetify, +} from "@@/tests/test-utils/setup"; +import { BoardMenuActionDelete } from "@ui-board"; +import { shallowMount } from "@vue/test-utils"; +import DeletedElementMenu from "./DeletedElementMenu.vue"; + +describe("DeletedElementMenu", () => { + const getWrapper = () => { + document.body.setAttribute("data-app", "true"); + + const wrapper = shallowMount(DeletedElementMenu, { + global: { + plugins: [createTestingVuetify(), createTestingI18n()], + }, + }); + + return { + wrapper, + }; + }; + + afterEach(() => { + jest.resetAllMocks(); + }); + + describe("Delete Button", () => { + it("should have a menu option to delete", () => { + const { wrapper } = getWrapper(); + + const menuItem = wrapper.findComponent(BoardMenuActionDelete); + + expect(menuItem.exists()).toEqual(true); + }); + + it("should emit the delete event on click", async () => { + const { wrapper } = getWrapper(); + + const menuItem = wrapper.findComponent(BoardMenuActionDelete); + + await menuItem.trigger("click"); + + expect(wrapper.emitted("delete:element")).toBeDefined(); + }); + }); +}); diff --git a/src/modules/feature/board-deleted-element/DeletedElementMenu.vue b/src/modules/feature/board-deleted-element/DeletedElementMenu.vue new file mode 100644 index 0000000000..6fb2174569 --- /dev/null +++ b/src/modules/feature/board-deleted-element/DeletedElementMenu.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/modules/feature/board-deleted-element/index.ts b/src/modules/feature/board-deleted-element/index.ts new file mode 100644 index 0000000000..54dcd4a44a --- /dev/null +++ b/src/modules/feature/board-deleted-element/index.ts @@ -0,0 +1,3 @@ +import DeletedElement from "./DeletedElement.vue"; + +export { DeletedElement }; diff --git a/src/modules/feature/board/card/CardHost.vue b/src/modules/feature/board/card/CardHost.vue index bca6ebc900..295caea787 100644 --- a/src/modules/feature/board/card/CardHost.vue +++ b/src/modules/feature/board/card/CardHost.vue @@ -33,7 +33,11 @@ />
- + { elementType: ContentElementType.CollaborativeTextEditor, component: CollaborativeTextEditorElement, }, + { + elementType: ContentElementType.Deleted, + component: DeletedElement, + }, ]; it.each(elementComponents)( diff --git a/src/modules/feature/board/card/ContentElementList.vue b/src/modules/feature/board/card/ContentElementList.vue index 289b8e17e1..a9daf72510 100644 --- a/src/modules/feature/board/card/ContentElementList.vue +++ b/src/modules/feature/board/card/ContentElementList.vue @@ -73,15 +73,22 @@ @move-up:edit="onMoveElementUp(index, element)" @delete:element="onDeleteElement" /> + - diff --git a/src/modules/ui/board/BoardMenu.vue b/src/modules/ui/board/BoardMenu.vue index 337c3fb97f..c8e99af5b2 100644 --- a/src/modules/ui/board/BoardMenu.vue +++ b/src/modules/ui/board/BoardMenu.vue @@ -17,7 +17,7 @@ > {{ mdiDotsVertical }} - {{ t(boardMenuAriaLabel) }} + {{ $t(boardMenuAriaLabel) }} @@ -32,7 +32,6 @@ import { mdiDotsVertical } from "@mdi/js"; import { computed, PropType, provide, toRef } from "vue"; import { BoardMenuScope } from "./board-menu-scope"; import { MENU_SCOPE } from "./injection-tokens"; -import { useI18n } from "vue-i18n"; const props = defineProps({ scope: { @@ -48,8 +47,6 @@ const props = defineProps({ const scope = toRef(props, "scope"); provide(MENU_SCOPE, scope.value); -const { t } = useI18n(); - const ariaLabelForScope: Record = { board: "components.board.menu.board", column: "components.board.menu.column", @@ -61,6 +58,7 @@ const ariaLabelForScope: Record = { fileElement: "components.board.menu.fileElement", linkElement: "components.board.menu.linkElement", submissionElement: "components.board.menu.submissionElement", + deletedElement: "components.board.menu.deletedElement", }; const boardMenuAriaLabel = computed(() => { @@ -75,6 +73,7 @@ const boardScopesWithBackground: Array = [ "fileElement", "linkElement", "submissionElement", + "deletedElement", ]; const hasBackground = computed(() => diff --git a/src/modules/ui/board/board-menu-scope.ts b/src/modules/ui/board/board-menu-scope.ts index bda0b49fbe..ae38e09e1b 100644 --- a/src/modules/ui/board/board-menu-scope.ts +++ b/src/modules/ui/board/board-menu-scope.ts @@ -7,4 +7,5 @@ export type BoardMenuScope = | "externalToolElement" | "fileElement" | "linkElement" - | "submissionElement"; + | "submissionElement" + | "deletedElement"; diff --git a/src/serverApi/v3/api.ts b/src/serverApi/v3/api.ts index e1ef1b70b6..907f9c3e28 100644 --- a/src/serverApi/v3/api.ts +++ b/src/serverApi/v3/api.ts @@ -439,10 +439,10 @@ export interface CardResponse { height: number; /** * - * @type {Array} + * @type {Array} * @memberof CardResponse */ - elements: Array; + elements: Array; /** * * @type {VisibilitySettingsResponse} @@ -1347,7 +1347,8 @@ export enum ContentElementType { RichText = 'richText', SubmissionContainer = 'submissionContainer', ExternalTool = 'externalTool', - CollaborativeTextEditor = 'collaborativeTextEditor' + CollaborativeTextEditor = 'collaborativeTextEditor', + Deleted = 'deleted' } /** @@ -1660,6 +1661,7 @@ export enum CopyApiResponseTypeEnum { Content = 'CONTENT', Course = 'COURSE', CoursegroupGroup = 'COURSEGROUP_GROUP', + DeletedElement = 'DELETED_ELEMENT', ExternalTool = 'EXTERNAL_TOOL', ExternalToolElement = 'EXTERNAL_TOOL_ELEMENT', File = 'FILE', @@ -1959,7 +1961,8 @@ export enum CreateCardBodyParamsRequiredEmptyElementsEnum { RichText = 'richText', SubmissionContainer = 'submissionContainer', ExternalTool = 'externalTool', - CollaborativeTextEditor = 'collaborativeTextEditor' + CollaborativeTextEditor = 'collaborativeTextEditor', + Deleted = 'deleted' } /** @@ -2403,6 +2406,56 @@ export interface DashboardResponse { */ gridElements: Array; } +/** + * + * @export + * @interface DeletedElementContent + */ +export interface DeletedElementContent { + /** + * + * @type {string} + * @memberof DeletedElementContent + */ + title: string; + /** + * + * @type {ContentElementType} + * @memberof DeletedElementContent + */ + deletedElementType: ContentElementType; +} +/** + * + * @export + * @interface DeletedElementResponse + */ +export interface DeletedElementResponse { + /** + * + * @type {string} + * @memberof DeletedElementResponse + */ + id: string; + /** + * + * @type {ContentElementType} + * @memberof DeletedElementResponse + */ + type: ContentElementType; + /** + * + * @type {DeletedElementContent} + * @memberof DeletedElementResponse + */ + content: DeletedElementContent; + /** + * + * @type {TimestampsResponse} + * @memberof DeletedElementResponse + */ + timestamps: TimestampsResponse; +} /** * * @export @@ -11036,7 +11089,7 @@ export const BoardCardApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async cardControllerCreateElement(cardId: string, createContentElementBodyParams: CreateContentElementBodyParams, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async cardControllerCreateElement(cardId: string, createContentElementBodyParams: CreateContentElementBodyParams, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.cardControllerCreateElement(cardId, createContentElementBodyParams, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -11116,7 +11169,7 @@ export const BoardCardApiFactory = function (configuration?: Configuration, base * @param {*} [options] Override http request option. * @throws {RequiredError} */ - cardControllerCreateElement(cardId: string, createContentElementBodyParams: CreateContentElementBodyParams, options?: any): AxiosPromise { + cardControllerCreateElement(cardId: string, createContentElementBodyParams: CreateContentElementBodyParams, options?: any): AxiosPromise { return localVarFp.cardControllerCreateElement(cardId, createContentElementBodyParams, options).then((request) => request(axios, basePath)); }, /** @@ -11190,7 +11243,7 @@ export interface BoardCardApiInterface { * @throws {RequiredError} * @memberof BoardCardApiInterface */ - cardControllerCreateElement(cardId: string, createContentElementBodyParams: CreateContentElementBodyParams, options?: any): AxiosPromise; + cardControllerCreateElement(cardId: string, createContentElementBodyParams: CreateContentElementBodyParams, options?: any): AxiosPromise; /** * diff --git a/tsconfig.json b/tsconfig.json index 5f7f2402c3..a21e81d719 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -44,6 +44,7 @@ "@feature-render-html": ["src/modules/feature/render-html"], "@feature-news-form": ["src/modules/feature/news-form"], "@feature-media-shelf": ["src/modules/feature/media-shelf"], + "@feature-board-deleted-element": ["src/modules/feature/board-deleted-element"], "@ui-alert": ["src/modules/ui/alert"], "@ui-board": ["src/modules/ui/board"], "@ui-chip": ["src/modules/ui/chip"],