Skip to content

Commit

Permalink
N21-2058 Add manual VIDIS license sync (#3514)
Browse files Browse the repository at this point in the history
  • Loading branch information
MarvinOehlerkingCap authored Jan 31, 2025
1 parent ee7aec6 commit f0e5b79
Show file tree
Hide file tree
Showing 14 changed files with 432 additions and 12 deletions.
1 change: 1 addition & 0 deletions config/webpack/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ module.exports = {
"src/modules/data/provisioning-options"
),
"@data-room": getDir("src/modules/data/room"),
"@data-license": getDir("src/modules/data/license"),
"@feature-board-file-element": getDir(
"src/modules/feature/board-file-element"
),
Expand Down
51 changes: 50 additions & 1 deletion src/components/administration/ExternalToolSection.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import {
NOTIFIER_MODULE_KEY,
SCHOOL_EXTERNAL_TOOLS_MODULE_KEY,
} from "@/utils/inject";
import { createModuleMocks } from "@@/tests/test-utils/mock-store-module";
import {
envsFactory,
meResponseFactory,
schoolExternalToolFactory,
schoolExternalToolMetadataFactory,
schoolToolConfigurationStatusFactory,
} from "@@/tests/test-utils/factory";
import { createModuleMocks } from "@@/tests/test-utils/mock-store-module";
import {
createTestingI18n,
createTestingVuetify,
Expand All @@ -30,6 +30,7 @@ import { nextTick, ref } from "vue";
import { Router, useRouter } from "vue-router";
import { VCardText } from "vuetify/lib/components/index.mjs";
import ExternalToolSection from "./ExternalToolSection.vue";
import VidisMediaSyncSection from "./VidisMediaSyncSection.vue";

jest.mock("@data-external-tool");

Expand Down Expand Up @@ -804,4 +805,52 @@ describe("ExternalToolSection", () => {
});
});
});

