{"version":3,"file":"app-124dd196.f584a1446b2fc034d810.bundle.js","mappings":"AAGA","sources":["webpack://lernplattform-admin-frontend/./src/resources/pages/learning-journey-edit-page/learning-journey-edit-page.html","webpack://lernplattform-admin-frontend/./src/resources/pages/learning-journeys-page/learning-journeys-page.html","webpack://lernplattform-admin-frontend/./src/resources/pages/lecturer-events-page/lecturer-events-page.html","webpack://lernplattform-admin-frontend/./src/resources/pages/link-accounts-page/link-accounts-page.html","webpack://lernplattform-admin-frontend/./src/resources/pages/login-page/login-page-external.html","webpack://lernplattform-admin-frontend/./src/resources/pages/login-page/login-page.html","webpack://lernplattform-admin-frontend/./src/resources/pages/logs-page/logs-page.html","webpack://lernplattform-admin-frontend/./src/resources/pages/learning-journey-edit-page/learning-journey-edit-page.ts","webpack://lernplattform-admin-frontend/./src/resources/pages/learning-journeys-page/learning-journeys-page.ts","webpack://lernplattform-admin-frontend/./src/resources/pages/lecturer-events-page/lecturer-events-page.ts","webpack://lernplattform-admin-frontend/./src/resources/pages/link-accounts-page/link-accounts-page.ts","webpack://lernplattform-admin-frontend/./src/resources/pages/login-page/login-page-external.ts","webpack://lernplattform-admin-frontend/./src/resources/pages/login-page/login-page.ts","webpack://lernplattform-admin-frontend/./src/resources/pages/logs-page/logs-page.ts"],"sourcesContent":["// Module\nvar code = \"<template> <button-standard click.delegate=\\\"navigateBack()\\\" t=\\\"[btnText]globals.back\\\" icon-name=\\\"System/Tabler/Chevron-Left\\\" btn-size=\\\"btn-sm\\\" btn-color=\\\"secondary\\\"></button-standard> <div class=\\\"page-header\\\"> <h1 class=\\\"page-title\\\">${ learningJourney.title }</h1> <div class=\\\"ml-auto\\\"> <button-standard click.delegate=\\\"handleDuplicateLearningJourneyClick()\\\" class=\\\"mb-2 d-inline-block\\\" t=\\\"[btnText]pages.learning-journey-edit.duplicateLearningJourney\\\" btn-color=\\\"secondary\\\"></button-standard> </div> </div> <navigation-tabs tabs.to-view=\\\"navigationTabs\\\" class=\\\"mb-6\\\"></navigation-tabs> <template if.to-view=\\\"activeTab === ENavigationTab.DETAILS\\\"> <form submit.trigger=\\\"updateLearningJourneyTitle()\\\" class=\\\"card\\\"> <div class=\\\"card-header\\\"> <h2 class=\\\"card-title\\\" t=\\\"globals.basics\\\"></h2> </div> <div class=\\\"card-body\\\"> <div class=\\\"row\\\"> <div class=\\\"form-group col-12\\\"> <div class=\\\"form-group\\\"> <label class=\\\"form-label\\\" t=\\\"globals.title\\\"></label> <input type=\\\"text\\\" required class=\\\"form-control\\\" value.two-way=\\\"learningJourneyTitle\\\"> </div> </div> </div> </div> <div class=\\\"card-footer text-right\\\"> <button class=\\\"btn btn-primary\\\" disabled.to-view=\\\"learningJourney.title === learningJourneyTitle\\\" type=\\\"submit\\\" t=\\\"globals.save\\\"></button> </div> </form> <div class=\\\"page-header mt-2\\\"> <h3 class=\\\"page-title\\\" t=\\\"pages.learning-journey-edit.structure\\\"></h3> </div> <div class=\\\"row\\\"> <learning-journey-course-structure if.to-view=\\\"learningJourney\\\" class=\\\"col-12\\\" courses.to-view=\\\"learningJourney.courses\\\" learning-journey-add-course.trigger=\\\"onAddCourse()\\\" learning-journey-edit-course.trigger=\\\"onEditCourse($event)\\\" learning-journey-move-course.trigger=\\\"onMoveCourse($event)\\\" learning-journey-remove-course.trigger=\\\"onRemoveCourse($event)\\\"></learning-journey-course-structure> </div> </template> <template if.to-view=\\\"activeTab === ENavigationTab.SKILLS\\\"> <assign-skills-form skills.to-view=\\\"learningJourneySkills\\\" save-clicked.trigger=\\\"onSaveSkills($event)\\\"></assign-skills-form> </template> </template>\";\n// Exports\nexport default code;","// Module\nvar code = \"<template> <div class=\\\"page-header\\\"> <h1 class=\\\"page-title\\\" t=\\\"globals.learningJourneys\\\"></h1> <div class=\\\"ml-auto\\\"> <button-standard click.delegate=\\\"handleCreateLearningJourneyClick()\\\" class=\\\"mb-2 d-inline-block\\\" t=\\\"[btnText]pages.learning-journeys.createLearningJourney\\\" icon-name=\\\"System/Tabler/Plus\\\" btn-color=\\\"primary\\\"></button-standard> </div> </div> <div class=\\\"row row-cards row-deck\\\"> <div class=\\\"col-12\\\"> <custom-table columns.to-view=\\\"tableColumns\\\" extendable.to-view=\\\"true\\\" selectable.to-view=\\\"true\\\" selected.two-way=\\\"selectedLearningJourneys\\\" table-id=\\\"learning-journeys-page\\\" refresh-version.to-view=\\\"tableRefreshVersion\\\" get-shown-entries-data.call=\\\"fetchTableData(limit, offset)\\\"> <button if.to-view=\\\"selectedLearningJourneys.length\\\" click.delegate=\\\"assignCoursesToLearningJourneys()\\\" type=\\\"button\\\" class=\\\"btn btn-outline-primary btn-sm\\\" t=\\\"globals.assignCourses\\\"></button> <button if.to-view=\\\"selectedLearningJourneys.length\\\" click.delegate=\\\"assignStudentsToLearningJourneys()\\\" type=\\\"button\\\" class=\\\"btn btn-outline-primary btn-sm\\\" t=\\\"globals.assignStudents\\\"></button> </custom-table> </div> </div> </template>\";\n// Exports\nexport default code;","// Module\nvar code = \"<template> <div if.to-view=\\\"showEventsTable\\\"> <div class=\\\"page-header\\\"> <h1 class=\\\"page-title\\\" t=\\\"pages.lecturerEvents.title\\\"></h1> </div> <div class=\\\"row row-cards row-deck\\\"> <div class=\\\"col-12\\\"> <lecturer-events-table table-refresh-version.two-way=\\\"tableRefreshVersion\\\" show-filters.to-view=\\\"true\\\" allow-sorting.to-view=\\\"true\\\" filter.two-way=\\\"filter\\\" fetch-table-data-delegate.call=\\\"fetchTableData(limit, offset)\\\"></lecturer-events-table> </div> </div> </div> <div if.to-view=\\\"showNoEventsAlert\\\" class=\\\"alert alert-info\\\"> <span t=\\\"pages.lecturerEvents.youHaveNoAssignedLectures\\\"></span> </div> </template>\";\n// Exports\nexport default code;","// Module\nvar code = \"<template> <div class=\\\"page-header\\\"> <h1 class=\\\"page-title\\\" t=\\\"pages.linkAccounts.title\\\"></h1> </div> <div class=\\\"row row-cards row-deck\\\"> <div class=\\\"card\\\"> <div class=\\\"card-header\\\" t=\\\"pages.linkAccounts.providers\\\"></div> <div class=\\\"list-group list-group-flush list-group-hoverable\\\"> <div if.to-view=\\\"linkedProviders.length\\\" repeat.for=\\\"linked of linkedProviders\\\" class=\\\"list-group-item\\\"> <div class=\\\"row align-items-center\\\"> <div class=\\\"col text-truncate\\\"> <div t=\\\"pages.linkAccounts.providerLinked\\\" t-params.to-view=\\\"{ provider: getProviderDisplayName(linked.provider) }\\\"></div> <div class=\\\"text-muted\\\"><span t=\\\"pages.linkAccounts.linkedOnText\\\"></span> ${ getDateOfLink(linked) }</div> </div> <div class=\\\"col-auto\\\"> <button class=\\\"btn btn-secondary btn-block\\\" disabled.to-view=\\\"!linked.canUnlink\\\" click.delegate=\\\"unlinkProvider(linked)\\\" t=\\\"pages.linkAccounts.unlinkProvider\\\"></button> </div> </div> </div> <div else class=\\\"list-group-item\\\"> <div class=\\\"row align-items-center\\\"> <p class=\\\"text-muted col-12 form-group\\\" t=\\\"pages.linkAccounts.noProvidersLinked\\\"></p> </div> </div> <div if.to-view=\\\"providers.length\\\" repeat.for=\\\"provider of providers\\\" class=\\\"list-group-item\\\"> <div class=\\\"row align-items-center\\\"> <div class=\\\"col text-truncate\\\"> <div>${ getProviderDisplayName(provider) }</div> </div> <div class=\\\"col-auto\\\"> <button class=\\\"btn btn-primary btn-block\\\" click.delegate=\\\"linkProvider(provider)\\\" t=\\\"pages.linkAccounts.linkProvider\\\"></button> </div> </div> </div> <div else class=\\\"list-group-item\\\"> <div class=\\\"row align-items-center\\\"> <p class=\\\"text-muted col-12 form-group\\\" t=\\\"pages.linkAccounts.noProvidersAvailable\\\"></p> </div> </div> </div> </div> </div> </template>\";\n// Exports\nexport default code;","// Module\nvar code = \"<template> <div class=\\\"col-login container text-center\\\"> <h1 class=\\\"h2 mb-3\\\" t=\\\"pages.login.loginInProgress\\\"></h1> <p class=\\\"h4 text-muted font-weight-normal mb-7\\\" t=\\\"globals.redirectShortly\\\"></p> </div> </template>\";\n// Exports\nexport default code;","// Module\nvar code = \"<template> <div class=\\\"text-center mb-6\\\"> <img class=\\\"login__logo-img\\\" src.to-view=\\\"logo\\\"> <span if.to-view=\\\"appName\\\" class=\\\"login__logo header-brand\\\">${appName}</span> </div> <div class=\\\"col-login mx-auto\\\"> <div if.to-view=\\\"errorTk\\\" class=\\\"alert alert-danger\\\" role=\\\"alert\\\" t=\\\"[html]${errorTk}\\\" t-params.to-view=\\\"{\\n          emailLink: `<a class='login__link' href='mailto:${supportEmail}'>${supportEmail}</a>`,\\n          appName: fullAppName\\n         }\\\"></div> <form show.to-view=\\\"!showTfa && !showPasswordReset\\\" class=\\\"card\\\" id=\\\"loginform\\\"> <div class=\\\"card-body p-6\\\"> <h1 class=\\\"login__title text-center\\\" t=\\\"pages.login.title\\\"></h1> <div class=\\\"form-group\\\"> <label for=\\\"email\\\" class=\\\"form-label\\\" t=\\\"pages.login.email.label\\\"></label> <input id=\\\"email\\\" type=\\\"email\\\" tabindex=\\\"1\\\" class=\\\"form-control\\\" value.two-way=\\\"email\\\" t=\\\"[placeholder]pages.login.email.placeholder\\\"> </div> <div class=\\\"form-group\\\"> <div class=\\\"form-label\\\"><label for=\\\"password\\\">${ 'pages.login.password.label' | t }</label> <a href=\\\"javascript:void(0);\\\" class=\\\"float-right small login__link\\\" t=\\\"pages.login.lostPassword\\\" click.delegate=\\\"handleShowPasswordResetClick()\\\"></a> </div> <div class=\\\"input-group\\\"> <input role=\\\"textbox\\\" id=\\\"password\\\" type.to-view=\\\"passwordInputType\\\" tabindex=\\\"2\\\" class=\\\"form-control\\\" value.two-way=\\\"password\\\" t=\\\"[placeholder]pages.login.password.placeholder\\\"> <div class=\\\"input-group-append\\\"> <button-standard click.trigger=\\\"togglePasswordVisibility()\\\" icon-name.to-view=\\\"passwordInputType === 'password' ? 'System/Tabler/Eye' : 'System/Tabler/EyeOff'\\\" btn-color=\\\"secondary\\\"></button-standard> </div> </div> </div> <div class=\\\"form-footer\\\"> <button type=\\\"submit\\\" id=\\\"login\\\" tabindex=\\\"3\\\" class=\\\"btn btn-primary btn-block\\\" t=\\\"pages.login.login\\\" click.delegate=\\\"signIn()\\\"></button> </div> </div> </form> <section if.to-view=\\\"isFrp && !showPasswordReset && !showTfa\\\" class=\\\"text-center login__registration-section\\\"> <h2 class=\\\"login__registration-section-title\\\" t=\\\"pages.login.noAccount\\\"></h2> <button-standard click.delegate=\\\"goToTeacherRegistrationPage()\\\" t=\\\"[btnText]pages.login.registerNow\\\" btn-type=\\\"outline\\\"></button-standard> <img class=\\\"login__registration-section-logo\\\" alt=\\\"\\\" src.to-view=\\\"logoBadge\\\"/> </section> <form show.to-view=\\\"showTfa\\\" class=\\\"card\\\"> <div class=\\\"card-body p-6\\\"> <div class=\\\"form-group\\\"> <label class=\\\"form-label\\\" t=\\\"pages.login.tfa.label\\\"></label> <input type=\\\"text\\\" focus.two-way=\\\"focusTfa\\\" class=\\\"form-control\\\" value.two-way=\\\"tfa\\\" t=\\\"[placeholder]pages.login.tfa.placeholder\\\"> </div> <div class=\\\"form-footer\\\"> <button type=\\\"submit\\\" class=\\\"btn btn-primary btn-block\\\" t=\\\"pages.login.login\\\" click.delegate=\\\"signIn()\\\"></button> </div> <label class=\\\"form-label mt-2 text-center\\\"> <a href=\\\"javascript:void(0);\\\" class=\\\"small login__link\\\" t=\\\"pages.login.cancel\\\" click.delegate=\\\"cancelTfa()\\\"></a> </label> </div> </form> <div show.to-view=\\\"!showTfa && !showPasswordReset && externalLoginConfigurations.length\\\"> <div class=\\\"text-center text-muted\\\" t=\\\"pages.login.externalProviders\\\"></div> <external-login external-login-config.to-view=\\\"externalLoginConfigurations\\\"></external-login> </div> <form show.to-view=\\\"showPasswordReset && showPasswordResetInfo\\\" class=\\\"card\\\"> <div class=\\\"card-body p-6 alert-success\\\" t=\\\"pages.login.passwordReset.sentNotification\\\"> </div> <div class=\\\"card-footer\\\"> <button type=\\\"submit\\\" class=\\\"btn btn-block btn-secondary\\\" t=\\\"globals.back\\\" click.delegate=\\\"handleCancelPasswordResetClick()\\\"></button> </div> </form> <form show.to-view=\\\"showPasswordReset && !showPasswordResetInfo\\\" class=\\\"card\\\"> <div class=\\\"card-body p-6\\\"> <div class=\\\"form-group\\\"> <label class=\\\"form-label\\\" t=\\\"pages.login.passwordReset.label\\\"></label> <input type=\\\"text\\\" focus.two-way=\\\"focusPasswordReset\\\" class=\\\"form-control ${showPasswordResetError ? 'animation--shake is-invalid' : ''}\\\" value.two-way=\\\"resetEmail\\\" t=\\\"[placeholder]pages.login.passwordReset.placeholder\\\"> </div> <div class=\\\"form-footer\\\"> <button type=\\\"submit\\\" class=\\\"btn btn-primary btn-block\\\" t=\\\"pages.login.passwordReset.button\\\" click.delegate=\\\"resetPassword()\\\"></button> </div> <label class=\\\"form-label mt-2 text-center\\\"> <a href=\\\"javascript:void(0);\\\" class=\\\"small login__link\\\" t=\\\"pages.login.cancel\\\" click.delegate=\\\"handleCancelPasswordResetClick()\\\"></a> </label> </div> </form> </div> </template>\";\n// Exports\nexport default code;","// Module\nvar code = \"<template> <div class=\\\"page-header\\\"> <h1 class=\\\"page-title\\\" t=\\\"pages.logs.title\\\"></h1> <div class=\\\"ml-auto\\\"> <filtered-export-widget filter.to-view=\\\"filter\\\" t=\\\"[btn-text]pages.logs.export.button\\\" export-csv.trigger=\\\"exportCsv($event)\\\"></filtered-export-widget> </div> </div> <div class=\\\"row row-cards row-deck\\\"> <div class=\\\"col-12\\\"> <custom-table columns.to-view=\\\"tableColumns\\\" extendable=\\\"true\\\" table-id=\\\"logs-page\\\" get-shown-entries-data.call=\\\"fetchTableData(limit, offset)\\\"></custom-table> </div> </div> </template>\";\n// Exports\nexport default code;","import { autoinject } from 'aurelia-framework';\nimport { Router } from 'aurelia-router';\nimport { ILearningJourneyDto, IMoveCourseInLearningJourneyDto, IUpdateLearningJourneyDto } from 'common/dto/learning-journey/management/learning-journey.management.interface';\nimport { ISkillDto } from 'common/dto/skill/management/skill.management.interface';\nimport { assertNotNullOrUndefined } from 'common/utils/assert';\nimport { CustomDialogService } from '../../../services/CustomDialogService';\nimport { ToastService } from '../../../services/ToastService';\nimport { LearningJourneyManagementApiService } from '../../../services/api/LearningJourneyManagementApiService';\nimport { AssignSkillsFormSaveClickedEvent } from '../../elements/assign-skills-form/assign-skills-form';\nimport { LearningJourneyEditCourseEvent, LearningJourneyMoveCourseEvent, LearningJourneyRemoveCourseEvent } from '../../elements/learning-journey-course-structure/learning-journey-course-structure';\nimport { INavigationTab } from '../../elements/navigation-tabs/navigation-tabs';\nimport { LinkBehavior } from '../../elements/toast-controller/toasts/default-toast/default-toast';\n\ninterface IParams {\n  learningJourneyId?: string;\n  tab?: ENavigationTab;\n}\n\nexport enum ENavigationTab {\n  DETAILS = 'details',\n  SKILLS = 'skills',\n}\n\n@autoinject()\nexport class LearningJourneyEditPage {\n  private learningJourneyId: number | null = null;\n  private learningJourney: ILearningJourneyDto | null = null;\n  private learningJourneyTitle: string = '';\n  private learningJourneySkills: ISkillDto[] = [];\n\n  private activeTab: ENavigationTab = ENavigationTab.DETAILS;\n  private ENavigationTab = ENavigationTab;\n  private navigationTabs: INavigationTab[] = [];\n\n  constructor(\n    private learningJourneyManagementApiService: LearningJourneyManagementApiService,\n    private router: Router,\n    private customDialogService: CustomDialogService,\n    private toastService: ToastService,\n  ) { }\n\n  protected activate(params: IParams): void {\n    this.learningJourneyId = params.learningJourneyId != null ? parseInt(params.learningJourneyId, 10) : null;\n    this.activeTab = params.tab ?? ENavigationTab.DETAILS;\n    this.navigationTabs = [\n      {\n        title: { titleTk: 'globals.details' },\n        active: this.activeTab === ENavigationTab.DETAILS,\n        callback: () => { this.navigateToTab(ENavigationTab.DETAILS); }\n      },\n      {\n        title: { titleTk: 'globals.skills' },\n        active: this.activeTab === ENavigationTab.SKILLS,\n        callback: () => { this.navigateToTab(ENavigationTab.SKILLS); }\n      }\n    ];\n    this.fetchLearningJourney();\n  }\n\n  private async fetchLearningJourney(): Promise<void> {\n    assertNotNullOrUndefined(this.learningJourneyId, 'learningJourneyId cannot be null or undefined');\n    this.learningJourney = await this.learningJourneyManagementApiService.getLearningJourney(this.learningJourneyId);\n    this.learningJourneyTitle = this.learningJourney.title;\n    this.learningJourneySkills = this.learningJourney.skills;\n  }\n\n  private async updateLearningJourneyTitle(): Promise<void> {\n    assertNotNullOrUndefined(this.learningJourneyId, 'learningJourneyId cannot be null or undefined');\n    const data: IUpdateLearningJourneyDto = {\n      title: this.learningJourneyTitle\n    };\n    this.learningJourney = await this.learningJourneyManagementApiService.updateLearningJourney(this.learningJourneyId, data);\n    this.toastService.success('globals.editSuccess');\n  }\n\n  private async handleDuplicateLearningJourneyClick(): Promise<void> {\n    assertNotNullOrUndefined(this.learningJourneyId, 'learningJourneyId cannot be null or undefined');\n    const duplicateId = await this.learningJourneyManagementApiService.duplicateLearningJourney(this.learningJourneyId);\n    this.toastService.success('pages.learning-journey-edit.duplicateSuccess', {}, {\n      textTk: 'pages.learning-journey-edit.duplicateLink',\n      linkHref: this.router.generate('learning-journey/id/tab', { learningJourneyId: duplicateId, tab: ENavigationTab.DETAILS }),\n      behavior: LinkBehavior.Navigate,\n    });\n  }\n\n  private navigateToTab(tab: ENavigationTab): void {\n    this.router.navigateToRoute('learning-journey/id/tab', { tab, learningJourneyId: this.learningJourneyId });\n  }\n\n  private navigateBack(): void {\n    this.router.navigateToRoute('learning-journeys');\n  }\n\n  private async onRemoveCourse(event: LearningJourneyRemoveCourseEvent): Promise<void> {\n    assertNotNullOrUndefined(this.learningJourney, 'learningJourney cannot be null or undefined');\n    await this.learningJourneyManagementApiService.removeCourseFromLearningJourney(event.detail.learningJourneyCourseId);\n    await this.fetchLearningJourney();\n    this.toastService.success('globals.editSuccess');\n  }\n\n  private async onAddCourse(): Promise<void> {\n    assertNotNullOrUndefined(this.learningJourney, 'learningJourney cannot be null or undefined');\n    if(await this.customDialogService.showAssignCoursesToLearningJourneysDialog({ learningJourneys: [this.learningJourney] })) {\n      await this.fetchLearningJourney();\n    }\n  }\n\n  private async onEditCourse(event: LearningJourneyEditCourseEvent): Promise<void> {\n    assertNotNullOrUndefined(this.learningJourney, 'learningJourney cannot be null or undefined');\n    const result = await this.customDialogService.showEditLearningJourneyCourseDialog({ learningJourney: this.learningJourney, learningJourneyCourse: event.detail.course });\n    if(!result) return;\n    await this.learningJourneyManagementApiService.updateCourseOfLearningJourney(event.detail.course.learningJourneyCourseId, result);\n    await this.fetchLearningJourney();\n    this.toastService.success('globals.editSuccess');\n  }\n\n  private async onSaveSkills(event: AssignSkillsFormSaveClickedEvent): Promise<void> {\n    assertNotNullOrUndefined(this.learningJourney, 'learningJourney cannot be null or undefined');\n    this.learningJourney = await this.learningJourneyManagementApiService.updateLearningJourneySkills(this.learningJourney.id, event.detail.selectedSkillIds);\n    this.learningJourneySkills = this.learningJourney.skills;\n    this.toastService.success('globals.editSuccess');\n  }\n\n  private async onMoveCourse(event: LearningJourneyMoveCourseEvent): Promise<void> {\n    const dto: IMoveCourseInLearningJourneyDto = {\n      order: event.detail.targetOrder,\n    };\n\n    await this.learningJourneyManagementApiService.moveCourseInLearningJourney(event.detail.learningJourneyCourseId, dto);\n    this.toastService.success('globals.editSuccess');\n    await this.fetchLearningJourney();\n  }\n}\n","import { autoinject } from 'aurelia-framework';\nimport { Router } from 'aurelia-router';\nimport { IFilterDto } from 'common/dto/filter/filter.interface';\nimport { ILearningJourneyDto } from 'common/dto/learning-journey/management/learning-journey.management.interface';\nimport { CustomDialogService } from '../../../services/CustomDialogService';\nimport { ToastService } from '../../../services/ToastService';\nimport { LearningJourneyManagementApiService } from '../../../services/api/LearningJourneyManagementApiService';\nimport { ActionsCell } from '../../elements/custom-table/actions-cell/actions-cell';\nimport { CustomTableCell } from '../../elements/custom-table/custom-table-cell/custom-table-cell';\nimport { createPrepareServersideSortingFunction, prepareServersideFiltering } from '../../elements/custom-table/custom-table-helpers';\nimport { IColumnDefinition } from '../../elements/custom-table/custom-table-interfaces';\nimport { ENavigationTab } from '../learning-journey-edit-page/learning-journey-edit-page';\n\n@autoinject()\nexport class LearningJourneysPage {\n  private tableRefreshVersion: number = 0;\n  private selectedLearningJourneys: ILearningJourneyDto[] = [];\n  private filter: IFilterDto<ILearningJourneyDto> = {\n    offset: 0,\n    limit: 10,\n    order: [],\n    filter: []\n  };\n\n  private tableColumns: Array<IColumnDefinition<CustomTableCell<ILearningJourneyDto> | ActionsCell<ILearningJourneyDto>>> = [\n    {\n      id: 'title',\n      nameTk: 'globals.title',\n      cellViewModel: CustomTableCell,\n      cellOptions: {\n        transformer: lJ => lJ.title,\n        callback: lJ => { this.navigateToLearningJourney(lJ); },\n        clickable: () => true\n      },\n      prepareSorting: createPrepareServersideSortingFunction(() => this.filter, 'title'),\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: lJ => prepareServersideFiltering(this.filter, 'title', lJ),\n      },\n    },\n    {\n      id: 'course',\n      nameTk: 'globals.courses',\n      cellViewModel: CustomTableCell,\n      cellOptions: {\n        transformer: lJ => lJ.courses.map(course => course.title).join(', ')\n      },\n      wrap: true\n    },\n    {\n      id: 'actions',\n      nameTk: '',\n      cellViewModel: ActionsCell,\n      shrink: true,\n      cellOptions: {\n        entries: [\n          {\n            labelTk: 'globals.edit',\n            icon: 'fe-edit',\n            clickCallback: lJ => { this.navigateToLearningJourney(lJ); }\n          },\n          {\n            labelTk: 'globals.delete',\n            icon: 'fe-delete',\n            additionalClasses: 'text-danger',\n            clickCallback: lJ => { this.handleDeleteLearningJourneyClick(lJ); },\n          },\n        ]\n      }\n    }\n  ];\n\n  constructor(\n    private learningJourneyManagementApiService: LearningJourneyManagementApiService,\n    private customDialogService: CustomDialogService,\n    private toastService: ToastService,\n    private router: Router\n  ) { }\n\n  private async fetchTableData(limit: number, offset: number): Promise<{ total: number; data: ILearningJourneyDto[] }> {\n    this.filter.limit = limit;\n    this.filter.offset = offset;\n\n    const response = await this.learningJourneyManagementApiService.getLearningJourneys(this.filter);\n\n    return {\n      data: response.rows,\n      total: response.count,\n    };\n  }\n\n  private async handleCreateLearningJourneyClick(): Promise<void> {\n    const result = await this.customDialogService.showCreateLearningJourneyDialog();\n    if(!result) return;\n    const newLearningJourney = await this.learningJourneyManagementApiService.createLearningJourney(result);\n    this.toastService.success('pages.learning-journeys.saveSuccess');\n    this.navigateToLearningJourney(newLearningJourney);\n  }\n\n  private async assignCoursesToLearningJourneys(): Promise<void> {\n    if(await this.customDialogService.showAssignCoursesToLearningJourneysDialog({ learningJourneys: this.selectedLearningJourneys })) {\n      this.tableRefreshVersion++;\n    }\n  }\n\n  private async assignStudentsToLearningJourneys(): Promise<void> {\n    if(await this.customDialogService.showAssignStudentsToLearningJourneysDialog({ learningJourneys: this.selectedLearningJourneys })) {\n      this.tableRefreshVersion++;\n    }\n  }\n\n  private navigateToLearningJourney(learningJourney: ILearningJourneyDto): void {\n    this.router.navigateToRoute('learning-journey/id/tab', { learningJourneyId: learningJourney.id, tab: ENavigationTab.DETAILS });\n  }\n\n  private async handleDeleteLearningJourneyClick(learningJourney: ILearningJourneyDto): Promise<void> {\n    const confirmed = await this.customDialogService?.confirmAction({\n      icon: { name: 'alert-triangle', color: 'var(--warning)' },\n      titleTk: 'pages.learning-journeys.deleteWarningTitle',\n      textTk: 'pages.learning-journeys.deleteWarningText',\n      confirmTk: 'globals.ok',\n    });\n    if(!confirmed) return;\n    await this.learningJourneyManagementApiService.deleteLearningJourney(learningJourney.id);\n    this.tableRefreshVersion++;\n  }\n}\n","import { autoinject, computedFrom } from 'aurelia-framework';\nimport { connectTo } from 'aurelia-store';\nimport { ColumnSortDirection, FilterOperationType } from 'common/dto/filter/filter.enum';\nimport { IFilterDto } from 'common/dto/filter/filter.interface';\nimport { IEventDto } from 'common/dto/tenant/event/tenant.event.interface';\nimport { pluck } from 'rxjs/operators';\nimport { EventsApiService } from '../../../services/api/EventsApiService';\nimport { VirtualFilterField } from '../../elements/custom-table/custom-table-helpers';\n\n@connectTo({\n  selector: {\n    tenantId: store => store.state.pipe(pluck('currentRole', 'tenantId')),\n    userId: store => store.state.pipe(pluck('user', 'id'))\n  }\n})\n@autoinject\nexport class LecturerEventsPage {\n  private tenantId!: number;\n  private userId!: number;\n\n  private tableRefreshVersion: number = 0;\n\n  private hasEvents: boolean | null = null;\n\n  private filter: IFilterDto<IEventDto<string>> = {\n    offset: 0,\n    limit: 10,\n    order: [{\n      field: 'plannedDateFrom',\n      dir: ColumnSortDirection.ASC,\n    }],\n    filter: [\n    ]\n  };\n\n  @computedFrom('hasEvents')\n  private get showEventsTable(): boolean {\n    return this.hasEvents === true;\n  }\n\n  @computedFrom('hasEvents')\n  private get showNoEventsAlert(): boolean {\n    return this.hasEvents === false;\n  }\n\n  constructor(private eventsApi: EventsApiService) { }\n\n  private tenantIdChanged(newValue?: number, oldValue?: number): void {\n    if(newValue && newValue !== oldValue) {\n      this.evaluateHasEvents(newValue);\n    }\n  }\n\n  private userIdChanged(newValue?: number, oldValue?: number): void {\n    if(newValue && newValue !== oldValue) {\n      this.filter.filter = this.filter.filter?.filter(filter => filter.field !== 'lecturerId' as VirtualFilterField);\n      this.filter.filter?.push({\n        field: 'lecturerId' as VirtualFilterField,\n        type: FilterOperationType.Eq,\n        value: newValue\n      });\n      this.evaluateHasEvents(this.tenantId);\n    }\n  }\n\n  private async evaluateHasEvents(tenantId?: number): Promise<void> {\n    if(tenantId && this.filter.filter?.find(filter => filter.field === 'lecturerId' as VirtualFilterField)) {\n      this.hasEvents = (await this.eventsApi.getEvents(tenantId, { ...this.filter, limit: 1 })).rows.length > 0;\n    }\n  }\n\n  private async fetchTableData(limit: number, offset: number): Promise<{ total: number; data: Array<IEventDto<string>> }> {\n    this.filter.limit = limit;\n    this.filter.offset = offset;\n    const results = await this.eventsApi.getEvents(this.tenantId, this.filter);\n    return { data: results.rows, total: results.count };\n  }\n}\n","import { autoinject } from 'aurelia-framework';\nimport { ILinkedExternalLoginProvider } from 'common/dto/auth/provider/external.provider.interface';\nimport { LoginProvider } from 'common/enum/auth.enum';\nimport { AppUtils } from 'common/utils/AppUtils';\nimport { AuthApiService } from '../../../services/api/AuthApiService';\nimport { DateService } from '../../../services/DateService';\nimport { ToastService } from '../../../services/ToastService';\n\n@autoinject()\nexport class LinkAccountsPage {\n  private providers: LoginProvider[] = [];\n  private linkedProviders: ILinkedExternalLoginProvider[] = [];\n\n  constructor(\n    private authApiService: AuthApiService,\n    private dateService: DateService,\n    private toastService: ToastService\n  ) { }\n\n  protected activate(): void {\n    this.authApiService.storeCsrfTokenIfAvailable();\n    this.updateProviders();\n  }\n\n  private async updateProviders(): Promise<void> {\n    const availableProviders = await this.authApiService.getExternalProviders();\n    this.linkedProviders = await this.authApiService.getLinkedProviders();\n    this.providers = availableProviders.filter(provider => !this.linkedProviders.some(linkedProvider => linkedProvider.provider === provider));\n  }\n\n  private async linkProvider(provider: LoginProvider): Promise<void> {\n    const url = await this.authApiService.getAuthUrl(provider, true);\n    window.location.href = url;\n  }\n\n  private async unlinkProvider(provider: ILinkedExternalLoginProvider): Promise<void> {\n    await this.authApiService.unlinkProvider(provider.id);\n    await this.updateProviders();\n    this.toastService.success('pages.linkAccounts.unlinkSuccess');\n  }\n\n  private getProviderDisplayName(provider: LoginProvider): string {\n    return AppUtils.getProviderDisplayName(provider);\n  }\n\n  private getDateOfLink(provider: ILinkedExternalLoginProvider): string {\n    return this.dateService.formatDate(provider.createdAt);\n  }\n}\n","import { autoinject } from 'aurelia-framework';\nimport { Router } from 'aurelia-router';\nimport { Store } from 'aurelia-store';\nimport { LogUtils } from 'common/utils/LogUtils';\nimport { AuthApiService } from 'services/api/AuthApiService';\nimport { IState } from 'store/state';\n\n@autoinject\nexport class LoginPageExternal {\n  constructor(private authApiService: AuthApiService, private store: Store<IState>, private router: Router) {\n  }\n\n  protected async activate(params: { token?: string; state?: string; error?: string }): Promise<void> {\n    try {\n      if(params.error != null && params.error !== '') {\n        throw new Error(`AuthenticationError: ${params.error}`);\n      }\n      if(params.token != null) {\n        await this.authApiService.signInViaOneTimeBearer(params.token, params.state!);\n      } else {\n        await this.authApiService.finalizeLogin();\n      }\n      this.router.navigateToRoute('home');\n    } catch(e) {\n      LogUtils.exception(e);\n      this.router.navigateToRoute('login', { error: e.message });\n    }\n  }\n}\n","import { autoinject } from 'aurelia-framework';\nimport { Router } from 'aurelia-router';\nimport { IExternalLoginConfiguration } from 'common/aurelia-components/external-login/external-login';\nimport { imageNameToString } from 'common/aurelia-components/images';\nimport { LoginProvider } from 'common/enum/auth.enum';\nimport { ErrorType } from 'common/enum/errortype.enum';\nimport { Config } from 'common/fe-config/config';\nimport { AppUtils as CommonAppUtils } from 'common/utils/AppUtils';\nimport { LogUtils } from 'common/utils/LogUtils';\nimport { StringUtils } from 'common/utils/StringUtils';\nimport { CustomDialogService } from '../../../services/CustomDialogService';\nimport { AuthApiService, AuthError } from '../../../services/api/AuthApiService';\nimport { AppUtils } from '../../../utils/AppUtils';\n\n@autoinject()\nexport class LoginPage {\n  private email = '';\n  private password = '';\n\n  private showTfa = false;\n  private focusTfa = false;\n  private tfa = '';\n\n  private showPasswordReset = false;\n  private focusPasswordReset = false;\n  private resetEmail = '';\n  private showPasswordResetInfo = false;\n  private showPasswordResetError = false;\n  private passwordInputType: 'password' | 'text' = 'password';\n\n  private errorTk = '';\n  private isFrp = CommonAppUtils.isFrp;\n  private logo = AppUtils.getLogo(true);\n  private logoBadge = imageNameToString.OEJRKBadge;\n\n  private fullAppName = CommonAppUtils.getAppName();\n  private appName = CommonAppUtils.getAppName(true);\n  private supportEmail = CommonAppUtils.getSupportEmail();\n  private externalLoginConfigurations: IExternalLoginConfiguration[] = [];\n\n  constructor(\n    private router: Router,\n    private authApiService: AuthApiService,\n    private customDialogService: CustomDialogService,\n  ) { }\n\n  protected activate(params: { error?: string }): void {\n    if(params.error) {\n      this.displayErrorMessage(params.error);\n      this.router.navigateToRoute('login');\n    }\n    this.updateExternalLoginProviders();\n  }\n\n  private async signIn(): Promise<void> {\n    this.errorTk = '';\n    try {\n      const loginSuccess = await this.authApiService.login(this.email, this.password, this.tfa);\n      if(loginSuccess) {\n        const { ref } = this.router.currentInstruction.queryParams;\n        this.router.navigate(ref || 'home');\n      } else {\n        this.errorTk = 'pages.login.errors.generic';\n      }\n    } catch(e) {\n      LogUtils.exception(e);\n      this.displayErrorMessage(e.message);\n    }\n  }\n\n  private displayErrorMessage(message: string): void {\n    this.errorTk = 'pages.login.errors.generic';\n    if(message === ErrorType.INVALID_TFA) {\n      this.errorTk = 'pages.login.errors.twoFactor';\n      this.showTfa = true;\n      this.focusTfa = true;\n    }\n    if(message === ErrorType.TOO_MANY_INVALID_LOGINS_BY_IP) {\n      this.errorTk = 'pages.login.errors.tooManyInvalidLoginsByIpError';\n    }\n    if(message === ErrorType.DISABLED_TENANT) {\n      this.errorTk = 'pages.login.errors.disabledTenant';\n    }\n    // TOO_MANY_SESSIONS can only trigger if the user has no admin roles\n    if(message === AuthError.ERR_NO_ROLES || message === ErrorType.TOO_MANY_SESSIONS || message === ErrorType.USER_LOGIN_WRONG_CLIENT) {\n      this.errorTk = this.isFrp ? 'pages.login.errors.noRolesFrp' : 'pages.login.errors.noRoles';\n    }\n  }\n\n  private cancelTfa(): void {\n    this.showTfa = false;\n    this.tfa = '';\n    this.email = '';\n    this.password = '';\n    this.errorTk = '';\n  }\n\n  private async loginExternal(provider: LoginProvider): Promise<void> {\n    const url = await this.authApiService.getAuthUrl(provider, false);\n    window.location.href = url;\n  }\n\n  private async updateExternalLoginProviders(): Promise<void> {\n    const availableExternalLoginProviders = await this.authApiService.getExternalProviders();\n    this.externalLoginConfigurations = availableExternalLoginProviders.map(provider => ({\n      color: 'secondary1',\n      provider,\n      callback: () => this.loginExternal(provider)\n    }));\n  }\n\n  private handleShowPasswordResetClick(): void {\n    this.resetEmail = this.email;\n    this.showPasswordReset = true;\n    this.focusPasswordReset = true;\n    this.showPasswordResetInfo = false;\n  }\n\n  private handleCancelPasswordResetClick(): void {\n    this.resetEmail = '';\n    this.email = '';\n    this.password = '';\n    this.showPasswordReset = false;\n    this.showPasswordResetInfo = false;\n    this.showPasswordResetError = false;\n  }\n\n  private async resetPassword(): Promise<void> {\n    this.showPasswordResetError = false;\n    try {\n      await this.authApiService.sendPasswordReset(this.resetEmail);\n      this.showPasswordResetInfo = true;\n    } catch(e) {\n      this.showPasswordResetError = true;\n      this.focusPasswordReset = true;\n      LogUtils.exception(e);\n    }\n  }\n\n  private togglePasswordVisibility(): void {\n    this.passwordInputType = this.passwordInputType === 'password' ? 'text' : 'password';\n  }\n\n  private async goToTeacherRegistrationPage(): Promise<void> {\n    const confirmed = await this.customDialogService?.confirmAction({\n      titleTk: 'pages.login.registerNow',\n      textTk: 'pages.login.registerNowText',\n      textTkParams: {\n        ufeUrl: Config().ufe.baseUrl,\n        ufeUrlFormatted: StringUtils.formatUrl(Config().ufe.baseUrl)\n      },\n      confirmTk: 'pages.login.registerNow',\n      confirmPositive: true\n    });\n    if(!confirmed) return;\n    this.router.navigateToRoute('teacher-registration');\n  }\n}\n","import { autoinject } from 'aurelia-framework';\nimport { I18N } from 'aurelia-i18n';\nimport { ColumnSortDirection, FilterOperationType } from 'common/dto/filter/filter.enum';\nimport { IFilterDto } from 'common/dto/filter/filter.interface';\nimport { ILogEntryResponseDto } from 'common/dto/log/log.dto.interface';\nimport { LogMessages, LogTitles } from 'common/log/log.messages';\nimport { LogType } from 'common/log/log.type';\nimport { StringUtils } from 'common/utils/StringUtils';\nimport dayjs from 'dayjs';\nimport { DateService } from '../../../services/DateService';\nimport { CustomTableCell } from '../../elements/custom-table/custom-table-cell/custom-table-cell';\nimport { IColumnDefinition, SortNulls } from '../../elements/custom-table/custom-table-interfaces';\nimport { FilteredExportWidgetExportCsvEvent } from '../../elements/filtered-export-widget/filtered-export-widget';\nimport { LogsApiService } from './../../../services/api/LogsApiService';\nimport { createPrepareServersideSortingFunction, prepareServersideFiltering, VirtualFilterField } from './../../elements/custom-table/custom-table-helpers';\n\n@autoinject()\nexport class LogsPage {\n  private logLocale: 'de' | 'en' = 'de';\n  private filter: IFilterDto<ILogEntryResponseDto> = {\n    offset: 0,\n    limit: 10,\n    order: [\n      {\n        field: 'timestamp',\n        dir: ColumnSortDirection.DESC,\n      }\n    ],\n    filter: []\n  };\n  private extraDataDateKeys = ['newFrom', 'newTo', 'oldFrom', 'oldTo'];\n\n  private tableColumns: Array<IColumnDefinition<CustomTableCell<ILogEntryResponseDto>>> = [\n    {\n      id: 'datetime',\n      nameTk: 'pages.logs.datetime',\n      prepareSorting: createPrepareServersideSortingFunction(this.filter, 'timestamp'),\n      cellViewModel: CustomTableCell,\n      cellOptions: { transformer: e => this.dateService.formatDateTime(e.timestamp) },\n      filter: {\n        placeholderTk: 'globals.filter',\n        daterange: true,\n        prepare: v => {\n          const [start, end] = v.split('|');\n          const filterEndDate = end ? (dayjs(end).add(1, 'day')).toISOString() : '';\n          prepareServersideFiltering(this.filter, 'timestamp' as VirtualFilterField, start, FilterOperationType.Gt);\n          prepareServersideFiltering(this.filter, 'timestamp' as VirtualFilterField, filterEndDate, FilterOperationType.Lt);\n        },\n      }\n    },\n    {\n      id: 'type',\n      nameTk: 'pages.logs.type',\n      prepareSorting: createPrepareServersideSortingFunction(this.filter, 'typeId' as VirtualFilterField),\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: v => prepareServersideFiltering(this.filter, 'typeId' as VirtualFilterField, v, FilterOperationType.Eq),\n        options: this.getLogTypeFilterOptions().sort((a, b) => a.key.localeCompare(b.key)),\n      },\n      cellViewModel: CustomTableCell,\n      cellOptions: { transformer: this.getLogTitleString.bind(this) },\n    },\n    {\n      id: 'message',\n      nameTk: 'pages.logs.message',\n      cellViewModel: CustomTableCell,\n      cellOptions: { transformer: this.getLogMessageString.bind(this), spanClasses: 'text-wrap' },\n    },\n    {\n      id: 'tenant',\n      nameTk: 'globals.tenant',\n      prepareSorting: createPrepareServersideSortingFunction(this.filter, 'tenantId'),\n      cellViewModel: CustomTableCell,\n      sortNulls: SortNulls.Last,\n      cellOptions: { property: 'tenantName' },\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: v => prepareServersideFiltering(this.filter, 'tenantName' as VirtualFilterField, v, FilterOperationType.Like),\n      }\n    },\n    {\n      id: 'firstname',\n      nameTk: 'globals.firstname',\n      prepareSorting: createPrepareServersideSortingFunction(this.filter, 'userFirstname' as VirtualFilterField),\n      cellViewModel: CustomTableCell,\n      sortNulls: SortNulls.Last,\n      cellOptions: {\n        transformer: e => e?.user?.firstname ?? ''\n      },\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: v => prepareServersideFiltering(this.filter, 'userFirstname' as VirtualFilterField, v, FilterOperationType.Like),\n      }\n    },\n    {\n      id: 'lastname',\n      nameTk: 'globals.lastname',\n      prepareSorting: createPrepareServersideSortingFunction(this.filter, 'userLastname' as VirtualFilterField),\n      cellViewModel: CustomTableCell,\n      sortNulls: SortNulls.Last,\n      cellOptions: {\n        transformer: e => e?.user?.lastname ?? ''\n      },\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: v => prepareServersideFiltering(this.filter, 'userLastname' as VirtualFilterField, v, FilterOperationType.Like),\n      }\n    },\n    {\n      id: 'email',\n      nameTk: 'globals.email',\n      prepareSorting: createPrepareServersideSortingFunction(this.filter, 'userEmail' as VirtualFilterField),\n      cellViewModel: CustomTableCell,\n      sortNulls: SortNulls.Last,\n      cellOptions: {\n        transformer: e => e?.user?.email ?? ''\n      },\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: v => prepareServersideFiltering(this.filter, 'userEmail' as VirtualFilterField, v, FilterOperationType.Like),\n      },\n      wrap: true\n    },\n    {\n      id: 'phoneNumber',\n      nameTk: 'globals.phone',\n      cellViewModel: CustomTableCell,\n      cellOptions: {\n        transformer: e => StringUtils.formatPhoneNumber(e.user?.phoneNumberCc, e.user?.phoneNumberNn),\n      },\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: v => prepareServersideFiltering(this.filter, 'userPhoneNumber' as VirtualFilterField, v, FilterOperationType.Like),\n      },\n      wrap: true\n    },\n    {\n      id: 'targetUserFirstname',\n      nameTk: 'pages.logs.targetUserFirstname',\n      prepareSorting: createPrepareServersideSortingFunction(this.filter, 'targetUserFirstname' as VirtualFilterField),\n      cellViewModel: CustomTableCell,\n      sortNulls: SortNulls.Last,\n      cellOptions: {\n        transformer: e => e?.targetUser?.firstname ?? ''\n      },\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: v => prepareServersideFiltering(this.filter, 'targetUserFirstname' as VirtualFilterField, v, FilterOperationType.Like),\n      }\n    },\n    {\n      id: 'targetUserLastname',\n      nameTk: 'pages.logs.targetUserLastname',\n      prepareSorting: createPrepareServersideSortingFunction(this.filter, 'targetUserLastname' as VirtualFilterField),\n      cellViewModel: CustomTableCell,\n      sortNulls: SortNulls.Last,\n      cellOptions: {\n        transformer: e => e?.targetUser?.lastname ?? ''\n      },\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: v => prepareServersideFiltering(this.filter, 'targetUserLastname' as VirtualFilterField, v, FilterOperationType.Like),\n      }\n    },\n    {\n      id: 'targetUserEmail',\n      nameTk: 'pages.logs.targetUserEmail',\n      prepareSorting: createPrepareServersideSortingFunction(this.filter, 'targetUserEmail' as VirtualFilterField),\n      cellViewModel: CustomTableCell,\n      sortNulls: SortNulls.Last,\n      cellOptions: {\n        transformer: e => e?.targetUser?.email ?? ''\n      },\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: v => prepareServersideFiltering(this.filter, 'targetUserEmail' as VirtualFilterField, v, FilterOperationType.Like),\n      }\n    },\n    {\n      id: 'targetUserPhoneNumber',\n      nameTk: 'pages.logs.targetUserPhoneNumber',\n      cellViewModel: CustomTableCell,\n      cellOptions: {\n        transformer: e => StringUtils.formatPhoneNumber(e.targetUser?.phoneNumberCc, e.targetUser?.phoneNumberNn),\n      },\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: v => prepareServersideFiltering(this.filter, 'targetUserPhoneNumber' as VirtualFilterField, v, FilterOperationType.Like),\n      }\n    },\n    {\n      id: 'data',\n      nameTk: 'pages.logs.data',\n      cellViewModel: CustomTableCell,\n      cellOptions: {\n        transformer: e => {\n          switch(e.logTypeId) {\n            case LogType.FEEDBACK:\n              return e.data.feedback;\n            case LogType.LOGIN_FAILED:\n              return e.data.identifier;\n            case LogType.COURSE_ASSIGNED:\n            case LogType.CODE_EXTENDED:\n              return `${this.dateService.formatDate(e.data.previousActiveUntil)} → ${this.dateService.formatDate(e.data.newActiveUntil)}`;\n            case LogType.COURSE_ASSIGNMENT_CHANGED:\n            default:\n              return '';\n          }\n        }\n      }\n    }\n  ];\n\n  constructor(\n    private apiService: LogsApiService,\n    private i18n: I18N,\n    private dateService: DateService,\n  ) { }\n\n  protected attached(): void {\n    this.logLocale = this.i18n.getLocale() === 'de' ? 'de' : 'en';\n  }\n\n  private async fetchTableData(limit: number, offset: number): Promise<{ total: number; data: Array<ILogEntryResponseDto> }> {\n    this.filter.limit = limit;\n    this.filter.offset = offset;\n    const results = await this.apiService.getLogs(this.filter);\n    return { data: results.rows, total: results.count };\n  }\n\n  private async exportCsv(event: FilteredExportWidgetExportCsvEvent): Promise<void> {\n    this.apiService.exportLogs(this.filter, event.detail.csvType);\n  }\n\n  private getLogMessageString(entry: ILogEntryResponseDto): string {\n    const text: string = ((LogMessages[this.logLocale] as Record<number, string>)[entry.logMessageId]);\n    return this.insertLogData(text, entry);\n  }\n\n  private getLogTitleString(entry: ILogEntryResponseDto): string {\n    const text: string = ((LogTitles[this.logLocale] as Record<number, string>)[entry.logTypeId]);\n    return this.insertLogData(text, entry);\n  }\n\n  private insertLogData(text: string, entry: ILogEntryResponseDto): string {\n    let processedText = text;\n    if(entry.data && processedText) {\n      for(const [extraKey, extraValue] of Object.entries(entry.data)) {\n        let value: string = extraValue as string;\n        if(this.extraDataDateKeys.includes(extraKey)) {\n          value = this.dateService.formatDateTime(value);\n        }\n        processedText = processedText.replace(`{{${extraKey}}}`, value);\n      }\n    }\n    return processedText;\n  }\n\n  private getLogTypeFilterOptions(): Array<{ key: string; value: string }> {\n    const options: Array<{ key: string; value: string }> = [];\n    for(const [key, value] of Object.entries(LogTitles[this.logLocale])) {\n      options.push({ key: value, value: key });\n    }\n    return options;\n  }\n}\n"],"names":[],"sourceRoot":""}