Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BC-6781 - Add Etherpad in Board in API (BE) #3206

Closed
wants to merge 52 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
92585d5
added collaborative text editor element
KalliSfak Apr 10, 2024
94f9942
BC-3577 - add locales
SevenWaysDP Apr 10, 2024
450ff01
BC-3577 - revert changes
SevenWaysDP Apr 10, 2024
20336ea
text editor element connection
KalliSfak Apr 10, 2024
3a6a3b8
test for contentElementList
KalliSfak Apr 11, 2024
13d4690
test for addElementDialog composable
KalliSfak Apr 11, 2024
603073d
test for innerContent
KalliSfak Apr 11, 2024
2a4d3d8
test for collaborativeTextEditor
KalliSfak Apr 11, 2024
f9e4caa
renaming
KalliSfak Apr 11, 2024
2762cc0
refactored collaborativeTextEditor component
KalliSfak Apr 12, 2024
9bf22cd
refactor test
KalliSfak Apr 12, 2024
8c082fc
Merge branch 'main' into BC-3577-add-texteditor-to-columnboard
bergatco Apr 15, 2024
a30a95a
added tests
KalliSfak Apr 15, 2024
74cddb4
Merge branch 'BC-3577-add-texteditor-to-columnboard' of github.com:hp…
KalliSfak Apr 15, 2024
8b8de04
test refactored
KalliSfak Apr 15, 2024
4cec651
Merge branch 'main' into BC-6781-add-collab-editor-element
bergatco Apr 16, 2024
8d75ce6
Merge branch 'main' into BC-3577-add-texteditor-to-columnboard
SevenWaysDP Apr 16, 2024
c666ac2
BC-3577 - add API calls and some refactoring
bergatco Apr 16, 2024
3dc77c4
Merge branch 'BC-3577-add-texteditor-to-columnboard' into BC-6781-add…
bergatco Apr 16, 2024
3410c0d
BC-3577 - move `getUrl` to fire on click
bergatco Apr 16, 2024
4985177
Merge branch 'main' into BC-6781-add-collab-editor-element
bischofmax Apr 17, 2024
4a63d43
Add collaborative text editor response factory
bischofmax Apr 18, 2024
3f10353
Remove collaborative text editor component
bischofmax Apr 18, 2024
733acf8
Remove sanitize url and remove unecessary div
bischofmax Apr 18, 2024
423a0b1
Remove fixed height on image and add alt text
bischofmax Apr 18, 2024
8ebf052
Fix error handling and add translation for server error message
bischofmax Apr 18, 2024
b526afa
Remove shared folder
bischofmax Apr 18, 2024
ee92808
Remove isTeacher check on BoardMenu
bischofmax Apr 18, 2024
4ac5efb
Add Element Menu and fix tests
bischofmax Apr 18, 2024
7fa675d
Merge branch 'BC-3577-add-texteditor-to-columnboard' into BC-6781-add…
bergatco Apr 18, 2024
f7463b9
BC-3577 - fix unit tests for `CollaborativeTextEditorElement`
bergatco Apr 18, 2024
9e4d2b7
BC-3577 - some cleaning up and adding unit tests for `CollaborativeTe…
bergatco Apr 18, 2024
48c7a70
BC-3577 - add unit tests for `CollaborativeTextEditorNotifications`
bergatco Apr 18, 2024
ac7ec18
BC-3577 - add unit tests for `CollaborativeTextEditorApi.composable`
bergatco Apr 18, 2024
97f7511
Merge branch 'main' into BC-6781-add-collab-editor-element
bergatco Apr 18, 2024
cd66374
Merge branch 'main' into BC-3577-add-texteditor-to-columnboard
bergatco Apr 18, 2024
c2d23d4
BC-3577 - fix naming error in unit tests for `CollaborativeTextEditor…
bergatco Apr 19, 2024
554585c
Merge branch 'BC-3577-add-texteditor-to-columnboard' into BC-6781-add…
bergatco Apr 19, 2024
806bfcb
BC-3577 - remove `throw error` and add `undefined` case for `getUrl`
bergatco Apr 19, 2024
4323424
BC-3577 - fix typo in unit tests
bergatco Apr 19, 2024
40a7e67
BC-3577 - fix another typo in unit tests
bergatco Apr 19, 2024
89c95ba
BC-3577 - generate client
bergatco Apr 19, 2024
bc08106
Merge branch 'main' into BC-3577-add-texteditor-to-columnboard
bergatco Apr 19, 2024
09c5a0a
BC-3577 - adapt unit tests to latest server changes
bergatco Apr 19, 2024
c90e75a
Merge branch 'main' into BC-3577-add-texteditor-to-columnboard
bischofmax Apr 22, 2024
353b6da
Merge branch 'BC-3577-add-texteditor-to-columnboard' into BC-6781-add…
bischofmax Apr 22, 2024
891432d
Merge branch 'main' into BC-6781-add-collab-editor-element
bischofmax Apr 22, 2024
af2d993
Merge branch 'main' into BC-3577-add-texteditor-to-columnboard
bischofmax Apr 22, 2024
b8241fb
Change handling of window open for safari
bischofmax Apr 22, 2024
d133cdd
Merge branch 'BC-3577-add-texteditor-to-columnboard' into BC-6781-add…
bischofmax Apr 22, 2024
d5f9225
Merge branch 'BC-6781-add-collab-editor-element' of github.com:hpi-sc…
bischofmax Apr 22, 2024
a9fd1f0
Fix editor test
bischofmax Apr 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions src/assets/img/collaborativeEditor.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/assets/img/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ declare module "@/assets/img/image-not-available.svg" {
const value: string;
export default value;
}

