{"version":3,"file":"app-7f50e535.f584a1446b2fc034d810.bundle.js","mappings":"AAGA","sources":["webpack://lernplattform-admin-frontend/./src/resources/pages/tenant-course-page/tenant-course-page.html","webpack://lernplattform-admin-frontend/./src/resources/pages/tenant-courses-page/tenant-courses-page.html","webpack://lernplattform-admin-frontend/./src/resources/pages/tenant-event-attendants-page/tenant-event-attendants-page.html","webpack://lernplattform-admin-frontend/./src/resources/pages/tenant-group-events-page/tenant-group-events-page.html","webpack://lernplattform-admin-frontend/./src/resources/pages/tenant-group-list-page/tenant-group-list-page.html","webpack://lernplattform-admin-frontend/./src/resources/pages/tenant-group-media-share-page/tenant-group-media-share-page.html","webpack://lernplattform-admin-frontend/./src/resources/pages/tenant-course-page/tenant-course-page.ts","webpack://lernplattform-admin-frontend/./src/resources/pages/tenant-courses-page/tenant-courses-page.ts","webpack://lernplattform-admin-frontend/./src/resources/pages/tenant-event-attendants-page/tenant-event-attendants-page.ts","webpack://lernplattform-admin-frontend/./src/resources/pages/tenant-group-events-page/tenant-group-events-page.ts","webpack://lernplattform-admin-frontend/./src/resources/pages/tenant-group-list-page/tenant-group-list-page.ts","webpack://lernplattform-admin-frontend/./src/resources/pages/tenant-group-media-share-page/tenant-group-media-share-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\\\">${course.title}</h1> </div> <navigation-tabs tabs.to-view=\\\"navigationTabs\\\" class=\\\"mb-6\\\"></navigation-tabs> <assign-skills-form if.to-view=\\\"activeTab === ENavigationTab.SKILLS && course\\\" skills.to-view=\\\"courseSkills\\\" save-clicked.trigger=\\\"onSaveSkills($event)\\\"></assign-skills-form> <assign-learning-journeys-form if.to-view=\\\"activeTab === ENavigationTab.LEARNING_JOURNEYS\\\" learning-journeys.to-view=\\\"learningJourneysOfCourse\\\" show-radios.to-view=\\\"true\\\" save-clicked.trigger=\\\"onSaveLearningJourneys($event)\\\"></assign-learning-journeys-form> </template> \";\n// Exports\nexport default code;","// Module\nvar code = \"<template> <div class=\\\"page-header\\\"> <h1 class=\\\"page-title\\\" t=\\\"globals.assignedCourses\\\"></h1> </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=\\\"learningJourneyFeatureEnabled\\\" selected.two-way=\\\"selectedCourses\\\" table-id=\\\"tenant-courses-page\\\" refresh-version.to-view=\\\"tableRefreshVersion\\\" get-shown-entries-data.call=\\\"fetchTableData(limit, offset)\\\"> <button if.to-view=\\\"selectedCourses.length\\\" click.delegate=\\\"assignLearningJourneysToCourses()\\\" type=\\\"button\\\" class=\\\"btn btn-outline-primary btn-sm\\\" t=\\\"globals.assignLearningJourneys\\\"></button> <button if.to-view=\\\"selectedCourses.length\\\" click.delegate=\\\"assignSkillsToCourses()\\\" type=\\\"button\\\" class=\\\"btn btn-outline-primary btn-sm\\\" t=\\\"globals.assignSkills\\\"></button> <button if.to-view=\\\"selectedCourses.length\\\" click.delegate=\\\"assignCoursesToStudents()\\\" 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 class=\\\"page-header\\\"> <h1 class=\\\"page-title\\\" t=\\\"pages.event-attendants.title\\\" t-params.to-view=\\\"{ eventName: event.title }\\\"></h1> <div class=\\\"ml-auto\\\"> <button-standard click.trigger=\\\"createPdf()\\\" t=\\\"[btn-text]pages.event-attendants.print\\\"></button-standard> </div> </div> <div class=\\\"row\\\"> <div class=\\\"col-6\\\"> <div class=\\\"card\\\"> <div class=\\\"card-body\\\"> <div class=\\\"card-title\\\" t=\\\"pages.event-attendants.eventDetails\\\"></div> <div class=\\\"row\\\"> <div class=\\\"col-12\\\"> <label class=\\\"form-label\\\" t=\\\"pages.event-attendants.date\\\" t-params.to-view=\\\"{ date: dateService.formatDate(event.plannedDateFrom) }\\\"></label> </div> </div> <div class=\\\"row\\\"> <div class=\\\"col-12\\\"> <label class=\\\"form-label\\\" t=\\\"pages.event-attendants.plannedTimeFromTo\\\" t-params.to-view=\\\"{ timeStart: formatDate(event.plannedDateFrom), timeEnd: formatDate(event.plannedDateTo) }\\\"></label> </div> </div> <div if.to-view=\\\"event.actualDateFrom && event.actualDateTo\\\" class=\\\"row\\\"> <div class=\\\"col-12\\\"> <label class=\\\"form-label\\\" t=\\\"pages.event-attendants.actualTimeFromTo\\\" t-params.to-view=\\\"{ timeStart: formatDate(event.actualDateFrom), timeEnd: formatDate(event.actualDateTo) }\\\"></label> </div> </div> </div> </div> </div> <div class=\\\"col-6\\\"> <div class=\\\"row\\\"> <div class=\\\"col-6\\\"> <label class=\\\"form-label\\\" t=\\\"pages.event-attendants.filterCourse\\\"></label> <div class=\\\"form-group\\\"> <div click.trigger=\\\"selectedCourseId = null\\\" class=\\\"custom-control custom-radio\\\"> <input class=\\\"custom-control-input tenant-event-attendants-page__disabled-checkbox\\\" type=\\\"checkbox\\\" id=\\\"eventAttendantsCourseFilterRadio\\\" checked.to-view=\\\"!selectedCourseId\\\"> <label class=\\\"custom-control-label\\\" for=\\\"eventAttendantsCourseFilterRadio\\\" t=\\\"pages.event-attendants.showAll\\\"></label> </div> <div repeat.for=\\\"course of event.courses\\\" class=\\\"custom-control custom-radio\\\"> <input class=\\\"custom-control-input\\\" type=\\\"radio\\\" id=\\\"eventAttendantsCourseFilterRadio${course.id}\\\" model.bind=\\\"course.id\\\" checked.bind=\\\"selectedCourseId\\\"> <label class=\\\"custom-control-label\\\" for=\\\"eventAttendantsCourseFilterRadio${course.id}\\\">${course.title}</label> </div> </div> </div> <div class=\\\"col-6\\\"> <label class=\\\"form-label\\\" t=\\\"pages.event-attendants.filterGroup\\\"></label> <div class=\\\"form-group\\\"> <div click.trigger=\\\"selectedCourseGroupId = null\\\" class=\\\"custom-control custom-radio\\\"> <input class=\\\"custom-control-input tenant-event-attendants-page__disabled-checkbox\\\" type=\\\"checkbox\\\" id=\\\"eventAttendantsCourseGroupFilterRadio\\\" checked.to-view=\\\"!selectedCourseGroupId\\\"> <label class=\\\"custom-control-label\\\" for=\\\"eventAttendantsCourseGroupFilterRadio\\\" t=\\\"pages.event-attendants.showAll\\\"></label> </div> <div repeat.for=\\\"group of event.courseGroups\\\" class=\\\"custom-control custom-radio\\\"> <input class=\\\"custom-control-input\\\" type=\\\"radio\\\" id=\\\"eventAttendantsCourseGroupFilterRadio${group.id}\\\" model.bind=\\\"group.id\\\" checked.bind=\\\"selectedCourseGroupId\\\"> <label class=\\\"custom-control-label\\\" for=\\\"eventAttendantsCourseGroupFilterRadio${group.id}\\\">${group.name}</label> </div> </div> </div> </div> </div> </div> <div class=\\\"row row-cards row-deck\\\"> <div class=\\\"col-12\\\"> <custom-table columns.to-view=\\\"tableColumns\\\" table-id.to-view=\\\"`tenant-event-attendants-page-${eventId}`\\\" refresh-version.to-view=\\\"tableRefreshVersion\\\" get-shown-entries-data.call=\\\"fetchTableData(limit, offset)\\\"></custom-table> </div> </div> </template>\";\n// Exports\nexport default code;","// Module\nvar code = \"<template> <div class=\\\"page-header\\\"> <h1 class=\\\"page-title\\\" t=\\\"pages.group-events.title\\\" t-params.to-view=\\\"{ groupName: courseGroupName }\\\"></h1> </div> <div if.to-view=\\\"!hasEvents\\\" class=\\\"alert alert-info\\\"> <span t=\\\"pages.group-events.noGroupEvents\\\"></span> </div> <div else class=\\\"row row-cards row-deck\\\"> <div class=\\\"col-12\\\"> <custom-table columns.to-view=\\\"tableColumns\\\" extendable=\\\"true\\\" table-id=\\\"tenant-group-events-page-${courseGroupId}\\\" refresh-version.to-view=\\\"tableRefreshVersion\\\" get-shown-entries-data.call=\\\"fetchTableData(limit, offset)\\\"></custom-table> </div> </div> </template>\";\n// Exports\nexport default code;","// Module\nvar code = \"<template> <div class=\\\"page-header\\\"> <h1 class=\\\"page-title\\\" t=\\\"pages.groups.title\\\"></h1> <div class=\\\"ml-auto\\\"> <button-standard if.to-view=\\\"selectedCourseGroups.length > 0\\\" click.delegate=\\\"deleteSelectedCourseGroups()\\\" class=\\\"mb-2 d-inline-block\\\" t=\\\"[btnText]pages.groups.deleteSelectedCourseGroups\\\" icon-name=\\\"System/Tabler/Trash\\\" btn-color=\\\"danger\\\"></button-standard> <button-standard click.delegate=\\\"createCourseGroup()\\\" class=\\\"mb-2 d-inline-block\\\" t=\\\"[btnText]pages.groups.createCourseGroup\\\" icon-name=\\\"System/Tabler/User-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=\\\"true\\\" table-id=\\\"tenant-group-list-page\\\" selectable.to-view=\\\"true\\\" selected.two-way=\\\"selectedCourseGroups\\\" get-shown-entries-data.call=\\\"fetchTableData(limit, offset)\\\" refresh-version.to-view=\\\"tableRefreshVersion\\\"></custom-table> </div> </div> </template>\";\n// Exports\nexport default code;","// Module\nvar code = \"<template> <div class=\\\"page-header\\\"> <h1 if.to-view=\\\"courseGroup\\\" class=\\\"page-title\\\" t=\\\"pages.tenant-group-media-share.title\\\" t-params.to-view=\\\"{ courseGroupName: courseGroup.name }\\\"></h1> <div class=\\\"ml-auto\\\"> <share-media-button table-refresh-version.two-way=\\\"tableRefreshVersion\\\" course-group-id.to-view=\\\"courseGroup.id\\\" course-id.to-view=\\\"courseGroup.course.id\\\"></share-media-button> </div> </div> <div class=\\\"row row-cards row-deck\\\"> <div class=\\\"col-12\\\"> <media-share-table if.to-view=\\\"courseGroup\\\" table-refresh-version.two-way=\\\"tableRefreshVersion\\\" course-group-id.to-view=\\\"courseGroup.id\\\"></media-share-table> </div> </div> </template>\";\n// Exports\nexport default code;","import { autoinject } from 'aurelia-framework';\nimport { Router } from 'aurelia-router';\nimport { ICourseEditResponseDto } from 'common/dto/course/management/course.management.interface';\nimport { FilterOperationType } from 'common/dto/filter/filter.enum';\nimport { IBulkAssignCoursesToLearningJourneysDto } 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 { IAssignableLearningJourneyDto } from '../../../interfaces/assign.interface';\nimport { ToastService } from '../../../services/ToastService';\nimport { LearningJourneyManagementApiService } from '../../../services/api/LearningJourneyManagementApiService';\nimport { TenantApiService } from '../../../services/api/TenantApiService';\nimport { AssignLearningJourneysFormSaveClickedEvent } from '../../elements/assign-learning-journeys-form/assign-learning-journeys-form';\nimport { AssignSkillsFormSaveClickedEvent } from '../../elements/assign-skills-form/assign-skills-form';\nimport { INavigationTab } from '../../elements/navigation-tabs/navigation-tabs';\n\ninterface IParams {\n  courseId: string;\n  tab?: ENavigationTab;\n}\n\nexport enum ENavigationTab {\n  SKILLS = 'skills',\n  LEARNING_JOURNEYS = 'learning-journeys',\n}\n\n@autoinject()\nexport class TenantCoursePage {\n  private courseId: number | null = null;\n  private course: ICourseEditResponseDto | null = null;\n  private courseSkills: ISkillDto[] = [];\n  private learningJourneysOfCourse: IAssignableLearningJourneyDto[] = [];\n\n  private activeTab: ENavigationTab = ENavigationTab.SKILLS;\n  private ENavigationTab = ENavigationTab;\n  private navigationTabs: INavigationTab[] = [];\n\n  constructor(\n    private tenantApiService: TenantApiService,\n    private learningJourneyManagementApiService: LearningJourneyManagementApiService,\n    private router: Router,\n    private toastService: ToastService,\n  ) { }\n\n  protected activate(params: IParams): void {\n    this.courseId = parseInt(params.courseId, 10);\n    this.activeTab = params.tab ?? ENavigationTab.SKILLS;\n    this.navigationTabs = [\n      {\n        title: { titleTk: 'globals.skills' },\n        active: this.activeTab === ENavigationTab.SKILLS,\n        callback: () => { this.navigateToTab(ENavigationTab.SKILLS); }\n      },\n      {\n        title: { titleTk: 'globals.learningJourneys' },\n        active: this.activeTab === ENavigationTab.LEARNING_JOURNEYS,\n        callback: () => { this.navigateToTab(ENavigationTab.LEARNING_JOURNEYS); }\n      }\n    ];\n    this.updateCourseAndLearningJourneys();\n  }\n\n  private navigateToTab(tab: ENavigationTab): void {\n    this.router.navigateToRoute('tenant-course/id/tab', { tab, courseId: this.courseId });\n  }\n\n  private async updateCourseAndLearningJourneys(): Promise<void> {\n    assertNotNullOrUndefined(this.courseId, 'courseId cannot be null or undefined');\n    const course = await this.tenantApiService.getCourse(this.courseId);\n    const courseSkills = await this.tenantApiService.getCourseSkills(this.courseId);\n    const learningJourneys = (await this.learningJourneyManagementApiService.getLearningJourneys({\n      filter: [\n        {\n          field: 'courses',\n          type: FilterOperationType.In,\n          value: [this.courseId],\n        }\n      ]\n    })).rows.map(lj => ({\n      coursesRequired: lj.courses.find(c => c.courseId === this.courseId)?.required ?? false,\n      learningJourneyId: lj.id,\n      learningJourneyTitle: lj.title,\n    }));\n    this.course = course;\n    this.courseSkills = courseSkills;\n    this.learningJourneysOfCourse = learningJourneys;\n  }\n\n  private navigateBack(): void {\n    this.router.navigateToRoute('tenant-courses');\n  }\n\n  private async onSaveSkills(event: AssignSkillsFormSaveClickedEvent): Promise<void> {\n    assertNotNullOrUndefined(this.course, 'course cannot be null or undefined');\n    this.courseSkills = await this.tenantApiService.updateCourseSkills(this.course.id, event.detail.selectedSkillIds);\n    this.toastService.success('globals.editSuccess');\n  }\n\n  private async onSaveLearningJourneys(event: AssignLearningJourneysFormSaveClickedEvent): Promise<void> {\n    assertNotNullOrUndefined(this.courseId, 'courseId cannot be null or undefined');\n    const { courseId } = this;\n    const { selectedLearningJourneys } = event.detail;\n\n    const dto: IBulkAssignCoursesToLearningJourneysDto = {\n      learningJourneyIds: [],\n      learningJourneys: selectedLearningJourneys.map(lJ => ({ learningJourneyId: lJ.learningJourneyId, required: lJ.coursesRequired })),\n      courses: [],\n      courseIds: [courseId]\n    };\n\n    await this.learningJourneyManagementApiService.bulkAssignCoursesToLearningJourney(dto);\n    this.toastService.success('globals.editSuccess');\n    await this.updateCourseAndLearningJourneys();\n  }\n}\n","import { autoinject } from 'aurelia-framework';\nimport { Router } from 'aurelia-router';\nimport { StoreService } from 'common/aurelia-services/StoreService';\nimport { COURSE_RATING_OPTIONS } from 'common/constants/course.constants';\nimport { ITenantCourseDto } from 'common/dto/course/access/course.access.interface';\nimport { ColumnSortDirection, FilterOperationType } from 'common/dto/filter/filter.enum';\nimport { IFilterDto } from 'common/dto/filter/filter.interface';\nimport { Language } from 'common/dto/other/language.enum';\nimport { ECourseAvailability } from 'common/enum/tenant.enum';\nimport { Config } from 'common/fe-config/config';\nimport { TenantManagementApiService } from '../../../services/api/TenantManagementApiService';\nimport { CustomDialogService } from '../../../services/CustomDialogService';\nimport { IState } from '../../../store/state';\nimport { ButtonCell } from '../../elements/custom-table/button-cell/button-cell';\nimport { CustomTableCell } from '../../elements/custom-table/custom-table-cell/custom-table-cell';\nimport { createPrepareServersideSortingFunction, prepareServersideFiltering, VirtualFilterField } from '../../elements/custom-table/custom-table-helpers';\nimport { IColumnDefinition, SortNulls } from '../../elements/custom-table/custom-table-interfaces';\nimport { RatingCell } from '../../elements/custom-table/rating-cell/rating-cell';\nimport { ENavigationTab } from '../tenant-course-page/tenant-course-page';\n\n@autoinject()\nexport class TenantCoursesPage {\n  private learningJourneyFeatureEnabled: boolean = Config().learningJourney.enabled;\n\n  private tenantId: number | null = null;\n  private selectedCourses: ITenantCourseDto[] = [];\n  private filter: IFilterDto<ITenantCourseDto> = {\n    filter: [{\n      field: 'isLectureCourse' as VirtualFilterField,\n      type: FilterOperationType.Eq,\n      value: false,\n    }],\n    order: [{\n      field: 'courseTitle' as VirtualFilterField,\n      dir: ColumnSortDirection.ASC,\n    }],\n  };\n  private tableRefreshVersion: number = 0;\n\n  private tableColumns: Array<IColumnDefinition<CustomTableCell<ITenantCourseDto> | RatingCell<ITenantCourseDto> | ButtonCell<ITenantCourseDto>>> = [\n    {\n      id: 'title',\n      nameTk: 'globals.title',\n      cellViewModel: CustomTableCell,\n      cellOptions: {\n        transformer: course => course.title || '-',\n        callback: course => this.navigateToCourse(course.id),\n        clickable: () => this.learningJourneyFeatureEnabled,\n      },\n      prepareSorting: createPrepareServersideSortingFunction(this.filter, 'courseTitle' as VirtualFilterField),\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: v => prepareServersideFiltering(this.filter, 'courseTitle' as VirtualFilterField, v, FilterOperationType.Like)\n      }\n    },\n    {\n      id: 'language',\n      nameTk: 'globals.language',\n      cellViewModel: CustomTableCell,\n      prepareSorting: createPrepareServersideSortingFunction(this.filter, 'language'),\n      cellOptions: {\n        transformer: course => course.language.toUpperCase(),\n      },\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: v => prepareServersideFiltering(this.filter, 'language', v, FilterOperationType.Eq),\n        options: Object.values(Language).map(lang => ({ value: lang, keyTk: `globals.languageOptions.${lang}` }))\n      }\n    },\n    {\n      id: 'standardShares',\n      nameTk: 'pages.tenant-courses.standardShares',\n      cellViewModel: ButtonCell,\n      shrink: true,\n      cellOptions: {\n        buttonText: () => ({\n          tk: 'globals.show'\n        }),\n        clickCallback: async course => { this.showCourseShares(course.id); }\n      }\n    },\n    {\n      id: 'courseGroupShares',\n      nameTk: 'pages.tenant-courses.courseGroupShares',\n      cellViewModel: ButtonCell,\n      shrink: true,\n      cellOptions: {\n        buttonText: () => ({\n          tk: 'globals.show'\n        }),\n        clickCallback: async course => { this.showCourseGroupShares(course.id); }\n      }\n    },\n    {\n      id: 'availabilityType',\n      nameTk: 'globals.visibility',\n      cellViewModel: CustomTableCell,\n      cellOptions: {\n        tk: course => `globals.availabilityType.${course.availability}`\n      },\n      visible: () => this.learningJourneyFeatureEnabled,\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: course => prepareServersideFiltering(this.filter, 'availabilityType' as VirtualFilterField, course, FilterOperationType.Eq),\n        options: Object.values(ECourseAvailability)\n          .map(type => (\n            {\n              keyTk: `globals.availabilityType.${type}`,\n              value: type\n            }\n          ))\n      }\n    },\n    {\n      id: 'rating',\n      nameTk: 'pages.tenant-courses.globalRating',\n      cellViewModel: RatingCell,\n      cellOptions: {\n        rating: course => course.aggregateRating,\n      },\n      prepareSorting: createPrepareServersideSortingFunction(this.filter, 'aggregateRating'),\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: course => prepareServersideFiltering(this.filter, 'aggregateRating', course, FilterOperationType.EqFloor),\n        options: COURSE_RATING_OPTIONS,\n      },\n      sortNulls: SortNulls.Smallest,\n    },\n  ];\n\n  constructor(\n    private tenantManagementApiService: TenantManagementApiService,\n    private storeService: StoreService<IState>,\n    private customDialogService: CustomDialogService,\n    private router: Router,\n  ) { }\n\n  protected attached(): void {\n    this.storeService.subscribeToDetailedChanges(this, [\n      state => state.currentRole?.tenantId ?? null,\n    ], (_state, tenantId) => {\n      this.tenantId = tenantId;\n      this.tableRefreshVersion++;\n    });\n  }\n\n  protected detached(): void {\n    this.storeService.disposeAllSubscriptions(this);\n  }\n\n  private async fetchTableData(limit: number, offset: number): Promise<{ total: number; data: ITenantCourseDto[] }> {\n    if(!this.tenantId) {\n      return { data: [], total: 0 };\n    }\n\n    this.filter.limit = limit;\n    this.filter.offset = offset;\n    const tenantCourses = await this.tenantManagementApiService.getCoursesOfTenant(this.tenantId, this.filter);\n    return {\n      data: tenantCourses.rows,\n      total: tenantCourses.count\n    };\n  }\n\n  private async showCourseShares(courseId: number): Promise<void> {\n    await this.customDialogService.showMediaShareTableDialog({ courseId, forTenantCoursesOnly: true });\n  }\n\n  private async showCourseGroupShares(courseId: number): Promise<void> {\n    await this.customDialogService.showMediaShareTableDialog({ courseId, forTenantCoursesOnly: false });\n  }\n\n  private async assignLearningJourneysToCourses(): Promise<void> {\n    if(await this.customDialogService.showAssignLearningJourneysToCoursesDialog({ courses: this.selectedCourses })) {\n      this.tableRefreshVersion++;\n    }\n  }\n\n  private async assignSkillsToCourses(): Promise<void> {\n    if(await this.customDialogService.showAssignSkillsToCoursesDialog({ courses: this.selectedCourses })) {\n      this.tableRefreshVersion++;\n    }\n  }\n\n  private async assignCoursesToStudents(): Promise<void> {\n    if(await this.customDialogService.showAssignCoursesToStudentsDialog({ courses: this.selectedCourses })) {\n      this.tableRefreshVersion++;\n    }\n  }\n\n  private navigateToCourse(courseId: number): void {\n    this.router.navigateToRoute('tenant-course/id/tab', { tab: ENavigationTab.SKILLS, courseId });\n  }\n}\n","import { autoinject, observable } from 'aurelia-framework';\nimport { I18N } from 'aurelia-i18n';\nimport { StoreService } from 'common/aurelia-services/StoreService';\nimport { FilterOperationType } from 'common/dto/filter/filter.enum';\nimport { IFilterDto } from 'common/dto/filter/filter.interface';\nimport { IEventOverviewEventDto, IEventOverviewUserDto } from 'common/dto/tenant/event/tenant.event.interface';\nimport { LogUtils } from 'common/utils/LogUtils';\nimport { jsPDF } from 'jspdf';\nimport { autoTable } from 'jspdf-autotable';\nimport { IState } from '../../../store/state';\nimport { FilterUtils } from '../../../utils/FilterUtils';\nimport { VirtualFilterField } from '../../elements/custom-table/custom-table-helpers';\nimport { IconCell } from '../../elements/custom-table/icon-cell/icon-cell';\nimport { EventsApiService } from './../../../services/api/EventsApiService';\nimport { CustomDialogService } from './../../../services/CustomDialogService';\nimport { DateService } from './../../../services/DateService';\nimport { PageLoadingIndicatorService } from './../../../services/PageLoadingIndicatorService';\nimport { ToastService } from './../../../services/ToastService';\nimport { ActionsCell } from './../../elements/custom-table/actions-cell/actions-cell';\nimport { CustomTableCell } from './../../elements/custom-table/custom-table-cell/custom-table-cell';\nimport { IColumnDefinition } from './../../elements/custom-table/custom-table-interfaces';\n\n@autoinject()\nexport class TenantEventAttendantsPage {\n  private event: IEventOverviewEventDto<string> | null = null;\n  private eventId: number | null = null;\n  private tenantId: number | null = null;\n\n  @observable() private selectedCourseId: number | null = null;\n  @observable() private selectedCourseGroupId: number | null = null;\n\n  private tableRefreshVersion = 0;\n  private filter: IFilterDto<IEventOverviewUserDto> = {\n    offset: 0,\n    limit: 10,\n    filter: []\n  };\n\n  private tableColumns: Array<IColumnDefinition<CustomTableCell<IEventOverviewUserDto> | IconCell<IEventOverviewUserDto> | ActionsCell<IEventOverviewUserDto>>> = [\n    {\n      id: 'name',\n      nameTk: 'globals.name',\n      cellViewModel: CustomTableCell,\n      cellOptions: {\n        transformer: e => e.nickname ?? this.i18n.tr('globals.empty')\n      },\n    },\n    {\n      id: 'status',\n      nameTk: 'pages.event-attendants.status',\n      cellViewModel: IconCell,\n      cellOptions: {\n        classes: 'text-left text-success',\n        iconTransformer: e => e.attended ? 'System/Tabler/Check' : '',\n        trailingTextTransformer: e => e.attended ? this.i18n.tr('pages.event-attendants.attended') : ''\n      },\n    },\n    {\n      id: 'attendanceInPercent',\n      nameTk: 'pages.event-attendants.attendanceInPercent',\n      cellViewModel: CustomTableCell,\n      cellOptions: {\n        transformer: e => e.attendedPercentage ? `${Math.min(e.attendedPercentage, 100)}%` : '0%'\n      },\n    },\n    {\n      id: 'actions',\n      nameTk: '',\n      shrink: true,\n      cellViewModel: ActionsCell,\n      cellOptions: {\n        entries: [\n          {\n            labelTk: 'pages.event-attendants.editEventAttendanceIntervals',\n            clickCallback: e => this.showManageAttendanceIntervalsDialog(e)\n          },\n          {\n            labelTk: 'pages.event-attendants.editEventAttendance',\n            clickCallback: e => this.showManageAttendanceDialog(e)\n          },\n        ],\n      }\n    }\n  ];\n\n  constructor(\n    private eventsApi: EventsApiService,\n    private customDialogService: CustomDialogService,\n    private dateService: DateService,\n    private toastService: ToastService,\n    private indicatorService: PageLoadingIndicatorService,\n    private i18n: I18N,\n    private storeService: StoreService<IState>,\n  ) { }\n\n  protected activate(params: Record<string, string>): void {\n    this.eventId = params.eventId ? parseInt(params.eventId) : null;\n\n    this.storeService.subscribeToDetailedChanges(this, [\n      state => state.currentRole?.tenantId ?? null,\n    ], (_state, tenantId) => {\n      this.tenantId = tenantId;\n      this.updateEventDetails();\n    });\n  }\n\n  protected deactivate(): void {\n    this.storeService.disposeAllSubscriptions(this);\n  }\n\n  private async updateEventDetails(): Promise<void> {\n    if(!this.eventId || !this.tenantId) return;\n    this.event = await this.eventsApi.getEvent(this.tenantId, this.eventId);\n  }\n\n  private async fetchTableData(limit: number, offset: number): Promise<{ total: number; data: Array<IEventOverviewUserDto> } | void> {\n    this.filter.limit = limit;\n    this.filter.offset = offset;\n    if(!this.eventId || !this.tenantId) return;\n    if(this.selectedCourseId) {\n      this.filter = FilterUtils.removeDuplicateFilterFields(\n        this.filter,\n        {\n          field: 'courseId' as VirtualFilterField,\n          value: this.selectedCourseId,\n          type: FilterOperationType.Eq\n        }\n      );\n    } else {\n      this.filter = FilterUtils.removeFilterForField(this.filter, 'courseId' as VirtualFilterField);\n    }\n    if(this.selectedCourseGroupId) {\n      this.filter = FilterUtils.removeDuplicateFilterFields(\n        this.filter,\n        {\n          field: 'courseGroupId' as VirtualFilterField,\n          value: this.selectedCourseGroupId,\n          type: FilterOperationType.Eq\n        }\n      );\n    } else {\n      this.filter = FilterUtils.removeFilterForField(this.filter, 'courseGroupId' as VirtualFilterField);\n    }\n\n    const results = await this.eventsApi.getGroupEventOverview(this.tenantId, this.eventId, this.filter);\n    return { data: results.rows, total: results.count };\n  }\n\n  private async showManageAttendanceIntervalsDialog(eventOverviewUser: IEventOverviewUserDto): Promise<void> {\n    if(!this.event) return;\n    const dialogValue = await this.customDialogService.showManageAttendanceIntervalsDialog({\n      event: this.event,\n      user: {\n        id: eventOverviewUser.userId,\n        nickname: eventOverviewUser.nickname,\n      },\n    });\n    if(dialogValue) this.tableRefreshVersion++;\n  }\n\n  private async showManageAttendanceDialog(eventOverviewUser: IEventOverviewUserDto): Promise<void> {\n    if(!this.event) return;\n    const modifiedAttendanceData = await this.customDialogService.showManageAttendanceDialog(eventOverviewUser);\n    if(modifiedAttendanceData) {\n      this.indicatorService.start();\n      try {\n        await this.eventsApi.editEventAttendance(this.event.id, eventOverviewUser.userId, modifiedAttendanceData);\n        this.toastService.success('pages.event-attendants.editAttendanceSuccess');\n        this.tableRefreshVersion++;\n      } catch(e) {\n        LogUtils.exception(e);\n        this.toastService.error('pages.event-attendants.editAttendanceError');\n      }\n      this.indicatorService.stop();\n    }\n  }\n\n  private formatDate(date: string | null): string {\n    return this.dateService.formatTime(date);\n  }\n\n  private selectedCourseGroupIdChanged(): void {\n    this.tableRefreshVersion++;\n  }\n\n  private selectedCourseIdChanged(): void {\n    this.tableRefreshVersion++;\n  }\n\n  private async createPdf(): Promise<void> {\n    if(!this.eventId || !this.tenantId) return;\n\n    const { rows } = await this.eventsApi.getGroupEventOverview(this.tenantId, this.eventId, { ...this.filter, limit: 500 });\n    const doc = new jsPDF({ format: 'a4', orientation: 'landscape', unit: 'mm' });\n    autoTable(doc, {\n      head: [[\n        this.i18n.tr('globals.name'),\n        this.i18n.tr('pages.event-attendants.status'),\n        this.i18n.tr('pages.event-attendants.attendanceInPercent'),\n      ]],\n      body: [\n        ...rows.map(entry => ([\n          entry.nickname ?? this.i18n.tr('globals.empty'),\n          entry.attended ? this.i18n.tr('pages.event-attendants.attended') : '',\n          entry.attendedPercentage ? `${Math.min(entry.attendedPercentage, 100)}%` : '0%'\n        ])),\n      ],\n    });\n    doc.output('dataurlnewwindow', { filename: 'attendee-list' });\n  }\n}\n","\nimport { autoinject } from 'aurelia-framework';\nimport { Router } from 'aurelia-router';\nimport { StoreService } from 'common/aurelia-services/StoreService';\nimport { EventType } from 'common/dto/course/content/course.types';\nimport { ColumnSortDirection, FilterOperationType } from 'common/dto/filter/filter.enum';\nimport { IFilterDto } from 'common/dto/filter/filter.interface';\nimport { IEventDto, IEventFilterDto } from 'common/dto/tenant/event/tenant.event.interface';\nimport { DateService } from '../../../services/DateService';\nimport { IState } from '../../../store/state';\nimport { FilterUtils } from '../../../utils/FilterUtils';\nimport { EventsApiService } from './../../../services/api/EventsApiService';\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, prepareServersideRangeFiltering, VirtualFilterField } from './../../elements/custom-table/custom-table-helpers';\nimport { IColumnDefinition } from './../../elements/custom-table/custom-table-interfaces';\n\n@autoinject()\nexport class TenantGroupEventsPage {\n  private courseGroupName: string = '';\n  private tenantId: number | null = null;\n  private courseGroupId: number | null = null;\n  private tableRefreshVersion = 0;\n  private hasEvents = false;\n  private filter: IFilterDto<IEventFilterDto<string>> = {\n    offset: 0,\n    limit: 10,\n    filter: [],\n    order: [{\n      field: 'plannedDateFrom',\n      dir: ColumnSortDirection.ASC,\n    }],\n  };\n\n  private tableColumns: Array<IColumnDefinition<CustomTableCell<IEventDto<string>> | ActionsCell<IEventDto<string>>>> = [\n    {\n      id: 'title',\n      nameTk: 'globals.name',\n      cellViewModel: CustomTableCell,\n      cellOptions: {\n        transformer: event => event.title,\n      },\n      prepareSorting: createPrepareServersideSortingFunction(() => this.filter, 'title'),\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: v => prepareServersideFiltering(this.filter, 'title', v),\n      },\n    },\n    {\n      id: 'plannedDate',\n      nameTk: 'pages.group-events.plannedDate',\n      cellViewModel: CustomTableCell,\n      cellOptions: {\n        transformer: event => this.dateService.formatDateWithTimespan(event.plannedDateFrom, event.plannedDateTo),\n      },\n      prepareSorting: createPrepareServersideSortingFunction(() => this.filter, 'plannedDateTo'),\n      filter: {\n        placeholderTk: 'globals.filter',\n        daterange: true,\n        prepare: v => prepareServersideRangeFiltering(this.filter, 'plannedDateTo', v),\n      },\n    },\n    {\n      id: 'actualDate',\n      nameTk: 'pages.group-events.actualDate',\n      cellViewModel: CustomTableCell,\n      cellOptions: {\n        transformer: event => event.actualDateFrom && event.actualDateTo ? this.dateService.formatDateWithTimespan(event.actualDateFrom, event.actualDateTo) : '',\n      },\n      prepareSorting: createPrepareServersideSortingFunction(() => this.filter, 'actualDateTo'),\n      filter: {\n        placeholderTk: 'globals.filter',\n        daterange: true,\n        prepare: v => prepareServersideRangeFiltering(this.filter, 'actualDateTo', v),\n      },\n    },\n    {\n      id: 'type',\n      nameTk: 'globals.type',\n      cellViewModel: CustomTableCell,\n      cellOptions: { tk: e => `globals.eventTypes.${e.type}` },\n      filter: {\n        placeholderTk: 'globals.filter',\n        prepare: v => prepareServersideFiltering(this.filter, 'type', v, FilterOperationType.Eq),\n        options: Object.values(EventType).map(eT => ({ keyTk: `globals.eventTypes.${eT}`, value: eT }))\n      }\n    },\n    {\n      id: 'actions',\n      nameTk: '',\n      cellViewModel: ActionsCell,\n      shrink: true,\n      cellOptions: {\n        entries: [\n          {\n            labelTk: 'globals.manageAttendees',\n            clickCallback: lecture => { this.router.navigateToRoute('event-attendants/id', { eventId: lecture.id }); }\n          },\n        ],\n      }\n    },\n  ];\n\n  constructor(\n    private eventsApi: EventsApiService,\n    private router: Router,\n    private dateService: DateService,\n    private storeService: StoreService<IState>,\n  ) { }\n\n  protected async activate(params: Record<string, string>): Promise<void> {\n    this.courseGroupId = params.courseGroupId ? parseInt(params.courseGroupId) : null;\n    this.storeService.subscribeToDetailedChanges(this, [\n      state => state.currentRole?.tenantId ?? null,\n    ], (_state, tenantId) => {\n      this.tenantId = tenantId;\n      this.updateHasEvents();\n    });\n  }\n\n  protected deactivate(): void {\n    this.storeService.disposeAllSubscriptions(this);\n  }\n\n  private async fetchTableData(limit: number, offset: number): Promise<{ total: number; data: Array<IEventDto<string>> }> {\n    if(!this.tenantId || !this.courseGroupId) return { total: 0, data: [] };\n    this.filter.limit = limit;\n    this.filter.offset = offset;\n    this.filter = FilterUtils.removeDuplicateFilterFields(\n      this.filter,\n      {\n        field: 'courseGroupId',\n        type: FilterOperationType.Eq,\n        value: this.courseGroupId\n      }\n    );\n\n    const events = await this.eventsApi.getEvents(this.tenantId, this.filter);\n    if(events.count > 0) {\n      this.courseGroupName = events.rows[0].courseGroups.find(courseGroup => courseGroup.id === this.courseGroupId)?.name || '';\n    }\n    return { total: events.count, data: events.rows };\n  }\n\n  private async updateHasEvents(): Promise<void> {\n    if(!this.tenantId || !this.courseGroupId) return;\n\n    const event = await this.eventsApi.getEvents(this.tenantId, {\n      limit: 1,\n      filter: [\n        {\n          field: 'courseGroupId' as VirtualFilterField,\n          type: FilterOperationType.Eq,\n          value: this.courseGroupId\n        }\n      ],\n    });\n    this.hasEvents = event.count > 0;\n  }\n}\n","import { autoinject, computedFrom } from 'aurelia-framework';\nimport { Router } from 'aurelia-router';\nimport { StoreService } from 'common/aurelia-services/StoreService';\nimport { ICourseGroupResponseDto, IUpdateCourseGroupDto } from 'common/dto/course/course.group.interface';\nimport { ColumnSortDirection, FilterOperationType } from 'common/dto/filter/filter.enum';\nimport { IFilterDto } from 'common/dto/filter/filter.interface';\nimport { ErrorType } from 'common/enum/errortype.enum';\nimport { ActiveOrInactive } from 'common/enum/status.enum';\nimport { StringUtils } from 'common/utils/StringUtils';\nimport { CustomDialogService } from '../../../services/CustomDialogService';\nimport { DateService } from '../../../services/DateService';\nimport { StudentService } from '../../../services/StudentService';\nimport { ToastService } from '../../../services/ToastService';\nimport { StudentsApiService } from '../../../services/api/StudentsApiService';\nimport { TenantApiService } from '../../../services/api/TenantApiService';\nimport { IState } from '../../../store/state';\nimport { ActionsCell } from '../../elements/custom-table/actions-cell/actions-cell';\nimport { CustomTableCell } from '../../elements/custom-table/custom-table-cell/custom-table-cell';\nimport {\n  VirtualFilterField,\n  createPrepareServersideSortingFunction,\n  deepPropertyString,\n  prepareServersideFiltering,\n  prepareServersideRangeFiltering\n} from '../../elements/custom-table/custom-table-helpers';\nimport { IColumnDefinition } from '../../elements/custom-table/custom-table-interfaces';\n\n@autoinject()\nexport class TenantGroupListPage {\n  private tableRefreshVersion = 0;\n  private selectedCourseGroups: ICourseGroupResponseDto<string>[] = [];\n  private showEvents: boolean = false;\n\n  private filter: IFilterDto<ICourseGroupResponseDto<string>> = {\n    offset: 0,\n    limit: 10,\n    order: [\n      {\n        field: 'name',\n        dir: ColumnSortDirection.ASC\n      }\n    ],\n    filter: [],\n  };\n\n  @computedFrom('showEvents')\n  private get tableColumns(): Array<IColumnDefinition<CustomTableCell<ICourseGroupResponseDto<string>> | ActionsCell<ICourseGroupResponseDto<string>>>> {\n    return [\n      {\n        id: 'course',\n        nameTk: 'globals.course',\n        cellViewModel: CustomTableCell,\n        prepareSorting: createPrepareServersideSortingFunction(this.filter, 'courseTitle' as VirtualFilterField),\n        cellOptions: {\n          transformer: deepPropertyString('course.title'),\n        },\n        filter: {\n          placeholderTk: 'globals.filter',\n          prepare: v => prepareServersideFiltering(this.filter, 'courseTitle' as VirtualFilterField, v, FilterOperationType.Like)\n        }\n      },\n      {\n        id: 'name',\n        nameTk: 'pages.tenantgrouplist.groupName',\n        cellViewModel: CustomTableCell,\n        cellOptions: {\n          transformer: (e: ICourseGroupResponseDto<string>) => e.name\n        },\n        prepareSorting: createPrepareServersideSortingFunction(this.filter, 'name'),\n        filter: {\n          placeholderTk: 'globals.filter',\n          prepare: v => prepareServersideFiltering(this.filter, 'name', v, FilterOperationType.Like)\n        }\n      },\n      {\n        id: 'internalNote',\n        nameTk: 'pages.groups.internalNote',\n        cellViewModel: CustomTableCell,\n        cellOptions: {\n          transformer: (e: ICourseGroupResponseDto<string>) => e.description ? StringUtils.truncateWithEllipsis(e.description, 20) : ''\n        },\n        prepareSorting: createPrepareServersideSortingFunction(this.filter, 'description'),\n        filter: {\n          placeholderTk: 'globals.filter',\n          prepare: v => prepareServersideFiltering(this.filter, 'description', v, FilterOperationType.Like)\n        }\n      },\n      {\n        id: 'startDate',\n        nameTk: 'pages.groups.startDate',\n        cellViewModel: CustomTableCell,\n        cellOptions: {\n          transformer: (e: ICourseGroupResponseDto<string>) => this.dateService.formatDate(e.from)\n        },\n        prepareSorting: createPrepareServersideSortingFunction(this.filter, 'from'),\n        filter: {\n          placeholderTk: 'globals.filter',\n          daterange: true,\n          prepare: v => prepareServersideRangeFiltering(this.filter, 'from', v),\n        },\n        wrap: true\n      },\n      {\n        id: 'endDate',\n        nameTk: 'pages.groups.endDate',\n        cellViewModel: CustomTableCell,\n        cellOptions: {\n          transformer: e => this.dateService.formatDate(e.to)\n        },\n        prepareSorting: createPrepareServersideSortingFunction(this.filter, 'to'),\n        filter: {\n          placeholderTk: 'globals.filter',\n          daterange: true,\n          prepare: v => prepareServersideRangeFiltering(this.filter, 'to', v),\n        },\n        wrap: true\n      },\n      {\n        id: 'participantCount',\n        nameTk: 'pages.groups.participantCount',\n        cellViewModel: CustomTableCell,\n        cellOptions: {\n          transformer: (e: ICourseGroupResponseDto<string>) => `${e.participantCount}`\n        },\n      },\n      {\n        id: 'status',\n        nameTk: 'globals.status',\n        cellViewModel: CustomTableCell,\n        cellOptions: { tk: (e: ICourseGroupResponseDto<string>) => e.status === ActiveOrInactive.Active ? 'globals.active' : 'globals.inactive', spanClasses: 'tag' },\n        prepareSorting: createPrepareServersideSortingFunction(this.filter, 'status'),\n        filter: {\n          initialValue: ActiveOrInactive.Active,\n          placeholderTk: 'globals.filter',\n          prepare: v => prepareServersideFiltering(this.filter, 'status', v, FilterOperationType.Eq),\n          options: [\n            { keyTk: 'globals.active', value: ActiveOrInactive.Active },\n            { keyTk: 'globals.inactive', value: ActiveOrInactive.Inactive }\n          ]\n        }\n      },\n      {\n        id: 'actions',\n        nameTk: '',\n        cellViewModel: ActionsCell,\n        shrink: true,\n        cellOptions: {\n          entries: [\n            {\n              labelTk: 'pages.groups.addInvitationToCourseGroup',\n              icon: 'fe-user-plus',\n              clickCallback: (e: ICourseGroupResponseDto<string>) => { this.addInvitationToCourseGroup(e); }\n            },\n            ...(this.showEvents ? [\n              'divider' as const,\n              {\n                labelTk: 'pages.groups.showGroupEvents',\n                icon: 'fe fe-calendar',\n                clickCallback: (e: ICourseGroupResponseDto<string>) => { this.router.navigateToRoute('group-events/id', { courseGroupId: e.id }); }\n              },\n            ] : []),\n            'divider',\n            {\n              labelTk: 'pages.groups.showGroupMediaShares',\n              icon: 'fe fe-share',\n              clickCallback: (e: ICourseGroupResponseDto<string>) => { this.router.navigateToRoute('group-shares/id', { courseGroupId: e.id }); }\n            },\n            'divider',\n            {\n              labelTk: 'globals.edit',\n              icon: 'fe fe-edit',\n              clickCallback: (e: ICourseGroupResponseDto<string>) => { this.showEditCourseGroupDialog(e); }\n            },\n            'divider',\n            {\n              labelTk: 'globals.delete',\n              icon: 'fe-delete',\n              additionalClasses: 'text-danger',\n              clickCallback: (e: ICourseGroupResponseDto<string>) => { this.deleteCourseGroup(e.id); }\n            },\n          ]\n        }\n      }\n    ];\n  }\n\n  constructor(\n    private api: StudentsApiService,\n    private router: Router,\n    private studentService: StudentService,\n    private tenantApi: TenantApiService,\n    private customDialogService: CustomDialogService,\n    private dateService: DateService,\n    private toastService: ToastService,\n    private storeService: StoreService<IState>,\n  ) { }\n\n\n  protected attached(): void {\n    this.storeService.subscribeToDetailedChanges(this, [\n      state => state.currentTenant\n    ], (_, currentTenant) => {\n      this.showEvents = !!currentTenant?.showEvents;\n    });\n  }\n\n  protected detached(): void {\n    this.storeService.disposeAllSubscriptions(this);\n  }\n\n  private async fetchTableData(limit: number, offset: number): Promise<{ total: number; data: Array<ICourseGroupResponseDto<string>> }> {\n    this.filter.limit = limit;\n    this.filter.offset = offset;\n    const results = await this.api.getCourseGroups(this.filter);\n    return { data: results.rows, total: results.count };\n  }\n\n  private async addInvitationToCourseGroup(courseGroup: ICourseGroupResponseDto<string>): Promise<void> {\n    const dialogValueInvitations = await this.customDialogService.showAddInvitationToCourseGroupDialog({ courseId: courseGroup.course.id, courseGroupId: courseGroup.id });\n\n    if(!dialogValueInvitations?.length) return;\n\n    if(await this.studentService.changeCourseGroup(dialogValueInvitations, courseGroup)) {\n      this.tableRefreshVersion++;\n    }\n  }\n\n  private async createCourseGroup(): Promise<void> {\n    const availableCourses = await this.tenantApi.getAvailableRegularCourses();\n    if(await this.studentService.createCourseGroup(availableCourses)) {\n      this.tableRefreshVersion++;\n    }\n  }\n\n  private async deleteCourseGroup(id: number): Promise<void> {\n    try {\n      await this.api.deleteCourseGroup(id);\n      this.toastService.success('pages.groups.deleteCourseGroupSuccess');\n      this.tableRefreshVersion++;\n    } catch(e) {\n      if(e.message === ErrorType.CANNOT_DELETE_NONEMPTY_COURSE_GROUP) {\n        this.toastService.error('pages.groups.deleteCourseGroupContainsUsersError');\n      } else {\n        this.toastService.error('pages.groups.deleteCourseGroupError');\n      }\n    }\n  }\n\n  private async deleteSelectedCourseGroups(): Promise<void> {\n    for(const courseGroup of this.selectedCourseGroups) {\n      await this.deleteCourseGroup(courseGroup.id);\n    }\n  }\n\n  private async showEditCourseGroupDialog(courseGroup: ICourseGroupResponseDto<string>): Promise<void> {\n    const dialogValue = await this.customDialogService.showEditCourseGroupDialog(courseGroup);\n    if(!dialogValue) return;\n    try {\n      const dto: IUpdateCourseGroupDto<string> = {\n        name: dialogValue.name,\n        description: dialogValue.description,\n        from: dialogValue.from,\n        to: dialogValue.to,\n      };\n      await this.api.editCourseGroup(courseGroup.id, dto);\n      this.toastService.success('pages.groups.editCourseGroupSuccess');\n      this.tableRefreshVersion++;\n    } catch(e) {\n      if(e.message === ErrorType.COURSE_GROUP_IS_DUPLICATE) {\n        this.toastService.error('utils.validation.createCourseGroupDuplicateError');\n      } else {\n        this.toastService.error('pages.groups.editCourseGroupError');\n      }\n    }\n  }\n}\n","import { autoinject } from 'aurelia-framework';\nimport { ICourseGroupResponseDto } from 'common/dto/course/course.group.interface';\nimport { StudentsApiService } from '../../../services/api/StudentsApiService';\n\n@autoinject()\nexport class TenantGroupMediaSharePage {\n  private tableRefreshVersion: number = 0;\n  private courseGroupId: number | null = null;\n  private courseGroup: ICourseGroupResponseDto<string> | null = null;\n\n  constructor(\n    private studentsApiService: StudentsApiService,\n  ) { }\n\n  protected async activate(params: Record<string, string>): Promise<void> {\n    const courseGroupId = parseInt(params.courseGroupId);\n    this.courseGroup = await this.studentsApiService.getCourseGroup(courseGroupId);\n  }\n}\n"],"names":[],"sourceRoot":""}