describe("VIDIS section", () => {
describe("when VIDIS is enabled", () => {
const setup = () => {
const { wrapper } = getWrapper(
{},
{
FEATURE_VIDIS_MEDIA_ACTIVATIONS_ENABLED: true,
}
);

return {
wrapper,
};
};

it("should display the VIDIS section", () => {
const { wrapper } = setup();

const vidisSection = wrapper.findComponent(VidisMediaSyncSection);

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

describe("when VIDIS is disabled", () => {
const setup = () => {
const { wrapper } = getWrapper(
{},
{
FEATURE_VIDIS_MEDIA_ACTIVATIONS_ENABLED: false,
}
);

return {
wrapper,
};
};

it("should not display the VIDIS section", () => {
const { wrapper } = setup();

const vidisSection = wrapper.findComponent(VidisMediaSyncSection);

expect(vidisSection.exists()).toEqual(false);
});
});
});
});
31 changes: 20 additions & 11 deletions src/components/administration/ExternalToolSection.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div>
<div class="mb-4">
<p class="mb-6">
{{ t("components.administration.externalToolsSection.info") }}
</p>
Expand Down Expand Up @@ -48,15 +48,17 @@
/>
</template>
</v-data-table>
<v-btn
class="mt-8 mb-4 button-save float-right"
color="primary"
variant="flat"
data-testid="add-external-tool-button"
:to="{ name: 'administration-tool-config-overview' }"
>
{{ t("components.administration.externalToolsSection.action.add") }}
</v-btn>
<div class="d-flex mt-8" data-testid="external-tool-section-table-actions">
<VSpacer />
<VBtn
color="primary"
variant="flat"
data-testid="add-external-tool-button"
:to="{ name: 'administration-tool-config-overview' }"
>
{{ t("components.administration.externalToolsSection.action.add") }}
</VBtn>
</div>

<v-dialog
v-if="metadata"
Expand Down Expand Up @@ -139,21 +141,23 @@
</v-card>
</v-dialog>
</div>
<VidisMediaSyncSection v-if="isVidisEnabled" />
</template>

<script setup lang="ts">
import { ToolApiAxiosParamCreator } from "@/serverApi/v3";
import { RequestArgs } from "@/serverApi/v3/base";
import AuthModule from "@/store/auth";
import EnvConfigModule from "@/store/env-config";
import NotifierModule from "@/store/notifier";
import SchoolExternalToolsModule from "@/store/school-external-tools";
import { DataTableHeader } from "@/store/types/data-table-header";
import {
AUTH_MODULE_KEY,
ENV_CONFIG_MODULE_KEY,
injectStrict,
NOTIFIER_MODULE_KEY,
SCHOOL_EXTERNAL_TOOLS_MODULE_KEY,
ENV_CONFIG_MODULE_KEY,
} from "@/utils/inject";
import { useSchoolExternalToolUsage } from "@data-external-tool";
import { mdiAlert, mdiCheckCircle } from "@icons/material";
Expand All @@ -163,6 +167,7 @@ import { useRouter } from "vue-router";
import { useExternalToolsSectionUtils } from "./external-tool-section-utils.composable";
import ExternalToolToolbar from "./ExternalToolToolbar.vue";
import { SchoolExternalToolItem } from "./school-external-tool-item";
import VidisMediaSyncSection from "./VidisMediaSyncSection.vue";
const schoolExternalToolsModule: SchoolExternalToolsModule = injectStrict(
SCHOOL_EXTERNAL_TOOLS_MODULE_KEY
Expand Down Expand Up @@ -266,6 +271,10 @@ const isMediaBoardUsageVisible: ComputedRef<boolean> = computed(() => {
envConfigModule.getEnv.FEATURE_MEDIA_SHELF_ENABLED;
return isVisible;
});
const isVidisEnabled: ComputedRef<boolean> = computed(() => {
return envConfigModule.getEnv.FEATURE_VIDIS_MEDIA_ACTIVATIONS_ENABLED;
});
</script>

<style lang="scss" scoped>
Expand Down
107 changes: 107 additions & 0 deletions src/components/administration/VidisMediaSyncSection.unit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import NotifierModule from "@/store/notifier";
import { NOTIFIER_MODULE_KEY } from "@/utils/inject";
import { createModuleMocks } from "@@/tests/test-utils/mock-store-module";
import {
createTestingI18n,
createTestingVuetify,
} from "@@/tests/test-utils/setup";
import { useSchoolLicenseApi } from "@data-license";
import { createMock, DeepMocked } from "@golevelup/ts-jest";
import { mount } from "@vue/test-utils";
import VidisMediaSyncSection from "./VidisMediaSyncSection.vue";

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

describe("VidisMediaSyncSection", () => {
let useSchoolLicenseApiMock: DeepMocked<
ReturnType<typeof useSchoolLicenseApi>
>;

const notifierModule: jest.Mocked<NotifierModule> =
createModuleMocks(NotifierModule);

const getWrapper = () => {
const wrapper = mount(VidisMediaSyncSection, {
global: {
plugins: [createTestingVuetify(), createTestingI18n()],
provide: {
[NOTIFIER_MODULE_KEY.valueOf()]: notifierModule,
},
},
});

return {
wrapper,
};
};

beforeEach(() => {
useSchoolLicenseApiMock =
createMock<ReturnType<typeof useSchoolLicenseApi>>();

jest.mocked(useSchoolLicenseApi).mockReturnValue(useSchoolLicenseApiMock);
});

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

describe("Sync button", () => {
describe("when the request is successful", () => {
const setup = () => {
const { wrapper } = getWrapper();

return {
wrapper,
};
};

it("should call the api", async () => {
const { wrapper } = setup();

const button = wrapper.find('[data-testid="sync-vidis-media-button"]');
await button.trigger("click");

expect(useSchoolLicenseApiMock.updateSchoolLicenses).toHaveBeenCalled();
});

it("should show a success notification", async () => {
const { wrapper } = setup();

const button = wrapper.find('[data-testid="sync-vidis-media-button"]');
await button.trigger("click");

expect(notifierModule.show).toHaveBeenCalledWith({
status: "success",
text: "components.administration.externalToolsSection.vidis.notification.success",
});
});
});

describe("when the request fails", () => {
const setup = () => {
const { wrapper } = getWrapper();

useSchoolLicenseApiMock.updateSchoolLicenses.mockRejectedValueOnce(
new Error()
);

return {
wrapper,
};
};

it("should show a failure notification", async () => {
const { wrapper } = setup();

const button = wrapper.find('[data-testid="sync-vidis-media-button"]');
await button.trigger("click");

expect(notifierModule.show).toHaveBeenCalledWith({
status: "error",
text: "common.notification.error",
});
});
});
});
});
60 changes: 60 additions & 0 deletions src/components/administration/VidisMediaSyncSection.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<template>
<div class="mb-4">
<h5>
{{ $t("components.administration.externalToolsSection.vidis.title") }}
</h5>
<p>
{{
$t("components.administration.externalToolsSection.vidis.description")
}}
</p>
<div class="d-flex mt-8" data-testid="external-tool-section-table-actions">
<VSpacer />
<VBtn
color="primary"
variant="flat"
data-testid="sync-vidis-media-button"
:loading="isLoading"
@click="updateVidisLicenses"
>
{{ $t("components.administration.externalToolsSection.action.sync") }}
</VBtn>
</div>
</div>
</template>

<script setup lang="ts">
import NotifierModule from "@/store/notifier";
import { injectStrict, NOTIFIER_MODULE_KEY } from "@/utils/inject";
import { useSchoolLicenseApi } from "@data-license";
import { ref } from "vue";
import { useI18n } from "vue-i18n";
const notifierModule: NotifierModule = injectStrict(NOTIFIER_MODULE_KEY);
const { t } = useI18n();
const { updateSchoolLicenses } = useSchoolLicenseApi();
const isLoading = ref(false);
const updateVidisLicenses = async () => {
isLoading.value = true;
try {
await updateSchoolLicenses();
notifierModule.show({
status: "success",
text: t(
"components.administration.externalToolsSection.vidis.notification.success"
),
});
} catch (e) {

Check warning on line 51 in src/components/administration/VidisMediaSyncSection.vue

View workflow job for this annotation

GitHub Actions / lint

'e' is defined but never used
notifierModule.show({
status: "error",
text: t("common.notification.error"),
});
}
isLoading.value = false;
};
</script>
7 changes: 7 additions & 0 deletions src/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,12 +305,19 @@ export default {
"Tool bearbeiten",
"components.administration.externalToolsSection.action.showDatasheet":
"Datenblatt anzeigen",
"components.administration.externalToolsSection.action.sync":
"Verfügbarkeit aktualisieren",
"components.administration.externalToolsSection.description.firstParagraph":
"Die schulspezifischen Parameter für das externe Tool werden hier konfiguriert. Nach dem Speichern der Konfiguration ist das Tool innerhalb der Schule verfügbar.",
"components.administration.externalToolsSection.description.secondParagraph":
"Weitere Informationen sind in unserem {0} zu finden.",
"components.administration.externalToolsSection.description.secondParagraph.link":
"Hilfebereich zu externen Tools",
"components.administration.externalToolsSection.vidis.title": "VIDIS-Medien",
"components.administration.externalToolsSection.vidis.description":
"Die Verfügbarkeit der VIDIS-Medien wird automatisch aktualisiert. Zusätzlich kann die Verfügbarkeit der Medien hier manuell aktualisiert werden, z.B. um kürzlich aktivierte Medien direkt in der Schulcloud nutzen zu können.",
"components.administration.externalToolsSection.vidis.notification.success":
"VIDIS-Medien erfolgreich aktualisiert",
"components.administration.externalToolsSection.dialog.content.metadata.error":
"Die Verwendung des Tools konnte nicht ermittelt werden.",
"components.administration.externalToolsSection.dialog.content.header.firstParagraph":
Expand Down
7 changes: 7 additions & 0 deletions src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,12 +303,19 @@ export default {
"components.administration.externalToolsSection.action.edit": "Edit Tool",
"components.administration.externalToolsSection.action.showDatasheet":
"View data sheet",
"components.administration.externalToolsSection.action.sync":
"Update availability",
"components.administration.externalToolsSection.description.firstParagraph":
"The school-specific parameters for the external tool are configured here. After saving the configuration, the tool will be available within the school.",
"components.administration.externalToolsSection.description.secondParagraph":
"Further information is available in our {0}.",
"components.administration.externalToolsSection.description.secondParagraph.link":
"Help section on external tools",
"components.administration.externalToolsSection.vidis.title": "VIDIS-Media",
"components.administration.externalToolsSection.vidis.description":
"The availability of VIDIS media is updated automatically. In addition, the availability of the media can be updated manually here, e.g. to be able to use recently activated media directly in the school cloud.",
"components.administration.externalToolsSection.vidis.notification.success":
"VIDIS media updated successfully",
"components.administration.externalToolsSection.dialog.content.metadata.error":
"The usage of the tool could not be determined.",
"components.administration.externalToolsSection.dialog.content.header.firstParagraph":
Expand Down
7 changes: 7 additions & 0 deletions src/locales/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,12 +307,19 @@ export default {
"Editar herramienta",
"components.administration.externalToolsSection.action.showDatasheet":
"Ver hoja de datos",
"components.administration.externalToolsSection.action.sync":
"Disponibilidad de actualización",
"components.administration.externalToolsSection.description.firstParagraph":
"Los parámetros específicos de la escuela para la herramienta externa se configuran aquí. Después de guardar la configuración, la herramienta estará disponible dentro de la escuela.",
"components.administration.externalToolsSection.description.secondParagraph":
"Más información está disponible en nuestro {0}.",
"components.administration.externalToolsSection.description.secondParagraph.link":
"Sección de ayuda sobre herramientas externas",
"components.administration.externalToolsSection.vidis.title": "Medios VIDIS",
"components.administration.externalToolsSection.vidis.description":
"La disponibilidad de los medios VIDIS se actualiza automáticamente. Además, aquí se puede actualizar manualmente la disponibilidad de los medios, por ejemplo para poder utilizar los medios activados recientemente directamente en la nube de la escuela.",
"components.administration.externalToolsSection.vidis.notification.success":
"Medios VIDIS actualizados exitosamente",
"components.administration.externalToolsSection.dialog.content.metadata.error":
"No se pudo determinar el uso de la herramienta.",
"components.administration.externalToolsSection.dialog.content.header.firstParagraph":
Expand Down
Loading

0 comments on commit f0e5b79

Please sign in to comment.