declare module "@/assets/img/collaborativeEditor.svg" {
const value: string;
export default value;
}
3 changes: 3 additions & 0 deletions src/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ export default {
"components.cardElement.deleteElement": "löschen",
"components.cardElement.dragElement": "verschieben",
"components.cardElement.drawingElement": "Whiteboard",
"components.cardElement.collaborativeTextEditorElement": "Texteditor",
"components.cardElement.fileElement.altDescription":
"Eine kurze Beschreibung hilft Personen, die das Bild nicht sehen können.",
"components.cardElement.fileElement.alternativeText": "Alternativtext",
Expand Down Expand Up @@ -367,6 +368,8 @@ export default {
"components.elementTypeSelection.elements.externalToolElement.subtitle":
"Externe Tools",
"components.elementTypeSelection.elements.fileElement.subtitle": "Datei",
"components.elementTypeSelection.elements.collaborativeTextEditor.subtitle":
"Texteditor",
"components.elementTypeSelection.elements.linkElement.subtitle": "Link",
"components.elementTypeSelection.elements.submissionElement.subtitle":
"Abgabe",
Expand Down
3 changes: 3 additions & 0 deletions src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ export default {
"components.cardElement.deleteElement": "Delete element",
"components.cardElement.dragElement": "Move element",
"components.cardElement.drawingElement": "Whiteboard",
"components.cardElement.collaborativeTextEditorElement": "Texteditor",
"components.cardElement.fileElement.altDescription":
"A short description helps people who cannot see the picture.",
"components.cardElement.fileElement.alternativeText": "Alternative Text",
Expand Down Expand Up @@ -363,6 +364,8 @@ export default {
"components.elementTypeSelection.elements.externalToolElement.subtitle":
"External tools",
"components.elementTypeSelection.elements.fileElement.subtitle": "File",
"components.elementTypeSelection.elements.collaborativeTextEditor.subtitle":
"Texteditor",
"components.elementTypeSelection.elements.linkElement.subtitle": "Link",
"components.elementTypeSelection.elements.submissionElement.subtitle":
"Submission",
Expand Down
6 changes: 5 additions & 1 deletion src/locales/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ export default {
"components.cardElement.deleteElement": "Suprimir elemento",
"components.cardElement.dragElement": "Mover elemento",
"components.cardElement.drawingElement": "Pizarra",
"components.cardElement.collaborativeTextEditorElement": "Texteditor",
"components.cardElement.fileElement.altDescription":
"Una breve descripción ayuda a las personas que no pueden ver la imagen.",
"components.cardElement.fileElement.alternativeText": "Texto alternativo",
Expand Down Expand Up @@ -369,7 +370,10 @@ export default {
"components.elementTypeSelection.dialog.title": "Añadir elemento",
"components.elementTypeSelection.elements.externalToolElement.subtitle":
"Herramientas externas",
"components.elementTypeSelection.elements.fileElement.subtitle": "Archivo",
"components.elementTypeSelection.elements.fileElement.subtitle":
"Editor de texto",
"components.elementTypeSelection.elements.collaborativeTextEditor.subtitle":
"Text Editor",
"components.elementTypeSelection.elements.linkElement.subtitle": "Enlace",
"components.elementTypeSelection.elements.submissionElement.subtitle":
"Envíos",
Expand Down
3 changes: 3 additions & 0 deletions src/locales/uk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ export default {
"components.cardElement.deleteElement": "Видалити елемент",
"components.cardElement.dragElement": "Перемістити елемент",
"components.cardElement.drawingElement": "Дошка",
"components.cardElement.collaborativeTextEditorElement": "Texteditor",
"components.cardElement.fileElement.altDescription":
"Короткий опис допомагає людям, які не бачать зображення.",
"components.cardElement.fileElement.alternativeText": "альтернативний текст",
Expand Down Expand Up @@ -370,6 +371,8 @@ export default {
"components.elementTypeSelection.elements.externalToolElement.subtitle":
"Зовнішні інструменти",
"components.elementTypeSelection.elements.fileElement.subtitle": "Файл",
"components.elementTypeSelection.elements.collaborativeTextEditor.subtitle":
"Текстовий редактор",
"components.elementTypeSelection.elements.linkElement.subtitle": "Посилання",
"components.elementTypeSelection.elements.submissionElement.subtitle":
"Подання",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
import { CollaborativeTextEditorParentType } from "@/serverApi/v3";
import NotifierModule from "@/store/notifier";
import { NOTIFIER_MODULE_KEY } from "@/utils/inject";
import { createModuleMocks } from "@/utils/mock-store-module";
import { collaborativeTextEditorElementResponseFactory } from "@@/tests/test-utils";
import {
createTestingI18n,
createTestingVuetify,
} from "@@/tests/test-utils/setup";
import { CollaborativeTextEditorElement } from "@feature-board-collaborative-text-editor-element";
import { createMock } from "@golevelup/ts-jest";
import { ContentElementBar } from "@ui-board";
import { mount } from "@vue/test-utils";
import { nextTick } from "vue";
import CollaborativeTextEditorElementMenu from "./components/CollaborativeTextEditorElementMenu.vue";
import { setupCollaborativeTextEditorApiMock } from "./test-utils/collaborativeTextEditorApiMock";

// Mocks
jest.mock("@data-board", () => ({
useBoardFocusHandler: jest.fn(),
useContentElementState: jest.fn(() => ({ modelValue: {} })),
useDeleteConfirmationDialog: jest.fn(),
}));
jest.mock("@feature-board");
jest.mock("./composables/CollaborativeTextEditorApi.composable");

describe("CollaborativeTextEditorElement", () => {
const notifierModule = createModuleMocks(NotifierModule);

const setup = (props: { isEditMode: boolean; getUrlHasError?: boolean }) => {
document.body.setAttribute("data-app", "true");

const element = collaborativeTextEditorElementResponseFactory.build();

const resolvedValue = props.getUrlHasError
? undefined
: `${CollaborativeTextEditorParentType.ContentElement}/${element.id}`;
const getUrlMock = jest.fn().mockResolvedValueOnce(resolvedValue);

const { getUrl } = setupCollaborativeTextEditorApiMock({
getUrlMock,
});

const wrapper = mount(CollaborativeTextEditorElement, {
global: {
plugins: [createTestingVuetify(), createTestingI18n()],
provide: {
[NOTIFIER_MODULE_KEY.valueOf()]: notifierModule,
},
},
propsData: { ...props, element: element },
});

const windowMock = createMock<Window>();
jest.spyOn(window, "open").mockImplementation(() => windowMock);

return {
wrapper,
isEditMode: true,
element: element,
getUrl,
windowMock,
};
};

afterEach(() => {
jest.resetAllMocks();
});

describe("when component is not in edit-mode", () => {
it("should render the element corrrectly", () => {
const { wrapper } = setup({
isEditMode: false,
});
expect(
wrapper.findComponent(CollaborativeTextEditorElement).isVisible()
).toBe(true);
});

it("should render the ContentElementBar", () => {
const { wrapper } = setup({
isEditMode: false,
});
expect(wrapper.findComponent(ContentElementBar).exists()).toBe(true);
});

it("should not render the BoardMenu", () => {
const { wrapper } = setup({
isEditMode: false,
});

const boardMenu = wrapper.findComponent(
CollaborativeTextEditorElementMenu
);

expect(boardMenu.exists()).toBe(false);
});

describe("when element is clicked", () => {
describe("when getUrl returns successful", () => {
it("should call getUrl", async () => {
const { wrapper, element, getUrl } = setup({
isEditMode: false,
});

const card = wrapper.findComponent({
ref: "collaborativetextEditorElement",
});

await card.trigger("click");

expect(getUrl).toHaveBeenCalledTimes(1);
expect(getUrl).toHaveBeenCalledWith(
element.id,
CollaborativeTextEditorParentType.ContentElement
);
});

it("should open collaborative text editor in new tab", async () => {
const { wrapper, element, windowMock } = setup({
isEditMode: false,
});

const card = wrapper.findComponent({
ref: "collaborativetextEditorElement",
});

await card.trigger("click");

expect(window.open).toHaveBeenCalledTimes(1);
expect(windowMock.location).toBe(
`${CollaborativeTextEditorParentType.ContentElement}/${element.id}`
);
});
});

describe("when getUrl returns undefined", () => {
it("should not open new tab", async () => {
const { wrapper, windowMock, element } = setup({
isEditMode: false,
getUrlHasError: true,
});

const card = wrapper.findComponent({
ref: "collaborativetextEditorElement",
});

await card.trigger("click");

expect(window.open).toHaveBeenCalledTimes(1);
expect(windowMock.location).not.toBe(
`${CollaborativeTextEditorParentType.ContentElement}/${element.id}`
);
});
});
});
});

describe("when component is in edit-mode", () => {
it("should render BoardMenu element", async () => {
const { wrapper } = setup({
isEditMode: true,
});

const boardMenu = wrapper.findComponent(
CollaborativeTextEditorElementMenu
);
expect(boardMenu.exists()).toBe(true);
});

describe("when move down is emitted by CollaborativeTextEditorElementMenu", () => {
it('should emit "move-down:edit" collaborative text editor', async () => {
const { wrapper } = setup({
isEditMode: true,
});

const boardMenu = wrapper.findComponent(
CollaborativeTextEditorElementMenu
);
boardMenu.vm.$emit("move-down:element");

expect(wrapper.emitted("move-down:edit")).toBeTruthy();
});
});

describe("when move up is clicked", () => {
it('should emit "move-up" collaborative text editor', async () => {
const { wrapper } = setup({
isEditMode: true,
});

const boardMenu = wrapper.findComponent(
CollaborativeTextEditorElementMenu
);
boardMenu.vm.$emit("move-up:element");

expect(wrapper.emitted("move-up:edit")).toBeTruthy();
});
});

describe("when delete is clicked", () => {
it('should emit "delete" collaborative text editor', async () => {
const { wrapper } = setup({
isEditMode: true,
});

const boardMenu = wrapper.findComponent(
CollaborativeTextEditorElementMenu
);
boardMenu.vm.$emit("delete:element", Promise.resolve(true));
await nextTick();

expect(wrapper.emitted("delete:element")).toBeTruthy();
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<template>
<v-card
class="mb-4"
data-testid="collaborative-text-editor-element"
variant="outlined"
ref="collaborativetextEditorElement"
:ripple="false"
tabindex="0"
elevation="0"
@keydown.up.down="onKeydownArrow"
role="button"
@click="redirectToEditorUrl"
>
<ContentElementBar :hasGreyBackground="true" :icon="mdiTextBoxEditOutline">
<template #display>
<v-img
:src="image"
:alt="$t('components.cardElement.collaborativeTextEditorElement')"
cover
class="rounded-t"
/>
</template>
<template #title>
{{ $t("components.cardElement.collaborativeTextEditorElement") }}
</template>
<template #menu>
<CollaborativeTextEditorElementMenu
v-if="isEditMode"
@move-down:element="onMoveDown"
@move-up:element="onMoveUp"
@delete:element="onDelete"
/>
</template>
</ContentElementBar>
</v-card>
</template>

<script setup lang="ts">
import image from "@/assets/img/collaborativeEditor.svg";
import {
CollaborativeTextEditorElementResponse,
CollaborativeTextEditorParentType,
} from "@/serverApi/v3";
import { useBoardFocusHandler } from "@data-board";
import { mdiTextBoxEditOutline } from "@mdi/js";
import { ContentElementBar } from "@ui-board";
import { PropType, ref, toRef } from "vue";
import CollaborativeTextEditorElementMenu from "./components/CollaborativeTextEditorElementMenu.vue";
import { useCollaborativeTextEditorApi } from "./composables/CollaborativeTextEditorApi.composable";

const props = defineProps({
element: {
type: Object as PropType<CollaborativeTextEditorElementResponse>,
required: true,
},
isEditMode: { type: Boolean, required: true },
});

const emit = defineEmits([
"delete:element",
"move-down:edit",
"move-up:edit",
"move-keyboard:edit",
]);

const collaborativeTextEditorElement = ref<HTMLElement | null>(null);
const element = toRef(props, "element");
useBoardFocusHandler(element.value.id, collaborativeTextEditorElement);

const { getUrl } = useCollaborativeTextEditorApi();

const redirectToEditorUrl = async () => {
const windowReference = window.open();

getUrl(
element.value.id,
CollaborativeTextEditorParentType.ContentElement
).then((url) => {
if (url && windowReference) {
windowReference.location = url;
}
});
};

const onKeydownArrow = (event: KeyboardEvent) => {
if (props.isEditMode) {
event.preventDefault();
emit("move-keyboard:edit", event);
}
};
const onDelete = async (confirmation: Promise<boolean>) => {
const shouldDelete = await confirmation;
if (shouldDelete) {
emit("delete:element", props.element.id);
}
};

const onMoveUp = () => emit("move-up:edit");
const onMoveDown = () => emit("move-down:edit");
</script>
Loading
Loading