Skip to content

Commit

Permalink
N21 2089 placeholder element media shelf (#3401)
Browse files Browse the repository at this point in the history
  • Loading branch information
GordonNicholasCap committed Sep 17, 2024
1 parent 1b02ab8 commit 6e0ed21
Show file tree
Hide file tree
Showing 15 changed files with 304 additions and 44 deletions.
1 change: 1 addition & 0 deletions src/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export default {
"common.medium.chip.deactivated": "Deaktiviert",
"common.medium.chip.notLicensed": "Nicht freigeschaltet",
"common.medium.chip.incomplete": "Konfiguration unvollständig",
"common.medium.chip.noLongerAvailable": "Nicht mehr verfügbar",
"common.medium.information.admin": "Bitte Einstellungen überprüfen.",
"common.medium.information.student": "Bitte an eine Lehrkraft wenden.",
"common.medium.information.teacher": "Bitte an Schuladministrator:in wenden.",
Expand Down
1 change: 1 addition & 0 deletions src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export default {
"common.medium.chip.deactivated": "Disabled",
"common.medium.chip.notLicensed": "Not activated",
"common.medium.chip.incomplete": "Configuration incomplete",
"common.medium.chip.noLongerAvailable": "No longer available",
"common.medium.information.admin": "Please check settings.",
"common.medium.information.student": "Please contact a teacher.",
"common.medium.information.teacher":
Expand Down
1 change: 1 addition & 0 deletions src/locales/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export default {
"common.medium.chip.deactivated": "Desactivado",
"common.medium.chip.notLicensed": "No esta activado",
"common.medium.chip.incomplete": "Configuración incompleta",
"common.medium.chip.noLongerAvailable": "Ya no está disponible",
"common.medium.information.admin": "Por favor verifique la configuración.",
"common.medium.information.student": "Por favor contacte a un maestro.",
"common.medium.information.teacher":
Expand Down
1 change: 1 addition & 0 deletions src/locales/uk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export default {
"common.medium.chip.deactivated": "Вимкнено",
"common.medium.chip.notLicensed": "Не активовано",
"common.medium.chip.incomplete": "Конфігурація не завершена",
"common.medium.chip.noLongerAvailable": "Більше не доступний",
"common.medium.information.admin": "Перевірте налаштування.",
"common.medium.information.student": "Будь ласка, зверніться до вчителя.",
"common.medium.information.teacher":
Expand Down
31 changes: 11 additions & 20 deletions src/modules/feature/board-deleted-element/DeletedElement.unit.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ContentElementType, DeletedElementResponse } from "@/serverApi/v3";
import { timestampsResponseFactory } from "@@/tests/test-utils";
import { deletedElementResponseFactory } from "@@/tests/test-utils";
import {
createTestingI18n,
createTestingVuetify,
Expand All @@ -15,16 +14,6 @@ import DeletedElementMenu from "./DeletedElementMenu.vue";

jest.mock("@data-board");

const DELETED_ELEMENT: DeletedElementResponse = {
id: "deleted-element-id",
content: {
deletedElementType: ContentElementType.ExternalTool,
title: "Deleted Tool",
},
type: ContentElementType.Deleted,
timestamps: timestampsResponseFactory.build(),
};

describe("DeletedElement", () => {
let useBoardFocusHandlerMock: DeepMocked<
ReturnType<typeof useBoardFocusHandler>
Expand All @@ -50,7 +39,7 @@ describe("DeletedElement", () => {

const getWrapper = (
props: ComponentProps<typeof DeletedElement> = {
element: DELETED_ELEMENT,
element: deletedElementResponseFactory.build(),
isEditMode: false,
}
) => {
Expand All @@ -75,7 +64,7 @@ describe("DeletedElement", () => {
useBoardPermissionsMock.isTeacher = false;

const { wrapper } = getWrapper({
element: DELETED_ELEMENT,
element: deletedElementResponseFactory.build(),
isEditMode: true,
});

Expand All @@ -97,7 +86,7 @@ describe("DeletedElement", () => {
describe("when in edit mode", () => {
const setup = () => {
const { wrapper } = getWrapper({
element: DELETED_ELEMENT,
element: deletedElementResponseFactory.build(),
isEditMode: true,
});

Expand All @@ -118,7 +107,7 @@ describe("DeletedElement", () => {
describe("when not in edit mode", () => {
const setup = () => {
const { wrapper } = getWrapper({
element: DELETED_ELEMENT,
element: deletedElementResponseFactory.build(),
isEditMode: false,
});

Expand All @@ -138,24 +127,26 @@ describe("DeletedElement", () => {

describe("when deleting the element", () => {
const setup = () => {
const deletedElement = deletedElementResponseFactory.build();
const { wrapper } = getWrapper({
element: DELETED_ELEMENT,
element: deletedElement,
isEditMode: true,
});

return {
wrapper,
deletedElement,
};
};

it("should emit an event", async () => {
const { wrapper } = setup();
const { wrapper, deletedElement } = setup();

wrapper.findComponent(DeletedElementMenu).vm.$emit("delete:element");
await nextTick();

expect(wrapper.emitted("delete:element")).toEqual([
[DELETED_ELEMENT.id],
[deletedElement.id],
]);
});
});
Expand All @@ -165,7 +156,7 @@ describe("DeletedElement", () => {
describe("when the deleted element was an external tool element", () => {
const setup = () => {
const { wrapper } = getWrapper({
element: DELETED_ELEMENT,
element: deletedElementResponseFactory.build(),
isEditMode: true,
});

Expand Down
35 changes: 21 additions & 14 deletions src/modules/feature/media-shelf/MediaBoardElementDisplay.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,23 @@
:ripple="false"
>
<div class="position-relative">
<v-img
v-if="element.thumbnail"
:src="element.thumbnail"
:aspect-ratio="16 / 9"
width="100%"
data-testid="media-element-thumbnail"
/>
<v-img
v-else
:aspect-ratio="16 / 9"
width="100%"
src="@/assets/img/media-board/default_img_media_shelf.png"
data-testid="media-element-default-thumbnail"
/>
<div :class="{ 'opacity-60': isUnavailable }">
<v-img
v-if="element.thumbnail"
:src="element.thumbnail"
:aspect-ratio="16 / 9"
width="100%"
data-testid="media-element-thumbnail"
/>
<v-img
v-else
:aspect-ratio="16 / 9"
width="100%"
src="@/assets/img/media-board/default_img_media_shelf.png"
data-testid="media-element-default-thumbnail"
/>
</div>
<div v-if="$slots.imageOverlay" class="chip-position">
<slot name="imageOverlay" />
</div>
Expand Down Expand Up @@ -70,6 +73,10 @@ defineProps({
element: {
type: Object as PropType<MediaElementDisplay>,
},
isUnavailable: {
type: Boolean,
default: false,
},
});
const card = ref(null);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {
createTestingI18n,
createTestingVuetify,
} from "@@/tests/test-utils/setup";
import { deletedElementResponseFactory } from "@@/tests/test-utils";
import { mount } from "@vue/test-utils";
import { BoardMenuActionDelete } from "@ui-board";
import { nextTick } from "vue";
import { ComponentProps } from "vue-component-type-helpers";
import { VBtn } from "vuetify/lib/components/index.mjs";
import MediaBoardExternalToolElementMenu from "./MediaBoardExternalToolElementMenu.vue";
import MediaBoardDeletedElement from "./MediaBoardExternalToolDeletedElement.vue";

describe("MediaBoardDeletedElement", () => {
const getWrapper = (
props: ComponentProps<typeof MediaBoardDeletedElement>,
stubThreeDotMenu = true
) => {
const wrapper = mount(MediaBoardDeletedElement, {
global: {
plugins: [createTestingVuetify(), createTestingI18n()],
},
props,
stubs: {
MediaBoardExternalToolElementMenu: stubThreeDotMenu,
},
});

return {
wrapper,
};
};

describe("three dot menu", () => {
describe("when clicking on the the three dot menu", () => {
const setupOverlayDiv = () => {
const overlayDiv = document.createElement("div");
overlayDiv.className = "v-overlay-container";
document.body.append();
};

const setup = () => {
const deletedElement = deletedElementResponseFactory.build();

const { wrapper } = getWrapper(
{
element: deletedElement,
},
false
);

setupOverlayDiv();

return {
wrapper,
};
};

afterEach(() => {
document.body.innerHTML = "";
});

it("should show the delete action", async () => {
const { wrapper } = setup();

const menuBtn = wrapper
.getComponent(MediaBoardExternalToolElementMenu)
.getComponent(VBtn);
await menuBtn.trigger("click");

const deleteAction = wrapper.findComponent(BoardMenuActionDelete);

expect(deleteAction.exists()).toEqual(true);
});
});

describe("when deleting the element from the menu", () => {
const setup = () => {
const deletedElement = deletedElementResponseFactory.build();

const { wrapper } = getWrapper({
element: deletedElement,
});

return {
wrapper,
deletedElement,
};
};

it("should emit a delete event", async () => {
const { wrapper, deletedElement } = setup();

const menu = wrapper.getComponent(MediaBoardExternalToolElementMenu);
menu.vm.$emit("delete:element");
await nextTick();

expect(wrapper.emitted("delete:element")).toEqual([
[deletedElement.id],
]);
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<template>
<MediaBoardElementDisplay :element="elementDisplayData" :isUnavailable="true">
<template #imageOverlay>
<div class="d-flex ga-1 flex-column pa-3">
<WarningChip data-testid="warning-chip-no-longer-available">
{{ $t("common.medium.chip.noLongerAvailable") }}
</WarningChip>
</div>
</template>
<template #menu>
<MediaBoardExternalToolElementMenu @delete:element="onDelete" />
</template>
</MediaBoardElementDisplay>
</template>

<script setup lang="ts">
import { DeletedElementResponse } from "@/serverApi/v3";
import { WarningChip } from "@ui-chip";
import { computed, PropType, Ref } from "vue";
import { MediaElementDisplay } from "./data";
import MediaBoardElementDisplay from "./MediaBoardElementDisplay.vue";
import MediaBoardExternalToolElementMenu from "./MediaBoardExternalToolElementMenu.vue";
const props = defineProps({
element: {
type: Object as PropType<DeletedElementResponse>,
required: true,
},
});
const emit = defineEmits<{
(e: "delete:element", elementId: string): void;
}>();
const onDelete = async () => {
emit("delete:element", props.element.id);
};
const elementDisplayData: Ref<MediaElementDisplay> = computed(() => {
return {
title: props.element?.content.title,
description: props.element?.content.description,
thumbnail: undefined,
};
});
</script>
Loading

0 comments on commit 6e0ed21

Please sign in to comment.