@rolatech/angular-course 17.2.1 → 17.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/index.mjs +2 -1
- package/esm2022/lib/components/course-details-dialog/course-details-dialog.component.mjs +92 -0
- package/esm2022/lib/components/course-edit-dialog/course-edit-dialog.component.mjs +233 -0
- package/esm2022/lib/components/course-preview/course-preview.component.mjs +11 -0
- package/esm2022/lib/components/course-pricing-add-dialog/course-pricing-add-dialog.component.mjs +33 -0
- package/esm2022/lib/components/course-pricing-dialog/course-pricing-dialog.component.mjs +59 -0
- package/esm2022/lib/components/course-schedule-add-dialog/course-schedule-add-dialog.component.mjs +34 -0
- package/esm2022/lib/components/course-schedule-dialog/course-schedule-dialog.component.mjs +63 -0
- package/esm2022/lib/components/course-section-item/course-section-item.component.mjs +52 -0
- package/esm2022/lib/components/course-section-lecture-item/course-section-lecture-item.component.mjs +113 -0
- package/esm2022/lib/components/course-section-lecture-video-dialog/course-section-lecture-video-dialog.component.mjs +112 -0
- package/esm2022/lib/components/course-section-lecture-video-item/course-section-lecture-video-item.component.mjs +11 -0
- package/esm2022/lib/components/detail-item/detail-item.component.mjs +73 -0
- package/esm2022/lib/components/index.mjs +24 -0
- package/esm2022/lib/components/pricing-item/pricing-item.component.mjs +45 -0
- package/esm2022/lib/components/schedule-item/schedule-item.component.mjs +124 -0
- package/fesm2022/rolatech-angular-course.mjs +1027 -153
- package/fesm2022/rolatech-angular-course.mjs.map +1 -1
- package/index.d.ts +1 -0
- package/lib/components/course-details-dialog/course-details-dialog.component.d.ts +23 -0
- package/lib/components/course-edit-dialog/course-edit-dialog.component.d.ts +51 -0
- package/lib/components/course-preview/course-preview.component.d.ts +5 -0
- package/lib/components/course-pricing-add-dialog/course-pricing-add-dialog.component.d.ts +12 -0
- package/lib/components/course-pricing-dialog/course-pricing-dialog.component.d.ts +19 -0
- package/lib/components/course-schedule-add-dialog/course-schedule-add-dialog.component.d.ts +12 -0
- package/lib/components/course-schedule-dialog/course-schedule-dialog.component.d.ts +19 -0
- package/lib/components/course-section-item/course-section-item.component.d.ts +24 -0
- package/lib/components/course-section-lecture-item/course-section-lecture-item.component.d.ts +40 -0
- package/lib/components/course-section-lecture-video-dialog/course-section-lecture-video-dialog.component.d.ts +29 -0
- package/lib/components/course-section-lecture-video-item/course-section-lecture-video-item.component.d.ts +5 -0
- package/lib/components/detail-item/detail-item.component.d.ts +32 -0
- package/lib/components/index.d.ts +23 -0
- package/lib/components/pricing-item/pricing-item.component.d.ts +17 -0
- package/lib/components/schedule-item/schedule-item.component.d.ts +34 -0
- package/package.json +1 -1
|
@@ -1,20 +1,48 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, importProvidersFrom, makeEnvironmentProviders,
|
|
2
|
+
import { Injectable, importProvidersFrom, makeEnvironmentProviders, Component, input, inject, output, ViewEncapsulation, model, effect, PLATFORM_ID, ElementRef, Inject, viewChild } from '@angular/core';
|
|
3
|
+
import * as i6 from '@angular/forms';
|
|
3
4
|
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
|
|
4
|
-
import { CommonModule,
|
|
5
|
-
import * as i1 from '@angular/router';
|
|
5
|
+
import { CommonModule, NgClass, DatePipe, isPlatformBrowser, ViewportScroller } from '@angular/common';
|
|
6
|
+
import * as i1$3 from '@angular/router';
|
|
6
7
|
import { RouterModule, RouterLink, ActivatedRoute, Router } from '@angular/router';
|
|
7
|
-
import { BaseService } from '@rolatech/angular-services';
|
|
8
|
-
import { AngularCommonModule, DurationPipe } from '@rolatech/angular-common';
|
|
9
|
-
import { BaseComponent, AngularComponentsModule, MediaPreviewDialogComponent, AppContainerComponent } from '@rolatech/angular-components';
|
|
10
|
-
import { AuthService, AuthUserService } from '@rolatech/angular-auth';
|
|
11
|
-
import { CommentsComponent } from '@rolatech/angular-comment';
|
|
8
|
+
import { BaseService, DialogService } from '@rolatech/angular-services';
|
|
12
9
|
import * as i2 from '@angular/material/icon';
|
|
13
10
|
import { MatIconModule } from '@angular/material/icon';
|
|
14
|
-
import
|
|
15
|
-
import
|
|
11
|
+
import * as i1$2 from '@angular/material/dialog';
|
|
12
|
+
import { MatDialog, MAT_DIALOG_DATA, MatDialogClose } from '@angular/material/dialog';
|
|
13
|
+
import { MediaPreviewDialogComponent, AngularComponentsModule, MediaListComponent, MediaListItemComponent, BaseComponent, AppContainerComponent } from '@rolatech/angular-components';
|
|
14
|
+
import * as i1 from '@angular/material/expansion';
|
|
16
15
|
import { MatExpansionModule } from '@angular/material/expansion';
|
|
16
|
+
import * as i3$2 from '@angular/material/checkbox';
|
|
17
17
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
18
|
+
import { DurationPipe, AngularCommonModule } from '@rolatech/angular-common';
|
|
19
|
+
import * as i3 from '@angular/material/button';
|
|
20
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
21
|
+
import * as i5$1 from '@angular/material/divider';
|
|
22
|
+
import { MatDividerModule } from '@angular/material/divider';
|
|
23
|
+
import * as i7$1 from '@angular/material/stepper';
|
|
24
|
+
import { MatStepperModule, MatStepper } from '@angular/material/stepper';
|
|
25
|
+
import { MomentDateAdapter } from '@angular/material-moment-adapter';
|
|
26
|
+
import * as i7 from '@angular/material/core';
|
|
27
|
+
import { DateAdapter, MAT_DATE_LOCALE, MAT_DATE_FORMATS, MatOptionModule } from '@angular/material/core';
|
|
28
|
+
import moment from 'moment';
|
|
29
|
+
import * as i6$1 from '@angular/material/select';
|
|
30
|
+
import { MatSelectModule } from '@angular/material/select';
|
|
31
|
+
import * as i5 from '@angular/material/datepicker';
|
|
32
|
+
import { MatDatepickerModule } from '@angular/material/datepicker';
|
|
33
|
+
import * as i3$1 from '@angular/cdk/text-field';
|
|
34
|
+
import { TextFieldModule } from '@angular/cdk/text-field';
|
|
35
|
+
import * as i2$1 from '@angular/material/input';
|
|
36
|
+
import { MatInputModule } from '@angular/material/input';
|
|
37
|
+
import * as i1$1 from '@angular/material/form-field';
|
|
38
|
+
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
39
|
+
import * as i3$3 from '@angular/material/snack-bar';
|
|
40
|
+
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
41
|
+
import * as i4 from '@angular/material/progress-bar';
|
|
42
|
+
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
43
|
+
import { first, remove, findLastIndex } from 'lodash';
|
|
44
|
+
import { AuthService, AuthUserService } from '@rolatech/angular-auth';
|
|
45
|
+
import { CommentsComponent } from '@rolatech/angular-comment';
|
|
18
46
|
|
|
19
47
|
var CourseStatus;
|
|
20
48
|
(function (CourseStatus) {
|
|
@@ -507,84 +535,68 @@ function provideAngulaCourse() {
|
|
|
507
535
|
return makeEnvironmentProviders(providers);
|
|
508
536
|
}
|
|
509
537
|
|
|
510
|
-
class
|
|
538
|
+
class CoursePreviewComponent {
|
|
539
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CoursePreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
540
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.0", type: CoursePreviewComponent, isStandalone: true, selector: "rolatech-course-preview", ngImport: i0, template: "<p>course-preview works!</p>\n", styles: [""] }); }
|
|
541
|
+
}
|
|
542
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CoursePreviewComponent, decorators: [{
|
|
543
|
+
type: Component,
|
|
544
|
+
args: [{ selector: 'rolatech-course-preview', standalone: true, imports: [], template: "<p>course-preview works!</p>\n" }]
|
|
545
|
+
}] });
|
|
546
|
+
|
|
547
|
+
class CourseInfoComponent {
|
|
511
548
|
constructor() {
|
|
512
549
|
this.course = input.required();
|
|
513
|
-
this.
|
|
550
|
+
this.instructor = input();
|
|
551
|
+
this.username = input();
|
|
514
552
|
}
|
|
515
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type:
|
|
516
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type:
|
|
553
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseInfoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
554
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseInfoComponent, isStandalone: true, selector: "rolatech-course-info", inputs: { course: { classPropertyName: "course", publicName: "course", isSignal: true, isRequired: true, transformFunction: null }, instructor: { classPropertyName: "instructor", publicName: "instructor", isSignal: true, isRequired: false, transformFunction: null }, username: { classPropertyName: "username", publicName: "username", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div>\n <div>\n <div class=\"text-2xl font-medium\">{{ course().name }}</div>\n @if (course().type && course().type.toString() !== 'ONLINE') {\n <div class=\"flex items-center pt-2\">\n <mat-icon>place</mat-icon>\n <span class=\"text-sm opacity-75\">{{ course().classroom.address }}</span>\n </div>\n }\n <div class=\"py-3 text-black-light flex justify-between\">\n <div>\n <div class=\"mb-1 flex items-center\">\n <span class=\"font-medium\">\u4E3B\u8BB2\u6559\u5E08: </span>\n <a class=\"ml-2 underline text-orange-600 text-[0.9rem]\" [routerLink]=\"['../../instructors/', '@' + username()]\">{{\n instructor()\n }}</a>\n </div>\n <span class=\"text-sm opacity-75\">\u6700\u540E\u7F16\u8F91: {{ course().updatedAt }} </span>\n </div>\n </div>\n </div>\n <!-- \u63CF\u8FF0 -->\n <div class=\"mb-3\">\n {{ course().description }}\n </div>\n</div>\n", styles: ["mat-icon{transform:scale(.8)}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] }); }
|
|
517
555
|
}
|
|
518
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type:
|
|
556
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseInfoComponent, decorators: [{
|
|
519
557
|
type: Component,
|
|
520
|
-
args: [{ selector: 'rolatech-course-
|
|
558
|
+
args: [{ selector: 'rolatech-course-info', standalone: true, imports: [MatIconModule, RouterLink], template: "<div>\n <div>\n <div class=\"text-2xl font-medium\">{{ course().name }}</div>\n @if (course().type && course().type.toString() !== 'ONLINE') {\n <div class=\"flex items-center pt-2\">\n <mat-icon>place</mat-icon>\n <span class=\"text-sm opacity-75\">{{ course().classroom.address }}</span>\n </div>\n }\n <div class=\"py-3 text-black-light flex justify-between\">\n <div>\n <div class=\"mb-1 flex items-center\">\n <span class=\"font-medium\">\u4E3B\u8BB2\u6559\u5E08: </span>\n <a class=\"ml-2 underline text-orange-600 text-[0.9rem]\" [routerLink]=\"['../../instructors/', '@' + username()]\">{{\n instructor()\n }}</a>\n </div>\n <span class=\"text-sm opacity-75\">\u6700\u540E\u7F16\u8F91: {{ course().updatedAt }} </span>\n </div>\n </div>\n </div>\n <!-- \u63CF\u8FF0 -->\n <div class=\"mb-3\">\n {{ course().description }}\n </div>\n</div>\n", styles: ["mat-icon{transform:scale(.8)}\n"] }]
|
|
521
559
|
}] });
|
|
522
560
|
|
|
523
|
-
class
|
|
561
|
+
class CourseMediaComponent {
|
|
524
562
|
constructor() {
|
|
525
|
-
|
|
526
|
-
this.
|
|
527
|
-
this.
|
|
528
|
-
this.
|
|
529
|
-
this.categories = [];
|
|
530
|
-
this.loading = false;
|
|
531
|
-
}
|
|
532
|
-
ngOnInit() {
|
|
533
|
-
this.findAllCategories();
|
|
534
|
-
this.route.paramMap.subscribe((params) => {
|
|
535
|
-
const id = params.get('id');
|
|
536
|
-
this.findCategoryById(id);
|
|
537
|
-
this.findCoursesByCategoryId(id);
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
|
-
findAllCategories() {
|
|
541
|
-
this.categoryService.find({}).subscribe({
|
|
542
|
-
next: (res) => {
|
|
543
|
-
this.categories = res.data;
|
|
544
|
-
},
|
|
545
|
-
});
|
|
546
|
-
}
|
|
547
|
-
findCategoryById(id) {
|
|
548
|
-
this.categoryService.get(id).subscribe({
|
|
549
|
-
next: (res) => {
|
|
550
|
-
this.category = res.data;
|
|
551
|
-
},
|
|
552
|
-
});
|
|
553
|
-
}
|
|
554
|
-
findAllCourses() {
|
|
555
|
-
this.courseService.find({}).subscribe({
|
|
556
|
-
next: (res) => {
|
|
557
|
-
this.courses = res.data;
|
|
558
|
-
},
|
|
559
|
-
});
|
|
563
|
+
this.dialog = inject(MatDialog);
|
|
564
|
+
this.media = input([]);
|
|
565
|
+
this.min = input(false);
|
|
566
|
+
this.mediaIndex = 0;
|
|
560
567
|
}
|
|
561
|
-
|
|
562
|
-
this.
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
this.
|
|
570
|
-
|
|
571
|
-
error: (error) => {
|
|
572
|
-
this.loading = false;
|
|
568
|
+
onImageClick(i) {
|
|
569
|
+
const dialogRef = this.dialog.open(MediaPreviewDialogComponent, {
|
|
570
|
+
maxWidth: '80vw',
|
|
571
|
+
maxHeight: '80vh',
|
|
572
|
+
height: '80%',
|
|
573
|
+
width: '80%',
|
|
574
|
+
panelClass: 'full-screen-modal',
|
|
575
|
+
data: {
|
|
576
|
+
media: this.media,
|
|
577
|
+
selected: i,
|
|
573
578
|
},
|
|
574
579
|
});
|
|
580
|
+
dialogRef.afterClosed().subscribe((result) => { });
|
|
575
581
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
582
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseMediaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
583
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseMediaComponent, isStandalone: true, selector: "rolatech-course-media", inputs: { media: { classPropertyName: "media", publicName: "media", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (media()) {\n @if (min()) {\n <div class=\"sm:w-80 object-cover aspect-video bg-gray-200 rounded-lg\">\n @if (media()) {\n <img class=\"aspect-video object-cover w-full rounded-lg\" [src]=\"media()[0].url\" />\n }\n </div>\n } @else {\n <div>\n <div class=\"object-cover aspect-video bg-gray-200\">\n <img class=\"aspect-video object-cover w-full rounded-md\" [src]=\"media()[mediaIndex].url\" />\n </div>\n @for (item of media(); track $index) {\n <div\n class=\"inline-flex flex-row mt-3 mr-3 cursor-pointer rounded-md\"\n (click)=\"mediaIndex = $index\"\n [ngClass]=\"mediaIndex === $index ? '' : 'opacity-30'\"\n >\n <img class=\"rounded-md aspect-video object-cover w-32\" [src]=\"item.url\" />\n </div>\n }\n </div>\n }\n}\n", styles: [""], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
|
|
584
|
+
}
|
|
585
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseMediaComponent, decorators: [{
|
|
586
|
+
type: Component,
|
|
587
|
+
args: [{ selector: 'rolatech-course-media', standalone: true, imports: [NgClass], template: "@if (media()) {\n @if (min()) {\n <div class=\"sm:w-80 object-cover aspect-video bg-gray-200 rounded-lg\">\n @if (media()) {\n <img class=\"aspect-video object-cover w-full rounded-lg\" [src]=\"media()[0].url\" />\n }\n </div>\n } @else {\n <div>\n <div class=\"object-cover aspect-video bg-gray-200\">\n <img class=\"aspect-video object-cover w-full rounded-md\" [src]=\"media()[mediaIndex].url\" />\n </div>\n @for (item of media(); track $index) {\n <div\n class=\"inline-flex flex-row mt-3 mr-3 cursor-pointer rounded-md\"\n (click)=\"mediaIndex = $index\"\n [ngClass]=\"mediaIndex === $index ? '' : 'opacity-30'\"\n >\n <img class=\"rounded-md aspect-video object-cover w-32\" [src]=\"item.url\" />\n </div>\n }\n </div>\n }\n}\n" }]
|
|
588
|
+
}] });
|
|
589
|
+
|
|
590
|
+
class CoursePricingComponent {
|
|
591
|
+
constructor() {
|
|
592
|
+
this.pricing = input([]);
|
|
581
593
|
}
|
|
582
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type:
|
|
583
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type:
|
|
594
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CoursePricingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
595
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CoursePricingComponent, isStandalone: true, selector: "rolatech-course-pricing", inputs: { pricing: { classPropertyName: "pricing", publicName: "pricing", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (pricing()) {\n <div class=\"py-3\">\n <div class=\"text-lg font-medium py-2\">\u4EF7\u683C</div>\n @for (item of pricing(); track $index) {\n <div>\n <span>{{ item.min }} \u81F3 {{ item.max }}\u4EBA</span>\n <span class=\"ml-3\">{{ item.total / 100 }}\u5143</span>\n </div>\n }\n </div>\n}\n", styles: [""] }); }
|
|
584
596
|
}
|
|
585
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type:
|
|
597
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CoursePricingComponent, decorators: [{
|
|
586
598
|
type: Component,
|
|
587
|
-
args: [{
|
|
599
|
+
args: [{ selector: 'rolatech-course-pricing', standalone: true, template: "@if (pricing()) {\n <div class=\"py-3\">\n <div class=\"text-lg font-medium py-2\">\u4EF7\u683C</div>\n @for (item of pricing(); track $index) {\n <div>\n <span>{{ item.min }} \u81F3 {{ item.max }}\u4EBA</span>\n <span class=\"ml-3\">{{ item.total / 100 }}\u5143</span>\n </div>\n }\n </div>\n}\n" }]
|
|
588
600
|
}] });
|
|
589
601
|
|
|
590
602
|
class CourseActionComponent {
|
|
@@ -612,50 +624,812 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImpor
|
|
|
612
624
|
args: [{ selector: 'rolatech-course-action', standalone: true, template: "<div class=\"flex flex-col\">\n <!-- <a class=\"p-3 bg-orange-600 text-white text-center mt-3\" target=\"_blank\" (click)=\"onCart(course)\">\u52A0\u5165\u8D2D\u7269\u8F66</a> -->\n <a\n class=\"p-3 bg-orange-600 text-white text-center mt-3 cursor-pointer rounded-md hover:bg-orange-700\"\n target=\"_blank\"\n (click)=\"onCheckout(course())\"\n >\u7ACB\u5373\u8D2D\u4E70</a\n >\n <a\n class=\"p-3 border border-black text-center mt-3 cursor-pointer rounded-md hover:bg-gray-100\"\n target=\"_blank\"\n (click)=\"onWish(course())\"\n >{{ inWishList() ? '\u79FB\u9664\u6536\u85CF' : '\u52A0\u5165\u6536\u85CF' }}</a\n >\n</div>\n" }]
|
|
613
625
|
}] });
|
|
614
626
|
|
|
615
|
-
class
|
|
627
|
+
class CourseScheduleComponent {
|
|
616
628
|
constructor() {
|
|
617
|
-
this.
|
|
618
|
-
|
|
619
|
-
|
|
629
|
+
this.schedule = input([]);
|
|
630
|
+
}
|
|
631
|
+
ngOnInit() {
|
|
632
|
+
// this.formatSchedule();
|
|
633
|
+
}
|
|
634
|
+
formatSchedule() { }
|
|
635
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseScheduleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
636
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseScheduleComponent, isStandalone: true, selector: "rolatech-course-schedule", inputs: { schedule: { classPropertyName: "schedule", publicName: "schedule", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<!-- \u8BFE\u8868 -->\n@if (schedule()) {\n <div class=\"py-3\" id=\"schedule\">\n <div class=\"text-xl font-medium py-2\">\u8BFE\u8868</div>\n @for (item of schedule(); track $index) {\n <mat-expansion-panel #panel [class.mat-elevation-z0]=\"true\" hideToggle [expanded]=\"$index === 0\">\n <mat-expansion-panel-header class=\"bg-red\">\n <mat-panel-title>\n <span class=\"text-[1rem]\">{{ item.title }}</span>\n </mat-panel-title>\n <mat-icon\n class=\"toggle-icon\"\n style=\"transition-duration:.5s;transform: {{ panel.expanded ? 'rotate(180deg)' : 'rotate(0deg)' }};\"\n >expand_more</mat-icon\n >\n </mat-expansion-panel-header>\n <div class=\"bg-white\">\n <div class=\"text-gray-600 font-thin pt-2\">\n <span>{{ item.startAt }} - {{ item.endAt }}</span>\n </div>\n <div class=\"py-3\">\n <div>{{ item.content }}</div>\n </div>\n </div>\n </mat-expansion-panel>\n }\n </div>\n}\n", styles: ["mat-expansion-panel{margin:0!important}.mat-expansion-panel-header{padding:0 16px;background:#f3f4f6!important}.mat-expansion-panel .mat-expansion-panel-header:not([aria-disabled=true]):hover{background:#dee0e2}.mat-expansion-panel-header{height:56px!important}.mat-expansion-panel .mat-expansion-panel-header{margin-bottom:8px;height:44px!important;padding:0 12px!important}.mat-expansion-panel-header .mat-expanded{height:56px!important}mat-expansion-panel .mat-expansion-panel-body{padding:0 8px 8px 4px!important}\n"], dependencies: [{ kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i1.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
|
|
637
|
+
}
|
|
638
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseScheduleComponent, decorators: [{
|
|
639
|
+
type: Component,
|
|
640
|
+
args: [{ selector: 'rolatech-course-schedule', standalone: true, imports: [MatExpansionModule, MatIconModule], template: "<!-- \u8BFE\u8868 -->\n@if (schedule()) {\n <div class=\"py-3\" id=\"schedule\">\n <div class=\"text-xl font-medium py-2\">\u8BFE\u8868</div>\n @for (item of schedule(); track $index) {\n <mat-expansion-panel #panel [class.mat-elevation-z0]=\"true\" hideToggle [expanded]=\"$index === 0\">\n <mat-expansion-panel-header class=\"bg-red\">\n <mat-panel-title>\n <span class=\"text-[1rem]\">{{ item.title }}</span>\n </mat-panel-title>\n <mat-icon\n class=\"toggle-icon\"\n style=\"transition-duration:.5s;transform: {{ panel.expanded ? 'rotate(180deg)' : 'rotate(0deg)' }};\"\n >expand_more</mat-icon\n >\n </mat-expansion-panel-header>\n <div class=\"bg-white\">\n <div class=\"text-gray-600 font-thin pt-2\">\n <span>{{ item.startAt }} - {{ item.endAt }}</span>\n </div>\n <div class=\"py-3\">\n <div>{{ item.content }}</div>\n </div>\n </div>\n </mat-expansion-panel>\n }\n </div>\n}\n", styles: ["mat-expansion-panel{margin:0!important}.mat-expansion-panel-header{padding:0 16px;background:#f3f4f6!important}.mat-expansion-panel .mat-expansion-panel-header:not([aria-disabled=true]):hover{background:#dee0e2}.mat-expansion-panel-header{height:56px!important}.mat-expansion-panel .mat-expansion-panel-header{margin-bottom:8px;height:44px!important;padding:0 12px!important}.mat-expansion-panel-header .mat-expanded{height:56px!important}mat-expansion-panel .mat-expansion-panel-body{padding:0 8px 8px 4px!important}\n"] }]
|
|
641
|
+
}] });
|
|
642
|
+
|
|
643
|
+
class CourseSectionsComponent {
|
|
644
|
+
constructor() {
|
|
645
|
+
this.purchased = input(false);
|
|
646
|
+
this.sections = input([]);
|
|
647
|
+
this.section = output();
|
|
648
|
+
this.checkout = output();
|
|
649
|
+
this.panelOpenState = false;
|
|
650
|
+
}
|
|
651
|
+
onSection(section, lecture) {
|
|
652
|
+
this.section.emit({ section, lecture });
|
|
653
|
+
}
|
|
654
|
+
onCheckout(section, lecture) {
|
|
655
|
+
this.checkout.emit({ section, lecture });
|
|
656
|
+
}
|
|
657
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseSectionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
658
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseSectionsComponent, isStandalone: true, selector: "rolatech-course-sections", inputs: { purchased: { classPropertyName: "purchased", publicName: "purchased", isSignal: true, isRequired: false, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { section: "section", checkout: "checkout" }, ngImport: i0, template: "@if (sections()) {\n <div id=\"sections()\">\n <div class=\"text-xl font-medium py-2\">\u8BFE\u7A0B\u5185\u5BB9</div>\n <mat-accordion multi>\n @for (item of sections(); track $index) {\n <mat-expansion-panel #panel [class.mat-elevation-z0]=\"true\" hideToggle [expanded]=\"$index === 0\">\n <mat-expansion-panel-header class=\"bg-red\">\n <mat-panel-title>\n <span class=\"text-[1rem]\">{{ item.title }}</span>\n </mat-panel-title>\n <mat-icon\n class=\"toggle-icon\"\n style=\"transition-duration:.5s;transform: {{ panel.expanded ? 'rotate(180deg)' : 'rotate(0deg)' }};\"\n >expand_more</mat-icon\n >\n </mat-expansion-panel-header>\n <div class=\"bg-white\">\n @for (lecture of item.lectures; track $index) {\n <div class=\"flex items-center justify-between py-1\">\n @if (lecture.item && lecture.type === 'VIDEO') {\n <div class=\"flex items-center gap-3\">\n <mat-icon>live_tv</mat-icon>\n <span class=\"text-md\"> {{ lecture.title }}</span>\n </div>\n <div>\n @if (purchased()) {\n <a\n class=\"text-sm mr-1 underline underline-offset-2 cursor-pointer text-orange-600\"\n (click)=\"onSection(item, lecture)\"\n >\u64AD\u653E</a\n >\n } @else {\n @if (lecture.item.canBePreviewed) {\n <a\n class=\"text-sm mr-1 underline underline-offset-2 cursor-pointer text-orange-600\"\n (click)=\"onSection(item, lecture)\"\n >\u8BD5\u770B</a\n >\n } @else {\n <a\n class=\"text-sm mr-1 underline underline-offset-2 cursor-pointer text-orange-600\"\n (click)=\"onCheckout(item, lecture)\"\n >\u8D2D\u4E70</a\n >\n }\n }\n\n <a class=\"text-gray-500 inline-block w-[60px] text-right\">{{ lecture.item.duration | duration }}</a>\n </div>\n }\n </div>\n }\n </div>\n </mat-expansion-panel>\n }\n </mat-accordion>\n </div>\n}\n", styles: ["mat-expansion-panel{margin:0!important}.mat-expansion-panel-header{padding:0 16px;background:#f3f4f6!important}.mat-expansion-panel .mat-expansion-panel-header:not([aria-disabled=true]):hover{background:#dee0e2}.mat-expansion-panel-header{height:56px!important}.mat-expansion-panel .mat-expansion-panel-header{margin-bottom:8px;height:44px!important;padding:0 12px!important}.mat-expansion-panel-header .mat-expanded{height:56px!important}mat-expansion-panel .mat-expansion-panel-body{padding:0 8px 8px 4px!important}mat-expansion-panel mat-icon{transform:scale(.9)}\n"], dependencies: [{ kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i1.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i1.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: DurationPipe, name: "duration" }, { kind: "ngmodule", type: MatCheckboxModule }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
659
|
+
}
|
|
660
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseSectionsComponent, decorators: [{
|
|
661
|
+
type: Component,
|
|
662
|
+
args: [{ selector: 'rolatech-course-sections', encapsulation: ViewEncapsulation.None, standalone: true, imports: [MatExpansionModule, MatIconModule, DurationPipe, MatCheckboxModule], template: "@if (sections()) {\n <div id=\"sections()\">\n <div class=\"text-xl font-medium py-2\">\u8BFE\u7A0B\u5185\u5BB9</div>\n <mat-accordion multi>\n @for (item of sections(); track $index) {\n <mat-expansion-panel #panel [class.mat-elevation-z0]=\"true\" hideToggle [expanded]=\"$index === 0\">\n <mat-expansion-panel-header class=\"bg-red\">\n <mat-panel-title>\n <span class=\"text-[1rem]\">{{ item.title }}</span>\n </mat-panel-title>\n <mat-icon\n class=\"toggle-icon\"\n style=\"transition-duration:.5s;transform: {{ panel.expanded ? 'rotate(180deg)' : 'rotate(0deg)' }};\"\n >expand_more</mat-icon\n >\n </mat-expansion-panel-header>\n <div class=\"bg-white\">\n @for (lecture of item.lectures; track $index) {\n <div class=\"flex items-center justify-between py-1\">\n @if (lecture.item && lecture.type === 'VIDEO') {\n <div class=\"flex items-center gap-3\">\n <mat-icon>live_tv</mat-icon>\n <span class=\"text-md\"> {{ lecture.title }}</span>\n </div>\n <div>\n @if (purchased()) {\n <a\n class=\"text-sm mr-1 underline underline-offset-2 cursor-pointer text-orange-600\"\n (click)=\"onSection(item, lecture)\"\n >\u64AD\u653E</a\n >\n } @else {\n @if (lecture.item.canBePreviewed) {\n <a\n class=\"text-sm mr-1 underline underline-offset-2 cursor-pointer text-orange-600\"\n (click)=\"onSection(item, lecture)\"\n >\u8BD5\u770B</a\n >\n } @else {\n <a\n class=\"text-sm mr-1 underline underline-offset-2 cursor-pointer text-orange-600\"\n (click)=\"onCheckout(item, lecture)\"\n >\u8D2D\u4E70</a\n >\n }\n }\n\n <a class=\"text-gray-500 inline-block w-[60px] text-right\">{{ lecture.item.duration | duration }}</a>\n </div>\n }\n </div>\n }\n </div>\n </mat-expansion-panel>\n }\n </mat-accordion>\n </div>\n}\n", styles: ["mat-expansion-panel{margin:0!important}.mat-expansion-panel-header{padding:0 16px;background:#f3f4f6!important}.mat-expansion-panel .mat-expansion-panel-header:not([aria-disabled=true]):hover{background:#dee0e2}.mat-expansion-panel-header{height:56px!important}.mat-expansion-panel .mat-expansion-panel-header{margin-bottom:8px;height:44px!important;padding:0 12px!important}.mat-expansion-panel-header .mat-expanded{height:56px!important}mat-expansion-panel .mat-expansion-panel-body{padding:0 8px 8px 4px!important}mat-expansion-panel mat-icon{transform:scale(.9)}\n"] }]
|
|
663
|
+
}] });
|
|
664
|
+
|
|
665
|
+
class CourseSectionItemComponent {
|
|
666
|
+
constructor() {
|
|
667
|
+
this.section = model.required();
|
|
668
|
+
this.actions = model();
|
|
669
|
+
this.hasUnsaved = model();
|
|
670
|
+
this.editId = model();
|
|
671
|
+
this.save = output();
|
|
672
|
+
this.cancel = output();
|
|
673
|
+
this.delete = output();
|
|
674
|
+
this.edit = output();
|
|
675
|
+
this.addLecture = output();
|
|
676
|
+
this.editing = false;
|
|
677
|
+
this.isExpand = false;
|
|
678
|
+
}
|
|
679
|
+
ngOnInit() { }
|
|
680
|
+
onSave(section) {
|
|
681
|
+
this.editing = false;
|
|
682
|
+
this.editId.set(null);
|
|
683
|
+
this.save.emit(section);
|
|
684
|
+
}
|
|
685
|
+
onCancel(section) {
|
|
686
|
+
this.editing = false;
|
|
687
|
+
this.editId.set(null);
|
|
688
|
+
this.cancel.emit(section);
|
|
689
|
+
}
|
|
690
|
+
onDelete(section) {
|
|
691
|
+
this.delete.emit(section);
|
|
692
|
+
}
|
|
693
|
+
onEdit(section) {
|
|
694
|
+
this.editId.set(null);
|
|
695
|
+
this.editing = true;
|
|
696
|
+
this.edit.emit(section);
|
|
697
|
+
}
|
|
698
|
+
onAddLecture(section) {
|
|
699
|
+
this.addLecture.emit(section);
|
|
700
|
+
}
|
|
701
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseSectionItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
702
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseSectionItemComponent, isStandalone: true, selector: "rolatech-course-section-item", inputs: { section: { classPropertyName: "section", publicName: "section", isSignal: true, isRequired: true, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, hasUnsaved: { classPropertyName: "hasUnsaved", publicName: "hasUnsaved", isSignal: true, isRequired: false, transformFunction: null }, editId: { classPropertyName: "editId", publicName: "editId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { section: "sectionChange", actions: "actionsChange", hasUnsaved: "hasUnsavedChange", editId: "editIdChange", save: "save", cancel: "cancel", delete: "delete", edit: "edit", addLecture: "addLecture" }, ngImport: i0, template: "<div class=\"flex flex-col grow\">\n @if (section().id !== editId()) {\n <div>\n <div class=\"flex justify-between items-center\">\n <div class=\"w-full flex gap-3 pl-3\">\n <span>{{ section().title }}</span>\n <mat-icon (click)=\"onEdit(section())\" class=\"cursor-pointer\">edit</mat-icon>\n <mat-icon class=\"cursor-pointer\" (click)=\"onDelete(section())\">delete</mat-icon>\n </div>\n <button mat-icon-button (click)=\"isExpand = !isExpand\">\n <mat-icon>{{ isExpand ? 'expand_less' : 'expand_more' }}</mat-icon>\n </button>\n </div>\n @if (isExpand) {\n <div>\n <ng-content></ng-content>\n </div>\n }\n </div>\n } @else {\n <div class=\"flex flex-col justify-between items-center\">\n <input\n type=\"text\"\n class=\"bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500\"\n placeholder=\"\u6807\u9898\"\n [(ngModel)]=\"section().title\"\n />\n <div class=\"w-full flex flex-row justify-end p-4 gap-3\">\n <button mat-button (click)=\"onCancel(section())\">\u53D6\u6D88</button>\n <button mat-flat-button color=\"primary\" (click)=\"onSave(section())\">\u4FDD\u5B58</button>\n </div>\n </div>\n }\n <!-- <mat-form-field appearance=\"fill\">\n <mat-label>\u63CF\u8FF0</mat-label>\n <input matInput placeholder=\"\u63CF\u8FF0\" [(ngModel)]=\"section.description\" />\n </mat-form-field> -->\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }] }); }
|
|
703
|
+
}
|
|
704
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseSectionItemComponent, decorators: [{
|
|
705
|
+
type: Component,
|
|
706
|
+
args: [{ selector: 'rolatech-course-section-item', standalone: true, imports: [MatIconModule, FormsModule, MatButtonModule], template: "<div class=\"flex flex-col grow\">\n @if (section().id !== editId()) {\n <div>\n <div class=\"flex justify-between items-center\">\n <div class=\"w-full flex gap-3 pl-3\">\n <span>{{ section().title }}</span>\n <mat-icon (click)=\"onEdit(section())\" class=\"cursor-pointer\">edit</mat-icon>\n <mat-icon class=\"cursor-pointer\" (click)=\"onDelete(section())\">delete</mat-icon>\n </div>\n <button mat-icon-button (click)=\"isExpand = !isExpand\">\n <mat-icon>{{ isExpand ? 'expand_less' : 'expand_more' }}</mat-icon>\n </button>\n </div>\n @if (isExpand) {\n <div>\n <ng-content></ng-content>\n </div>\n }\n </div>\n } @else {\n <div class=\"flex flex-col justify-between items-center\">\n <input\n type=\"text\"\n class=\"bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500\"\n placeholder=\"\u6807\u9898\"\n [(ngModel)]=\"section().title\"\n />\n <div class=\"w-full flex flex-row justify-end p-4 gap-3\">\n <button mat-button (click)=\"onCancel(section())\">\u53D6\u6D88</button>\n <button mat-flat-button color=\"primary\" (click)=\"onSave(section())\">\u4FDD\u5B58</button>\n </div>\n </div>\n }\n <!-- <mat-form-field appearance=\"fill\">\n <mat-label>\u63CF\u8FF0</mat-label>\n <input matInput placeholder=\"\u63CF\u8FF0\" [(ngModel)]=\"section.description\" />\n </mat-form-field> -->\n</div>\n" }]
|
|
707
|
+
}] });
|
|
708
|
+
|
|
709
|
+
const MY_FORMATS = {
|
|
710
|
+
parse: {
|
|
711
|
+
dateInput: 'YYYY-MM-DD',
|
|
712
|
+
},
|
|
713
|
+
display: {
|
|
714
|
+
dateInput: 'YYYY-MM-DD',
|
|
715
|
+
monthYearLabel: 'MMM YYYY',
|
|
716
|
+
dateA11yLabel: 'YYYY-MM-DD',
|
|
717
|
+
monthYearA11yLabel: 'MMMM YYYY',
|
|
718
|
+
},
|
|
719
|
+
};
|
|
720
|
+
class ScheduleItemComponent {
|
|
721
|
+
constructor() {
|
|
722
|
+
this.value = input();
|
|
723
|
+
this.actions = input(false);
|
|
724
|
+
this.shadow = input(false);
|
|
725
|
+
this.delete = output();
|
|
726
|
+
this.save = output();
|
|
727
|
+
this.date = ScheduleDate;
|
|
728
|
+
this.schedule = effect(() => {
|
|
729
|
+
this.schedule = this.value();
|
|
730
|
+
this.schedule.startDate = moment(this.schedule.startAt).format('YYYY-MM-DD');
|
|
731
|
+
this.schedule.startTime = moment(this.schedule.startAt).format('HH:mm');
|
|
732
|
+
this.schedule.endDate = moment(this.schedule.endAt).format('YYYY-MM-DD');
|
|
733
|
+
this.schedule.endTime = moment(this.schedule.endAt).format('HH:mm');
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
// constructor() {
|
|
737
|
+
// this.schedule = this.value();
|
|
738
|
+
// }
|
|
739
|
+
ngOnInit() {
|
|
740
|
+
// this.schedule = computed(() => {
|
|
741
|
+
// console.log(this.value());
|
|
742
|
+
// return this.value();
|
|
743
|
+
// })();
|
|
744
|
+
// this.schedule = this.value();
|
|
745
|
+
// this.schedule.startDate = moment(this.schedule.startAt).format('YYYY-MM-DD');
|
|
746
|
+
// this.schedule.startTime = moment(this.schedule.startAt).format('HH:mm');
|
|
747
|
+
// this.schedule.endDate = moment(this.schedule.endAt).format('YYYY-MM-DD');
|
|
748
|
+
// this.schedule.endTime = moment(this.schedule.endAt).format('HH:mm');
|
|
749
|
+
}
|
|
750
|
+
ngOnDestroy() {
|
|
751
|
+
const { startAt, endAt, startTime, startDate, endDate, endTime } = this.schedule;
|
|
752
|
+
this.schedule.startAt = this.schedule.startDate + ' ' + this.schedule.startTime;
|
|
753
|
+
this.schedule.endAt = this.schedule.endDate + ' ' + this.schedule.endTime;
|
|
754
|
+
delete this.schedule.startDate;
|
|
755
|
+
delete this.schedule.startTime;
|
|
756
|
+
delete this.schedule.endDate;
|
|
757
|
+
delete this.schedule.endTime;
|
|
758
|
+
}
|
|
759
|
+
startDateChanged(event) { }
|
|
760
|
+
startTimeChanged(event) { }
|
|
761
|
+
endDateChanged(event) { }
|
|
762
|
+
endTimeChanged(event) { }
|
|
763
|
+
onSave(schedule) {
|
|
764
|
+
this.format();
|
|
765
|
+
this.save.emit(schedule);
|
|
766
|
+
}
|
|
767
|
+
onDelete(schedule) {
|
|
768
|
+
this.delete.emit(schedule);
|
|
769
|
+
}
|
|
770
|
+
format() {
|
|
771
|
+
this.schedule.startAt = this.schedule.startDate + ' ' + this.schedule.startTime;
|
|
772
|
+
this.schedule.endAt = this.schedule.endDate + ' ' + this.schedule.endTime;
|
|
773
|
+
}
|
|
774
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: ScheduleItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
775
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: ScheduleItemComponent, isStandalone: true, selector: "rolatech-schedule-item", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, shadow: { classPropertyName: "shadow", publicName: "shadow", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { delete: "delete", save: "save" }, providers: [
|
|
776
|
+
{
|
|
777
|
+
provide: DateAdapter,
|
|
778
|
+
useClass: MomentDateAdapter,
|
|
779
|
+
deps: [MAT_DATE_LOCALE],
|
|
780
|
+
},
|
|
781
|
+
{ provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
|
|
782
|
+
DatePipe,
|
|
783
|
+
], ngImport: i0, template: "<div class=\"flex flex-col\" [ngClass]=\"{ shadow: shadow() }\">\n <mat-form-field appearance=\"fill\">\n <mat-label> \u6807\u9898 </mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"schedule.title\" name=\"title\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label> \u5185\u5BB9 </mat-label>\n <textarea\n matInput\n type=\"text\"\n [(ngModel)]=\"schedule.content\"\n name=\"content\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"3\"\n required\n ></textarea>\n </mat-form-field>\n <div class=\"flex flex-row gap-3\">\n <mat-form-field appearance=\"fill\">\n <mat-label>\u5F00\u59CB\u65E5\u671F</mat-label>\n <input\n matInput\n [matDatepicker]=\"picker\"\n (focus)=\"picker.open()\"\n name=\"startAt\"\n [(ngModel)]=\"schedule.startDate\"\n (ngModelChange)=\"startDateChanged($event)\"\n (dateInput)=\"schedule.startDate = $event.value.format('YYYY-MM-DD')\"\n readonly\n required\n />\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>\u5F00\u59CB\u65F6\u95F4</mat-label>\n <mat-select [(ngModel)]=\"schedule.startTime\" (selectionChange)=\"startTimeChanged($event)\" required readonly>\n @for (d of date; track d) {\n <mat-option [value]=\"d\">\n {{ d }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"flex flex-row gap-3\">\n <mat-form-field appearance=\"fill\">\n <mat-label>\u7ED3\u675F\u65E5\u671F</mat-label>\n <input\n matInput\n [matDatepicker]=\"picker2\"\n name=\"endAt\"\n (focus)=\"picker2.open()\"\n (ngModelChange)=\"endDateChanged($event)\"\n [(ngModel)]=\"schedule.endDate\"\n (dateInput)=\"schedule.endDate = $event.value.format('YYYY-MM-DD')\"\n readonly\n required\n />\n <mat-datepicker-toggle matIconSuffix [for]=\"picker2\"></mat-datepicker-toggle>\n <mat-datepicker #picker2></mat-datepicker>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>\u7ED3\u675F\u65F6\u95F4</mat-label>\n <mat-select [(ngModel)]=\"schedule.endTime\" (selectionChange)=\"endTimeChanged($event)\" required readonly>\n @for (d of date; track d) {\n <mat-option [value]=\"d\">\n {{ d }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n</div>\n@if (actions()) {\n <div class=\"flex flex-row justify-end p-4\">\n <button mat-button (click)=\"onDelete(schedule)\">\u5220\u9664</button>\n <button mat-button (click)=\"onSave(schedule)\">\u4FDD\u5B58</button>\n </div>\n}\n<mat-divider></mat-divider>\n", styles: [""], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i1$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i3$1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TextFieldModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i5.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i5.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i5.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i7.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }] }); }
|
|
784
|
+
}
|
|
785
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: ScheduleItemComponent, decorators: [{
|
|
786
|
+
type: Component,
|
|
787
|
+
args: [{ selector: 'rolatech-schedule-item', providers: [
|
|
788
|
+
{
|
|
789
|
+
provide: DateAdapter,
|
|
790
|
+
useClass: MomentDateAdapter,
|
|
791
|
+
deps: [MAT_DATE_LOCALE],
|
|
792
|
+
},
|
|
793
|
+
{ provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
|
|
794
|
+
DatePipe,
|
|
795
|
+
], standalone: true, imports: [
|
|
796
|
+
NgClass,
|
|
797
|
+
MatFormFieldModule,
|
|
798
|
+
MatInputModule,
|
|
799
|
+
FormsModule,
|
|
800
|
+
TextFieldModule,
|
|
801
|
+
MatDatepickerModule,
|
|
802
|
+
MatSelectModule,
|
|
803
|
+
MatOptionModule,
|
|
804
|
+
MatButtonModule,
|
|
805
|
+
MatDividerModule,
|
|
806
|
+
], template: "<div class=\"flex flex-col\" [ngClass]=\"{ shadow: shadow() }\">\n <mat-form-field appearance=\"fill\">\n <mat-label> \u6807\u9898 </mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"schedule.title\" name=\"title\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label> \u5185\u5BB9 </mat-label>\n <textarea\n matInput\n type=\"text\"\n [(ngModel)]=\"schedule.content\"\n name=\"content\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"3\"\n required\n ></textarea>\n </mat-form-field>\n <div class=\"flex flex-row gap-3\">\n <mat-form-field appearance=\"fill\">\n <mat-label>\u5F00\u59CB\u65E5\u671F</mat-label>\n <input\n matInput\n [matDatepicker]=\"picker\"\n (focus)=\"picker.open()\"\n name=\"startAt\"\n [(ngModel)]=\"schedule.startDate\"\n (ngModelChange)=\"startDateChanged($event)\"\n (dateInput)=\"schedule.startDate = $event.value.format('YYYY-MM-DD')\"\n readonly\n required\n />\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>\u5F00\u59CB\u65F6\u95F4</mat-label>\n <mat-select [(ngModel)]=\"schedule.startTime\" (selectionChange)=\"startTimeChanged($event)\" required readonly>\n @for (d of date; track d) {\n <mat-option [value]=\"d\">\n {{ d }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"flex flex-row gap-3\">\n <mat-form-field appearance=\"fill\">\n <mat-label>\u7ED3\u675F\u65E5\u671F</mat-label>\n <input\n matInput\n [matDatepicker]=\"picker2\"\n name=\"endAt\"\n (focus)=\"picker2.open()\"\n (ngModelChange)=\"endDateChanged($event)\"\n [(ngModel)]=\"schedule.endDate\"\n (dateInput)=\"schedule.endDate = $event.value.format('YYYY-MM-DD')\"\n readonly\n required\n />\n <mat-datepicker-toggle matIconSuffix [for]=\"picker2\"></mat-datepicker-toggle>\n <mat-datepicker #picker2></mat-datepicker>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>\u7ED3\u675F\u65F6\u95F4</mat-label>\n <mat-select [(ngModel)]=\"schedule.endTime\" (selectionChange)=\"endTimeChanged($event)\" required readonly>\n @for (d of date; track d) {\n <mat-option [value]=\"d\">\n {{ d }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n</div>\n@if (actions()) {\n <div class=\"flex flex-row justify-end p-4\">\n <button mat-button (click)=\"onDelete(schedule)\">\u5220\u9664</button>\n <button mat-button (click)=\"onSave(schedule)\">\u4FDD\u5B58</button>\n </div>\n}\n<mat-divider></mat-divider>\n" }]
|
|
807
|
+
}] });
|
|
808
|
+
|
|
809
|
+
class CourseSectionLectureVideoDialogComponent {
|
|
810
|
+
constructor(dialogRef, data) {
|
|
811
|
+
this.dialogRef = dialogRef;
|
|
812
|
+
this.data = data;
|
|
813
|
+
this.thumbnailUpload = output();
|
|
814
|
+
this.courseService = inject(CourseService);
|
|
815
|
+
this.courseSectionService = inject(CourseSectionService);
|
|
816
|
+
this.snackBar = inject(MatSnackBar);
|
|
817
|
+
this.platformId = inject(PLATFORM_ID);
|
|
620
818
|
this.el = inject(ElementRef);
|
|
621
|
-
this.
|
|
819
|
+
this.lecture = data.data;
|
|
820
|
+
}
|
|
821
|
+
ngAfterViewInit() {
|
|
822
|
+
this.initPlayer(this.lecture.item.url, this.lecture.item.thumbnail);
|
|
823
|
+
}
|
|
824
|
+
close() {
|
|
825
|
+
this.dialogRef.close();
|
|
826
|
+
}
|
|
827
|
+
initPlayer(url, thumbnail) {
|
|
828
|
+
if (!isPlatformBrowser(this.platformId)) {
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
// 'https://cos-video-1258344699.cos.ap-guangzhou.tencentcos.cn/test.mp4',
|
|
832
|
+
if (!this.player) {
|
|
833
|
+
const playerContainer = this.el.nativeElement.querySelector('#dplayer');
|
|
834
|
+
this.player = new DPlayer({
|
|
835
|
+
container: playerContainer,
|
|
836
|
+
screenshot: true,
|
|
837
|
+
preload: 'metadata',
|
|
838
|
+
video: {
|
|
839
|
+
url: url,
|
|
840
|
+
pic: thumbnail,
|
|
841
|
+
},
|
|
842
|
+
});
|
|
843
|
+
// this.player.on('loadedmetadata', () => {
|
|
844
|
+
// console.log('Video duration:', this.player.video.duration);
|
|
845
|
+
// });
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
ngOnInit() { }
|
|
849
|
+
ngOnDestroy() {
|
|
850
|
+
if (this.player) {
|
|
851
|
+
this.player.destroy();
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
onThumbnailUpload(event) {
|
|
855
|
+
const file = event.target.files[0];
|
|
856
|
+
if (file) {
|
|
857
|
+
const reader = new FileReader();
|
|
858
|
+
reader.readAsDataURL(file);
|
|
859
|
+
reader.onload = () => {
|
|
860
|
+
this.mediaSrc = reader.result;
|
|
861
|
+
const formData = new FormData();
|
|
862
|
+
formData.append('file', file);
|
|
863
|
+
this.courseService.uploadLectureVideoThumbnail(this.lecture.item.id, formData).subscribe({
|
|
864
|
+
next: (res) => {
|
|
865
|
+
this.lecture.item = res.data;
|
|
866
|
+
this.snackBar.open('上传成功');
|
|
867
|
+
this.player.switchVideo({
|
|
868
|
+
url: this.lecture.item.url,
|
|
869
|
+
pic: res.data.thumbnail,
|
|
870
|
+
});
|
|
871
|
+
},
|
|
872
|
+
});
|
|
873
|
+
};
|
|
874
|
+
reader.onerror = (error) => { };
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
onPreviewChange(event) {
|
|
878
|
+
this.courseSectionService.canBePreviewed(this.lecture.item.id, { canBePreviewed: event.checked }).subscribe({
|
|
879
|
+
next: (res) => {
|
|
880
|
+
this.lecture.item.canBePreviewed = res.data.canBePreviewed;
|
|
881
|
+
// this.lecture = res.data;
|
|
882
|
+
},
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseSectionLectureVideoDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
886
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseSectionLectureVideoDialogComponent, isStandalone: true, selector: "rolatech-course-section-lecture-video-dialog", outputs: { thumbnailUpload: "thumbnailUpload" }, ngImport: i0, template: "<div class=\"flex flex-col-reverse sm:flex-row justify-between h-full gap-3\">\n <div class=\"w-full sm:w-1/2\">\n <div>\n <div class=\"py-3 flex flex-col\">\n <span class=\"text-lg font-bold\"> \u5C01\u9762 </span>\n <span class=\"text-sm\">\u4E00\u4E2A\u597D\u7684\u5C01\u9762\u53EF\u4EE5\u5F15\u8D77\u66F4\u591A\u7684\u5173\u6CE8</span>\n </div>\n\n <div class=\"flex gap-3\">\n <div\n class=\"p-3 w-36 flex flex-col items-center justify-center outline-dashed outline-1 rounded cursor-pointer\"\n (click)=\"fileInput.click()\"\n >\n <mat-icon>upload</mat-icon>\n <span class=\"text-sm\">\u4E0A\u4F20\u5C01\u9762</span>\n </div>\n <input type=\"file\" accept=\"image/*\" (change)=\"onThumbnailUpload($event)\" #fileInput style=\"display: none\" />\n @if (lecture.item.thumbnail) {\n <div class=\"aspect-video w-32 h-auto bg-black\">\n <img [src]=\"lecture.item.thumbnail\" class=\"aspect-video object-contain\" />\n </div>\n } @else {\n <div class=\"aspect-video w-32 h-auto\">\n <img [src]=\"mediaSrc\" class=\"aspect-video object-contain\" />\n </div>\n }\n </div>\n </div>\n <div class=\"mt-3\">\n <div class=\"py-3 flex flex-col\">\n <span class=\"text-lg font-bold\"> \u8BD5\u770B\u5185\u5BB9 </span>\n <span class=\"text-sm\">\u5C11\u91CF\u7684\u8BD5\u770B\u5185\u5BB9, \u53EF\u4EE5\u589E\u52A0\u8D2D\u4E70\u7387</span>\n </div>\n <mat-checkbox color=\"primary\" (change)=\"onPreviewChange($event)\" [checked]=\"lecture.item.canBePreviewed\"\n >\u5141\u8BB8\u8BD5\u770B</mat-checkbox\n >\n </div>\n </div>\n <div class=\"w-full sm:w-1/2\">\n @if (lecture) {\n <div>\n <div id=\"dplayer\" class=\"w-full h-auto aspect-video sm:rounded-xl\"></div>\n </div>\n }\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatStepperModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i3$2.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }] }); }
|
|
887
|
+
}
|
|
888
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseSectionLectureVideoDialogComponent, decorators: [{
|
|
889
|
+
type: Component,
|
|
890
|
+
args: [{ selector: 'rolatech-course-section-lecture-video-dialog', standalone: true, imports: [
|
|
891
|
+
MatIconModule,
|
|
892
|
+
MatDividerModule,
|
|
893
|
+
FormsModule,
|
|
894
|
+
MatStepperModule,
|
|
895
|
+
ScheduleItemComponent,
|
|
896
|
+
MatButtonModule,
|
|
897
|
+
MatDialogClose,
|
|
898
|
+
MatCheckboxModule,
|
|
899
|
+
], template: "<div class=\"flex flex-col-reverse sm:flex-row justify-between h-full gap-3\">\n <div class=\"w-full sm:w-1/2\">\n <div>\n <div class=\"py-3 flex flex-col\">\n <span class=\"text-lg font-bold\"> \u5C01\u9762 </span>\n <span class=\"text-sm\">\u4E00\u4E2A\u597D\u7684\u5C01\u9762\u53EF\u4EE5\u5F15\u8D77\u66F4\u591A\u7684\u5173\u6CE8</span>\n </div>\n\n <div class=\"flex gap-3\">\n <div\n class=\"p-3 w-36 flex flex-col items-center justify-center outline-dashed outline-1 rounded cursor-pointer\"\n (click)=\"fileInput.click()\"\n >\n <mat-icon>upload</mat-icon>\n <span class=\"text-sm\">\u4E0A\u4F20\u5C01\u9762</span>\n </div>\n <input type=\"file\" accept=\"image/*\" (change)=\"onThumbnailUpload($event)\" #fileInput style=\"display: none\" />\n @if (lecture.item.thumbnail) {\n <div class=\"aspect-video w-32 h-auto bg-black\">\n <img [src]=\"lecture.item.thumbnail\" class=\"aspect-video object-contain\" />\n </div>\n } @else {\n <div class=\"aspect-video w-32 h-auto\">\n <img [src]=\"mediaSrc\" class=\"aspect-video object-contain\" />\n </div>\n }\n </div>\n </div>\n <div class=\"mt-3\">\n <div class=\"py-3 flex flex-col\">\n <span class=\"text-lg font-bold\"> \u8BD5\u770B\u5185\u5BB9 </span>\n <span class=\"text-sm\">\u5C11\u91CF\u7684\u8BD5\u770B\u5185\u5BB9, \u53EF\u4EE5\u589E\u52A0\u8D2D\u4E70\u7387</span>\n </div>\n <mat-checkbox color=\"primary\" (change)=\"onPreviewChange($event)\" [checked]=\"lecture.item.canBePreviewed\"\n >\u5141\u8BB8\u8BD5\u770B</mat-checkbox\n >\n </div>\n </div>\n <div class=\"w-full sm:w-1/2\">\n @if (lecture) {\n <div>\n <div id=\"dplayer\" class=\"w-full h-auto aspect-video sm:rounded-xl\"></div>\n </div>\n }\n </div>\n</div>\n" }]
|
|
900
|
+
}], ctorParameters: () => [{ type: i1$2.MatDialogRef }, { type: undefined, decorators: [{
|
|
901
|
+
type: Inject,
|
|
902
|
+
args: [MAT_DIALOG_DATA]
|
|
903
|
+
}] }] });
|
|
904
|
+
|
|
905
|
+
class CourseSectionLectureItemComponent {
|
|
906
|
+
constructor() {
|
|
622
907
|
this.platformId = inject(PLATFORM_ID);
|
|
623
|
-
this.
|
|
624
|
-
this.
|
|
625
|
-
this.
|
|
908
|
+
this.el = inject(ElementRef);
|
|
909
|
+
this.dialogService = inject(DialogService);
|
|
910
|
+
this.myVideo = viewChild('video');
|
|
911
|
+
this.progress = input(0);
|
|
912
|
+
this.lecture = input.required();
|
|
913
|
+
this.actions = input(true);
|
|
914
|
+
this.hasUnsaved = input(false);
|
|
915
|
+
this.editId = model();
|
|
916
|
+
this.save = output();
|
|
917
|
+
this.cancel = output();
|
|
918
|
+
this.delete = output();
|
|
919
|
+
this.edit = output();
|
|
920
|
+
this.mediaEdit = output();
|
|
921
|
+
this.thumbnailUpload = output();
|
|
922
|
+
this.upload = output();
|
|
923
|
+
this.deleteMedia = output();
|
|
924
|
+
this.editing = false;
|
|
626
925
|
}
|
|
627
926
|
ngOnInit() { }
|
|
628
|
-
|
|
629
|
-
this.
|
|
927
|
+
onSave(lecture) {
|
|
928
|
+
this.editing = false;
|
|
929
|
+
this.editId.set(null);
|
|
930
|
+
this.save.emit(lecture);
|
|
931
|
+
}
|
|
932
|
+
onCancel(lecture) {
|
|
933
|
+
this.editing = false;
|
|
934
|
+
this.editId.set(null);
|
|
935
|
+
this.cancel.emit(lecture);
|
|
936
|
+
}
|
|
937
|
+
onDelete(lecture) {
|
|
938
|
+
this.delete.emit(lecture);
|
|
939
|
+
}
|
|
940
|
+
onEdit(lecture) {
|
|
941
|
+
this.editId.set(lecture.id);
|
|
942
|
+
this.editing = true;
|
|
943
|
+
this.edit.emit(lecture);
|
|
944
|
+
}
|
|
945
|
+
onMediaEdit(lecture) {
|
|
946
|
+
this.editId.set(lecture.id);
|
|
947
|
+
this.editing = true;
|
|
948
|
+
// this.mediaEdit.emit(lecture);
|
|
949
|
+
const options = {
|
|
950
|
+
title: '编辑视频',
|
|
951
|
+
cancelText: '取消',
|
|
952
|
+
confirmText: '确定',
|
|
953
|
+
data: this.lecture,
|
|
954
|
+
width: '80vw',
|
|
955
|
+
height: '100%',
|
|
956
|
+
component: CourseSectionLectureVideoDialogComponent,
|
|
957
|
+
};
|
|
958
|
+
this.dialogService.open(options);
|
|
959
|
+
this.dialogService.confirmed().subscribe({
|
|
960
|
+
next: (res) => {
|
|
961
|
+
if (res) {
|
|
962
|
+
const data = {
|
|
963
|
+
name: res,
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
},
|
|
967
|
+
});
|
|
630
968
|
}
|
|
631
|
-
|
|
632
|
-
|
|
969
|
+
onVideoThumbnailUpload(video) {
|
|
970
|
+
this.thumbnailUpload.emit(video);
|
|
971
|
+
}
|
|
972
|
+
onUpload(id, data) {
|
|
973
|
+
this.lecture().isUploading = true;
|
|
974
|
+
this.upload.emit({ id, data });
|
|
975
|
+
}
|
|
976
|
+
onDeleteMedia(data) {
|
|
977
|
+
this.deleteMedia.emit(data);
|
|
978
|
+
}
|
|
979
|
+
onLoadedMetadata(event) {
|
|
980
|
+
if (this.lecture().item.duration) {
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
983
|
+
const videoElement = event.target;
|
|
984
|
+
this.lecture().item.duration = videoElement.duration;
|
|
985
|
+
// console.log('Video Width:', videoElement.videoWidth);
|
|
986
|
+
// console.log('Video Height:', videoElement.videoHeight);
|
|
987
|
+
}
|
|
988
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseSectionLectureItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
989
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseSectionLectureItemComponent, isStandalone: true, selector: "rolatech-course-section-lecture-item", inputs: { progress: { classPropertyName: "progress", publicName: "progress", isSignal: true, isRequired: false, transformFunction: null }, lecture: { classPropertyName: "lecture", publicName: "lecture", isSignal: true, isRequired: true, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, hasUnsaved: { classPropertyName: "hasUnsaved", publicName: "hasUnsaved", isSignal: true, isRequired: false, transformFunction: null }, editId: { classPropertyName: "editId", publicName: "editId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { editId: "editIdChange", save: "save", cancel: "cancel", delete: "delete", edit: "edit", mediaEdit: "mediaEdit", thumbnailUpload: "thumbnailUpload", upload: "upload", deleteMedia: "deleteMedia" }, viewQueries: [{ propertyName: "myVideo", first: true, predicate: ["video"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"flex flex-col grow p-2\">\n @if (lecture().id !== editId()) {\n <div class=\"w-full flex gap-3 p-3\">\n <span>{{ lecture().title }}</span>\n <mat-icon (click)=\"onEdit(lecture())\" class=\"cursor-pointer\">edit</mat-icon>\n <mat-icon class=\"cursor-pointer\" (click)=\"onDelete(lecture())\">delete</mat-icon>\n </div>\n } @else {\n <div class=\"flex flex-col justify-between items-center\">\n <input\n type=\"text\"\n class=\"bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500\"\n placeholder=\"\u6807\u9898\"\n [(ngModel)]=\"lecture().title\"\n />\n <div class=\"w-full flex flex-row justify-end p-4 gap-3\">\n <button mat-button (click)=\"onCancel(lecture())\">\u53D6\u6D88</button>\n <button mat-flat-button color=\"primary\" (click)=\"onSave(lecture())\">\u4FDD\u5B58</button>\n </div>\n </div>\n }\n\n <div>\n @if (lecture().item) {\n <div class=\"flex flex-row p-2 gap-3\">\n <div class=\"bg-black h-fit\">\n <video\n id=\"video\"\n #video\n [src]=\"lecture().item.url\"\n class=\"w-32 aspect-video\"\n (loadedmetadata)=\"onLoadedMetadata($event)\"\n [poster]=\"lecture().item.thumbnail\"\n ></video>\n </div>\n <div class=\"flex flex-col justify-between w-full\">\n <div class=\"flex justify-between items-center w-full\">\n <div class=\"flex justify-between items-center w-full px-2\">\n <span>\u89C6\u9891\u5185\u5BB9</span>\n </div>\n @if (lecture().isUploading) {\n <div>\n <span> {{ lecture().item.progress }}%</span>\n </div>\n }\n </div>\n <div class=\"flex justify-between items-center\">\n <div>\n <button mat-button (click)=\"onMediaEdit(lecture().item)\">\n <mat-icon>edit</mat-icon>\n <span>\u7F16\u8F91</span>\n </button>\n <button mat-button (click)=\"onDeleteMedia(lecture().item)\">\n <mat-icon>delete</mat-icon>\n <span>\u5220\u9664</span>\n </button>\n </div>\n <div>\n <span>{{ lecture().item.duration | duration }}</span>\n </div>\n </div>\n </div>\n </div>\n @if (lecture().isUploading) {\n <div class=\"p-2\">\n <mat-progress-bar color=\"primary\" mode=\"determinate\" [value]=\"lecture().item.progress\"> </mat-progress-bar>\n </div>\n }\n } @else {\n @if (lecture().id !== editId()) {\n <div class=\"px-3\">\n <input\n class=\"ud-sr-only\"\n type=\"file\"\n accept=\".avi,.mpg,.mpeg,.flv,.mov,.m2v,.m4v,.mp4,.rm,.ram,.vob,.ogv,.webm,.wmv\"\n (change)=\"onUpload(lecture().id, $event)\"\n #fileInput\n />\n <div class=\"flex justify-between items-center\">\n <div>\u65E0\u89C6\u9891\u6587\u4EF6</div>\n <button mat-flat-button color=\"primary\" (click)=\"fileInput.click()\">\u4E0A\u4F20\u89C6\u9891</button>\n </div>\n </div>\n }\n }\n </div>\n @if (!hasUnsaved) {\n <ng-content></ng-content>\n }\n</div>\n", styles: [".ud-sr-only{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: AngularCommonModule }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: i4.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "pipe", type: DurationPipe, name: "duration" }] }); }
|
|
633
990
|
}
|
|
634
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type:
|
|
991
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseSectionLectureItemComponent, decorators: [{
|
|
635
992
|
type: Component,
|
|
636
|
-
args: [{ selector: 'rolatech-course-
|
|
993
|
+
args: [{ selector: 'rolatech-course-section-lecture-item', standalone: true, imports: [
|
|
994
|
+
MatIconModule,
|
|
995
|
+
AngularCommonModule,
|
|
996
|
+
FormsModule,
|
|
997
|
+
MatButtonModule,
|
|
998
|
+
MatDividerModule,
|
|
999
|
+
AngularComponentsModule,
|
|
1000
|
+
DurationPipe,
|
|
1001
|
+
], template: "<div class=\"flex flex-col grow p-2\">\n @if (lecture().id !== editId()) {\n <div class=\"w-full flex gap-3 p-3\">\n <span>{{ lecture().title }}</span>\n <mat-icon (click)=\"onEdit(lecture())\" class=\"cursor-pointer\">edit</mat-icon>\n <mat-icon class=\"cursor-pointer\" (click)=\"onDelete(lecture())\">delete</mat-icon>\n </div>\n } @else {\n <div class=\"flex flex-col justify-between items-center\">\n <input\n type=\"text\"\n class=\"bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500\"\n placeholder=\"\u6807\u9898\"\n [(ngModel)]=\"lecture().title\"\n />\n <div class=\"w-full flex flex-row justify-end p-4 gap-3\">\n <button mat-button (click)=\"onCancel(lecture())\">\u53D6\u6D88</button>\n <button mat-flat-button color=\"primary\" (click)=\"onSave(lecture())\">\u4FDD\u5B58</button>\n </div>\n </div>\n }\n\n <div>\n @if (lecture().item) {\n <div class=\"flex flex-row p-2 gap-3\">\n <div class=\"bg-black h-fit\">\n <video\n id=\"video\"\n #video\n [src]=\"lecture().item.url\"\n class=\"w-32 aspect-video\"\n (loadedmetadata)=\"onLoadedMetadata($event)\"\n [poster]=\"lecture().item.thumbnail\"\n ></video>\n </div>\n <div class=\"flex flex-col justify-between w-full\">\n <div class=\"flex justify-between items-center w-full\">\n <div class=\"flex justify-between items-center w-full px-2\">\n <span>\u89C6\u9891\u5185\u5BB9</span>\n </div>\n @if (lecture().isUploading) {\n <div>\n <span> {{ lecture().item.progress }}%</span>\n </div>\n }\n </div>\n <div class=\"flex justify-between items-center\">\n <div>\n <button mat-button (click)=\"onMediaEdit(lecture().item)\">\n <mat-icon>edit</mat-icon>\n <span>\u7F16\u8F91</span>\n </button>\n <button mat-button (click)=\"onDeleteMedia(lecture().item)\">\n <mat-icon>delete</mat-icon>\n <span>\u5220\u9664</span>\n </button>\n </div>\n <div>\n <span>{{ lecture().item.duration | duration }}</span>\n </div>\n </div>\n </div>\n </div>\n @if (lecture().isUploading) {\n <div class=\"p-2\">\n <mat-progress-bar color=\"primary\" mode=\"determinate\" [value]=\"lecture().item.progress\"> </mat-progress-bar>\n </div>\n }\n } @else {\n @if (lecture().id !== editId()) {\n <div class=\"px-3\">\n <input\n class=\"ud-sr-only\"\n type=\"file\"\n accept=\".avi,.mpg,.mpeg,.flv,.mov,.m2v,.m4v,.mp4,.rm,.ram,.vob,.ogv,.webm,.wmv\"\n (change)=\"onUpload(lecture().id, $event)\"\n #fileInput\n />\n <div class=\"flex justify-between items-center\">\n <div>\u65E0\u89C6\u9891\u6587\u4EF6</div>\n <button mat-flat-button color=\"primary\" (click)=\"fileInput.click()\">\u4E0A\u4F20\u89C6\u9891</button>\n </div>\n </div>\n }\n }\n </div>\n @if (!hasUnsaved) {\n <ng-content></ng-content>\n }\n</div>\n", styles: [".ud-sr-only{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}\n"] }]
|
|
637
1002
|
}] });
|
|
638
1003
|
|
|
639
|
-
class
|
|
1004
|
+
class CourseSectionLectureVideoItemComponent {
|
|
1005
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseSectionLectureVideoItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1006
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.0", type: CourseSectionLectureVideoItemComponent, isStandalone: true, selector: "rolatech-course-section-lecture-video-item", ngImport: i0, template: "<p>course-section-lecture-video-item works!</p>\n", styles: [""] }); }
|
|
1007
|
+
}
|
|
1008
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseSectionLectureVideoItemComponent, decorators: [{
|
|
1009
|
+
type: Component,
|
|
1010
|
+
args: [{ selector: 'rolatech-course-section-lecture-video-item', standalone: true, template: "<p>course-section-lecture-video-item works!</p>\n" }]
|
|
1011
|
+
}] });
|
|
1012
|
+
|
|
1013
|
+
class CourseItemComponent {
|
|
640
1014
|
constructor() {
|
|
641
1015
|
this.course = input.required();
|
|
642
|
-
this.
|
|
643
|
-
this.username = input();
|
|
1016
|
+
this.row = input(true);
|
|
644
1017
|
}
|
|
645
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type:
|
|
646
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type:
|
|
1018
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1019
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseItemComponent, isStandalone: true, selector: "rolatech-course-item", inputs: { course: { classPropertyName: "course", publicName: "course", isSignal: true, isRequired: true, transformFunction: null }, row: { classPropertyName: "row", publicName: "row", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (row()) {\n <div class=\"flex w-full flex-row\">\n <div class=\"h-fit w-2/5 sm:w-1/4 aspect-video bg-gray-200 rounded-lg\">\n @if (course().media) {\n @defer (on viewport()) {\n <img class=\"w-full object-cover aspect-video rounded-lg\" [src]=\"course().media[0].url\" />\n } @placeholder {\n <div class=\"bg-gray-200 w-full object-cover aspect-video rounded-lg\"></div>\n }\n }\n </div>\n <div class=\"w-3/5 sm:w-3/4 ml-3 py-1 flex flex-col justify-between\">\n <div>\n <div class=\"sm:text-xl font-medium break-words line-clamp-2 whitespace-normal\">{{ course().name }}</div>\n <div class=\"invisible h-0 sm:h-auto sm:visible break-words line-clamp-1 whitespace-normal\">\n {{ course().description }}\n </div>\n </div>\n @if (course().pricing) {\n <div class=\"sm:text-lg font-medium py-1\">\u00A5{{ course().pricing[0].total / 100 }}</div>\n }\n </div>\n </div>\n} @else {\n <div>\n <div class=\"bg-gray-200 rounded-lg h-fit\">\n @if (course().media) {\n @defer (on viewport()) {\n <img class=\"w-full object-cover aspect-video rounded-lg\" [src]=\"course().media[0].url\" />\n } @placeholder {\n <div class=\"bg-gray-200 w-full object-cover aspect-video rounded-lg\"></div>\n }\n }\n </div>\n <div class=\"mt-2\">\n <div class=\"text-md sm:text-xl font-medium break-words line-clamp-2\">{{ course().name }}</div>\n @if (course().pricing) {\n <div class=\"text-md sm:text-lg font-medium py-1\">\u00A5{{ course().pricing[0].total / 100 }}</div>\n }\n </div>\n </div>\n}\n", styles: [""] }); }
|
|
647
1020
|
}
|
|
648
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type:
|
|
1021
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseItemComponent, decorators: [{
|
|
649
1022
|
type: Component,
|
|
650
|
-
args: [{ selector: 'rolatech-course-
|
|
1023
|
+
args: [{ selector: 'rolatech-course-item', standalone: true, imports: [], template: "@if (row()) {\n <div class=\"flex w-full flex-row\">\n <div class=\"h-fit w-2/5 sm:w-1/4 aspect-video bg-gray-200 rounded-lg\">\n @if (course().media) {\n @defer (on viewport()) {\n <img class=\"w-full object-cover aspect-video rounded-lg\" [src]=\"course().media[0].url\" />\n } @placeholder {\n <div class=\"bg-gray-200 w-full object-cover aspect-video rounded-lg\"></div>\n }\n }\n </div>\n <div class=\"w-3/5 sm:w-3/4 ml-3 py-1 flex flex-col justify-between\">\n <div>\n <div class=\"sm:text-xl font-medium break-words line-clamp-2 whitespace-normal\">{{ course().name }}</div>\n <div class=\"invisible h-0 sm:h-auto sm:visible break-words line-clamp-1 whitespace-normal\">\n {{ course().description }}\n </div>\n </div>\n @if (course().pricing) {\n <div class=\"sm:text-lg font-medium py-1\">\u00A5{{ course().pricing[0].total / 100 }}</div>\n }\n </div>\n </div>\n} @else {\n <div>\n <div class=\"bg-gray-200 rounded-lg h-fit\">\n @if (course().media) {\n @defer (on viewport()) {\n <img class=\"w-full object-cover aspect-video rounded-lg\" [src]=\"course().media[0].url\" />\n } @placeholder {\n <div class=\"bg-gray-200 w-full object-cover aspect-video rounded-lg\"></div>\n }\n }\n </div>\n <div class=\"mt-2\">\n <div class=\"text-md sm:text-xl font-medium break-words line-clamp-2\">{{ course().name }}</div>\n @if (course().pricing) {\n <div class=\"text-md sm:text-lg font-medium py-1\">\u00A5{{ course().pricing[0].total / 100 }}</div>\n }\n </div>\n </div>\n}\n" }]
|
|
651
1024
|
}] });
|
|
652
1025
|
|
|
653
|
-
class
|
|
1026
|
+
class PricingItemComponent {
|
|
654
1027
|
constructor() {
|
|
655
|
-
this.
|
|
656
|
-
this.
|
|
657
|
-
this.
|
|
658
|
-
this.
|
|
1028
|
+
this.actions = input(false);
|
|
1029
|
+
this.shadow = input(false);
|
|
1030
|
+
this.pricing = model.required();
|
|
1031
|
+
this.delete = output();
|
|
1032
|
+
this.save = output();
|
|
1033
|
+
}
|
|
1034
|
+
ngOnInit() {
|
|
1035
|
+
this.pricing().total = this.pricing().total / 100;
|
|
1036
|
+
}
|
|
1037
|
+
onSave(pricing) {
|
|
1038
|
+
const finalPricing = {
|
|
1039
|
+
...pricing,
|
|
1040
|
+
total: pricing.total * 100,
|
|
1041
|
+
};
|
|
1042
|
+
this.save.emit(finalPricing);
|
|
1043
|
+
}
|
|
1044
|
+
onDelete(pricing) {
|
|
1045
|
+
this.delete.emit(pricing);
|
|
1046
|
+
}
|
|
1047
|
+
setTwoNumberDecimal(e) {
|
|
1048
|
+
this.pricing().total = e;
|
|
1049
|
+
}
|
|
1050
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: PricingItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1051
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: PricingItemComponent, isStandalone: true, selector: "rolatech-pricing-item", inputs: { actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, shadow: { classPropertyName: "shadow", publicName: "shadow", isSignal: true, isRequired: false, transformFunction: null }, pricing: { classPropertyName: "pricing", publicName: "pricing", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { pricing: "pricingChange", delete: "delete", save: "save" }, ngImport: i0, template: "<div class=\"flex flex-col py-3\" [ngClass]=\"{ shadow: shadow() }\">\n <mat-form-field appearance=\"fill\">\n <mat-label> \u6700\u5C11\u4EBA\u6570 </mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"pricing().min\" name=\"min\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label> \u6700\u591A\u4EBA\u6570 </mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"pricing().max\" name=\"max\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label> \u4EF7\u683C </mat-label>\n <!-- <input matInput type=\"number\" step=\"0.01\" [ngModel]=\"pricing().total\"\n (ngModelChange)=\"setTwoNumberDecimal($event)\" name=\"total\" required placeholder=\"20.23\" /> -->\n <input matInput rolatechDecimal type=\"text\" [(ngModel)]=\"pricing().total\" name=\"total\" required />\n </mat-form-field>\n</div>\n@if (actions()) {\n <div class=\"flex flex-row justify-end p-4\">\n <button mat-button (click)=\"onDelete(pricing())\">\u5220\u9664</button>\n <button mat-button (click)=\"onSave(pricing())\">\u4FDD\u5B58</button>\n </div>\n}\n<mat-divider></mat-divider>\n", styles: [""], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }] }); }
|
|
1052
|
+
}
|
|
1053
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: PricingItemComponent, decorators: [{
|
|
1054
|
+
type: Component,
|
|
1055
|
+
args: [{ selector: 'rolatech-pricing-item', standalone: true, imports: [NgClass, MatFormFieldModule, MatInputModule, FormsModule, MatButtonModule, MatDividerModule], template: "<div class=\"flex flex-col py-3\" [ngClass]=\"{ shadow: shadow() }\">\n <mat-form-field appearance=\"fill\">\n <mat-label> \u6700\u5C11\u4EBA\u6570 </mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"pricing().min\" name=\"min\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label> \u6700\u591A\u4EBA\u6570 </mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"pricing().max\" name=\"max\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label> \u4EF7\u683C </mat-label>\n <!-- <input matInput type=\"number\" step=\"0.01\" [ngModel]=\"pricing().total\"\n (ngModelChange)=\"setTwoNumberDecimal($event)\" name=\"total\" required placeholder=\"20.23\" /> -->\n <input matInput rolatechDecimal type=\"text\" [(ngModel)]=\"pricing().total\" name=\"total\" required />\n </mat-form-field>\n</div>\n@if (actions()) {\n <div class=\"flex flex-row justify-end p-4\">\n <button mat-button (click)=\"onDelete(pricing())\">\u5220\u9664</button>\n <button mat-button (click)=\"onSave(pricing())\">\u4FDD\u5B58</button>\n </div>\n}\n<mat-divider></mat-divider>\n" }]
|
|
1056
|
+
}], ctorParameters: () => [] });
|
|
1057
|
+
|
|
1058
|
+
class CoursePricingAddDialogComponent {
|
|
1059
|
+
constructor(dialogRef, data) {
|
|
1060
|
+
this.dialogRef = dialogRef;
|
|
1061
|
+
this.data = data;
|
|
1062
|
+
this.pricing = {
|
|
1063
|
+
min: 0,
|
|
1064
|
+
max: 0,
|
|
1065
|
+
total: 0,
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
close() {
|
|
1069
|
+
this.dialogRef.close();
|
|
1070
|
+
}
|
|
1071
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CoursePricingAddDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1072
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CoursePricingAddDialogComponent, isStandalone: true, selector: "rolatech-course-pricing-add-dialog", ngImport: i0, template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-xl font-bold\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <div class=\"flex-1 overflow-hidden p-3 overflow-y-auto max-h-[55vh]\">\n <rolatech-pricing-item [pricing]=\"pricing\"></rolatech-pricing-item>\n </div>\n <div class=\"h-16 flex justify-end items-center px-5 gap-3\">\n <button mat-button mat-dialog-close>\u53D6\u6D88</button>\n <button mat-button [mat-dialog-close]=\"pricing\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: PricingItemComponent, selector: "rolatech-pricing-item", inputs: ["actions", "shadow", "pricing"], outputs: ["pricingChange", "delete", "save"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }] }); }
|
|
1073
|
+
}
|
|
1074
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CoursePricingAddDialogComponent, decorators: [{
|
|
1075
|
+
type: Component,
|
|
1076
|
+
args: [{ selector: 'rolatech-course-pricing-add-dialog', standalone: true, imports: [MatIconModule, PricingItemComponent, MatButtonModule, MatDialogClose], template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-xl font-bold\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <div class=\"flex-1 overflow-hidden p-3 overflow-y-auto max-h-[55vh]\">\n <rolatech-pricing-item [pricing]=\"pricing\"></rolatech-pricing-item>\n </div>\n <div class=\"h-16 flex justify-end items-center px-5 gap-3\">\n <button mat-button mat-dialog-close>\u53D6\u6D88</button>\n <button mat-button [mat-dialog-close]=\"pricing\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n", styles: ["mat-form-field{width:100%}\n"] }]
|
|
1077
|
+
}], ctorParameters: () => [{ type: i1$2.MatDialogRef }, { type: undefined, decorators: [{
|
|
1078
|
+
type: Inject,
|
|
1079
|
+
args: [MAT_DIALOG_DATA]
|
|
1080
|
+
}] }] });
|
|
1081
|
+
|
|
1082
|
+
class CourseScheduleAddDialogComponent {
|
|
1083
|
+
constructor(dialogRef, data) {
|
|
1084
|
+
this.dialogRef = dialogRef;
|
|
1085
|
+
this.data = data;
|
|
1086
|
+
this.schedule = {
|
|
1087
|
+
title: '',
|
|
1088
|
+
content: '',
|
|
1089
|
+
startAt: '',
|
|
1090
|
+
endAt: '',
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
close() {
|
|
1094
|
+
this.dialogRef.close();
|
|
1095
|
+
}
|
|
1096
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseScheduleAddDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1097
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseScheduleAddDialogComponent, isStandalone: true, selector: "rolatech-course-schedule-add-dialog", ngImport: i0, template: "<div class=\"flex flex-col h-full\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-xl font-bold\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <div class=\"flex-1 overflow-y-auto max-h-[55vh] px-3\">\n <rolatech-schedule-item [value]=\"schedule\" [shadow]=\"false\"></rolatech-schedule-item>\n </div>\n <div class=\"h-16 flex justify-end items-center px-5 gap-3\">\n <button mat-button mat-dialog-close>\u53D6\u6D88</button>\n <button mat-button [mat-dialog-close]=\"schedule\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ScheduleItemComponent, selector: "rolatech-schedule-item", inputs: ["value", "actions", "shadow"], outputs: ["delete", "save"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }] }); }
|
|
1098
|
+
}
|
|
1099
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseScheduleAddDialogComponent, decorators: [{
|
|
1100
|
+
type: Component,
|
|
1101
|
+
args: [{ selector: 'rolatech-course-schedule-add-dialog', standalone: true, imports: [MatIconModule, ScheduleItemComponent, MatButtonModule, MatDialogClose], template: "<div class=\"flex flex-col h-full\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-xl font-bold\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <div class=\"flex-1 overflow-y-auto max-h-[55vh] px-3\">\n <rolatech-schedule-item [value]=\"schedule\" [shadow]=\"false\"></rolatech-schedule-item>\n </div>\n <div class=\"h-16 flex justify-end items-center px-5 gap-3\">\n <button mat-button mat-dialog-close>\u53D6\u6D88</button>\n <button mat-button [mat-dialog-close]=\"schedule\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n" }]
|
|
1102
|
+
}], ctorParameters: () => [{ type: i1$2.MatDialogRef }, { type: undefined, decorators: [{
|
|
1103
|
+
type: Inject,
|
|
1104
|
+
args: [MAT_DIALOG_DATA]
|
|
1105
|
+
}] }] });
|
|
1106
|
+
|
|
1107
|
+
class CoursePricingDialogComponent {
|
|
1108
|
+
constructor(dialogRef, data, courseService, snackBar, dialog) {
|
|
1109
|
+
this.dialogRef = dialogRef;
|
|
1110
|
+
this.data = data;
|
|
1111
|
+
this.courseService = courseService;
|
|
1112
|
+
this.snackBar = snackBar;
|
|
1113
|
+
this.dialog = dialog;
|
|
1114
|
+
this.pricing = [];
|
|
1115
|
+
this.courseId = data.courseId;
|
|
1116
|
+
this.pricing = data.pricing;
|
|
1117
|
+
}
|
|
1118
|
+
close() {
|
|
1119
|
+
this.dialogRef.close();
|
|
1120
|
+
}
|
|
1121
|
+
addPricing() {
|
|
1122
|
+
this.pricing.push({
|
|
1123
|
+
min: 0,
|
|
1124
|
+
max: 0,
|
|
1125
|
+
total: 0,
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1128
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CoursePricingDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: CourseService }, { token: i3$3.MatSnackBar }, { token: i1$2.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1129
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CoursePricingDialogComponent, isStandalone: true, selector: "rolatech-course-pricing-dialog", ngImport: i0, template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto w-2/3 max-h-[55vh]\">\n <form #detailForm=\"ngForm\" class=\"p-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of pricing; track item) {\n <rolatech-pricing-item [pricing]=\"item\"> </rolatech-pricing-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addPricing()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u4EF7\u683C</span>\n </button>\n </div>\n </form>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n <button mat-button [mat-dialog-close]=\"pricing\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatStepperModule }, { kind: "directive", type: i7$1.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: PricingItemComponent, selector: "rolatech-pricing-item", inputs: ["actions", "shadow", "pricing"], outputs: ["pricingChange", "delete", "save"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }] }); }
|
|
1130
|
+
}
|
|
1131
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CoursePricingDialogComponent, decorators: [{
|
|
1132
|
+
type: Component,
|
|
1133
|
+
args: [{ selector: 'rolatech-course-pricing-dialog', standalone: true, imports: [
|
|
1134
|
+
MatIconModule,
|
|
1135
|
+
MatDividerModule,
|
|
1136
|
+
FormsModule,
|
|
1137
|
+
MatStepperModule,
|
|
1138
|
+
PricingItemComponent,
|
|
1139
|
+
MatButtonModule,
|
|
1140
|
+
MatDialogClose,
|
|
1141
|
+
], template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto w-2/3 max-h-[55vh]\">\n <form #detailForm=\"ngForm\" class=\"p-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of pricing; track item) {\n <rolatech-pricing-item [pricing]=\"item\"> </rolatech-pricing-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addPricing()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u4EF7\u683C</span>\n </button>\n </div>\n </form>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n <button mat-button [mat-dialog-close]=\"pricing\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n" }]
|
|
1142
|
+
}], ctorParameters: () => [{ type: i1$2.MatDialogRef }, { type: undefined, decorators: [{
|
|
1143
|
+
type: Inject,
|
|
1144
|
+
args: [MAT_DIALOG_DATA]
|
|
1145
|
+
}] }, { type: CourseService }, { type: i3$3.MatSnackBar }, { type: i1$2.MatDialog }] });
|
|
1146
|
+
|
|
1147
|
+
class CourseScheduleDialogComponent {
|
|
1148
|
+
constructor(dialogRef, data, courseService, snackBar, dialog) {
|
|
1149
|
+
this.dialogRef = dialogRef;
|
|
1150
|
+
this.data = data;
|
|
1151
|
+
this.courseService = courseService;
|
|
1152
|
+
this.snackBar = snackBar;
|
|
1153
|
+
this.dialog = dialog;
|
|
1154
|
+
this.schedule = [];
|
|
1155
|
+
this.courseId = data.courseId;
|
|
1156
|
+
this.schedule = data.schedule;
|
|
1157
|
+
}
|
|
1158
|
+
close() {
|
|
1159
|
+
this.dialogRef.close();
|
|
1160
|
+
}
|
|
1161
|
+
addSchedule() {
|
|
1162
|
+
if (!this.schedule) {
|
|
1163
|
+
this.schedule = [];
|
|
1164
|
+
}
|
|
1165
|
+
this.schedule.push({
|
|
1166
|
+
title: '',
|
|
1167
|
+
content: '',
|
|
1168
|
+
startAt: '',
|
|
1169
|
+
endAt: '',
|
|
1170
|
+
});
|
|
1171
|
+
}
|
|
1172
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseScheduleDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: CourseService }, { token: i3$3.MatSnackBar }, { token: i1$2.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1173
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseScheduleDialogComponent, isStandalone: true, selector: "rolatech-course-schedule-dialog", ngImport: i0, template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto\">\n <form #detailForm=\"ngForm\" class=\"p-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of schedule; track item) {\n <rolatech-schedule-item [value]=\"item\"></rolatech-schedule-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addSchedule()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BFE\u8868</span>\n </button>\n </div>\n </form>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n <button mat-button [mat-dialog-close]=\"schedule\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatStepperModule }, { kind: "directive", type: i7$1.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: ScheduleItemComponent, selector: "rolatech-schedule-item", inputs: ["value", "actions", "shadow"], outputs: ["delete", "save"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }] }); }
|
|
1174
|
+
}
|
|
1175
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseScheduleDialogComponent, decorators: [{
|
|
1176
|
+
type: Component,
|
|
1177
|
+
args: [{ selector: 'rolatech-course-schedule-dialog', standalone: true, imports: [
|
|
1178
|
+
MatIconModule,
|
|
1179
|
+
MatDividerModule,
|
|
1180
|
+
FormsModule,
|
|
1181
|
+
MatStepperModule,
|
|
1182
|
+
ScheduleItemComponent,
|
|
1183
|
+
MatButtonModule,
|
|
1184
|
+
MatDialogClose,
|
|
1185
|
+
], template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto\">\n <form #detailForm=\"ngForm\" class=\"p-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of schedule; track item) {\n <rolatech-schedule-item [value]=\"item\"></rolatech-schedule-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addSchedule()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BFE\u8868</span>\n </button>\n </div>\n </form>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n <button mat-button [mat-dialog-close]=\"schedule\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n" }]
|
|
1186
|
+
}], ctorParameters: () => [{ type: i1$2.MatDialogRef }, { type: undefined, decorators: [{
|
|
1187
|
+
type: Inject,
|
|
1188
|
+
args: [MAT_DIALOG_DATA]
|
|
1189
|
+
}] }, { type: CourseService }, { type: i3$3.MatSnackBar }, { type: i1$2.MatDialog }] });
|
|
1190
|
+
|
|
1191
|
+
class DetailItemComponent {
|
|
1192
|
+
constructor() {
|
|
1193
|
+
this.isUploading = input();
|
|
1194
|
+
this.detail = input.required();
|
|
1195
|
+
this.shadow = input(true);
|
|
1196
|
+
this.actions = input(false);
|
|
1197
|
+
this.selectMedia = input();
|
|
1198
|
+
this.upload = output();
|
|
1199
|
+
this.delete = output();
|
|
1200
|
+
this.save = output();
|
|
1201
|
+
this.deleteMedia = output();
|
|
1202
|
+
}
|
|
1203
|
+
ngOnInit() {
|
|
1204
|
+
this.selectedImg = this.detail().media ? this.detail().media[0] : null;
|
|
1205
|
+
}
|
|
1206
|
+
onUpload(id, data) {
|
|
1207
|
+
this.upload.emit({ id, data });
|
|
1208
|
+
}
|
|
1209
|
+
onMediaItemClick(image) {
|
|
1210
|
+
this.selectedImg = image;
|
|
1211
|
+
}
|
|
1212
|
+
select(item) {
|
|
1213
|
+
this.selectedImg = item;
|
|
1214
|
+
}
|
|
1215
|
+
deleteImage() { }
|
|
1216
|
+
onSave(detail) {
|
|
1217
|
+
this.save.emit(detail);
|
|
1218
|
+
}
|
|
1219
|
+
onDelete(detail) {
|
|
1220
|
+
this.delete.emit(detail);
|
|
1221
|
+
}
|
|
1222
|
+
onDeleteMedia(id, media) {
|
|
1223
|
+
this.deleteMedia.emit({ id, media });
|
|
1224
|
+
this.selectedImg = this.detail().media ? first(this.detail().media) : null;
|
|
1225
|
+
}
|
|
1226
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: DetailItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1227
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: DetailItemComponent, isStandalone: true, selector: "rolatech-detail-item", inputs: { isUploading: { classPropertyName: "isUploading", publicName: "isUploading", isSignal: true, isRequired: false, transformFunction: null }, detail: { classPropertyName: "detail", publicName: "detail", isSignal: true, isRequired: true, transformFunction: null }, shadow: { classPropertyName: "shadow", publicName: "shadow", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, selectMedia: { classPropertyName: "selectMedia", publicName: "selectMedia", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { upload: "upload", delete: "delete", save: "save", deleteMedia: "deleteMedia" }, ngImport: i0, template: "<div class=\"mb-8\" [ngClass]=\"{ shadow: shadow() }\">\n <div class=\"flex flex-col md:flex-row pt-6\">\n <div class=\"flex flex-col grow\">\n <mat-form-field appearance=\"fill\">\n <mat-label>\u6807\u9898</mat-label>\n <input matInput placeholder=\"\u6807\u9898\" [(ngModel)]=\"detail().title\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\" [hideRequiredMarker]=\"true\">\n <mat-label>\u63CF\u8FF0</mat-label>\n <input matInput placeholder=\"\u63CF\u8FF0\" [(ngModel)]=\"detail().description\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\" [hideRequiredMarker]=\"true\">\n <mat-label>\u5185\u5BB9</mat-label>\n <textarea\n matInput\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"3\"\n placeholder=\"\u5185\u5BB9\"\n [(ngModel)]=\"detail().content\"\n ></textarea>\n </mat-form-field>\n </div>\n <!-- image -->\n <div class=\"md:basis-1/2 px-3\">\n <div class=\"flex flex-row justify-center pb-4 p-1\">\n @if (selectedImg) {\n <img class=\"object-contain w-80 h-80\" [src]=\"selectedImg.url\" [alt]=\"selectedImg.alt\" />\n }\n @if (selectedImg) {\n <button mat-icon-button (click)=\"onDeleteMedia(detail().id, selectedImg)\">\n <mat-icon>delete</mat-icon>\n </button>\n }\n </div>\n <!-- media -->\n <div>\n <div class=\"flex flex-row flex-wrap cursor-pointer relative box-border\" fxLayout=\"row\">\n <div class=\"progress-bar\">\n @if (detail().isUploading) {\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n }\n </div>\n @for (media of detail().media; track media) {\n <div class=\"media-list-item\">\n <img class=\"tile-media\" (click)=\"onMediaItemClick(media)\" [src]=\"media.url\" [alt]=\"media.alt\" />\n </div>\n }\n <input\n style=\"display: none\"\n type=\"file\"\n accept=\"image/*\"\n (change)=\"onUpload(detail().id, $event)\"\n #fileInput\n />\n <div class=\"add-button\">\n <img\n (click)=\"fileInput.click()\"\n class=\"tile-media\"\n src=\"assets/images/baseline_add_black_48dp.png\"\n alt=\"add image\"\n />\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n@if (actions()) {\n <div class=\"flex flex-row justify-end p-4\">\n <button mat-button (click)=\"onDelete(detail())\">\u5220\u9664</button>\n <button mat-button (click)=\"onSave(detail())\">\u4FDD\u5B58</button>\n </div>\n}\n<mat-divider></mat-divider>\n", styles: [".media-list{flex-wrap:wrap;box-sizing:border-box}.progress-bar{display:block;min-height:6px;width:100%}.media-list-item{cursor:pointer;position:relative;box-sizing:border-box;padding:2px}.tile-media{height:80px;width:80px;object-fit:contain;cursor:pointer;border:1px solid grey;padding:6px;position:relative;box-sizing:border-box}.add-button{cursor:pointer;position:relative;box-sizing:border-box;padding:2px}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i3$1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TextFieldModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i4.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }] }); }
|
|
1228
|
+
}
|
|
1229
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: DetailItemComponent, decorators: [{
|
|
1230
|
+
type: Component,
|
|
1231
|
+
args: [{ selector: 'rolatech-detail-item', standalone: true, imports: [
|
|
1232
|
+
NgClass,
|
|
1233
|
+
MatFormFieldModule,
|
|
1234
|
+
MatInputModule,
|
|
1235
|
+
FormsModule,
|
|
1236
|
+
TextFieldModule,
|
|
1237
|
+
MatButtonModule,
|
|
1238
|
+
MatIconModule,
|
|
1239
|
+
MatProgressBarModule,
|
|
1240
|
+
MatDividerModule,
|
|
1241
|
+
], template: "<div class=\"mb-8\" [ngClass]=\"{ shadow: shadow() }\">\n <div class=\"flex flex-col md:flex-row pt-6\">\n <div class=\"flex flex-col grow\">\n <mat-form-field appearance=\"fill\">\n <mat-label>\u6807\u9898</mat-label>\n <input matInput placeholder=\"\u6807\u9898\" [(ngModel)]=\"detail().title\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\" [hideRequiredMarker]=\"true\">\n <mat-label>\u63CF\u8FF0</mat-label>\n <input matInput placeholder=\"\u63CF\u8FF0\" [(ngModel)]=\"detail().description\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\" [hideRequiredMarker]=\"true\">\n <mat-label>\u5185\u5BB9</mat-label>\n <textarea\n matInput\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"3\"\n placeholder=\"\u5185\u5BB9\"\n [(ngModel)]=\"detail().content\"\n ></textarea>\n </mat-form-field>\n </div>\n <!-- image -->\n <div class=\"md:basis-1/2 px-3\">\n <div class=\"flex flex-row justify-center pb-4 p-1\">\n @if (selectedImg) {\n <img class=\"object-contain w-80 h-80\" [src]=\"selectedImg.url\" [alt]=\"selectedImg.alt\" />\n }\n @if (selectedImg) {\n <button mat-icon-button (click)=\"onDeleteMedia(detail().id, selectedImg)\">\n <mat-icon>delete</mat-icon>\n </button>\n }\n </div>\n <!-- media -->\n <div>\n <div class=\"flex flex-row flex-wrap cursor-pointer relative box-border\" fxLayout=\"row\">\n <div class=\"progress-bar\">\n @if (detail().isUploading) {\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n }\n </div>\n @for (media of detail().media; track media) {\n <div class=\"media-list-item\">\n <img class=\"tile-media\" (click)=\"onMediaItemClick(media)\" [src]=\"media.url\" [alt]=\"media.alt\" />\n </div>\n }\n <input\n style=\"display: none\"\n type=\"file\"\n accept=\"image/*\"\n (change)=\"onUpload(detail().id, $event)\"\n #fileInput\n />\n <div class=\"add-button\">\n <img\n (click)=\"fileInput.click()\"\n class=\"tile-media\"\n src=\"assets/images/baseline_add_black_48dp.png\"\n alt=\"add image\"\n />\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n@if (actions()) {\n <div class=\"flex flex-row justify-end p-4\">\n <button mat-button (click)=\"onDelete(detail())\">\u5220\u9664</button>\n <button mat-button (click)=\"onSave(detail())\">\u4FDD\u5B58</button>\n </div>\n}\n<mat-divider></mat-divider>\n", styles: [".media-list{flex-wrap:wrap;box-sizing:border-box}.progress-bar{display:block;min-height:6px;width:100%}.media-list-item{cursor:pointer;position:relative;box-sizing:border-box;padding:2px}.tile-media{height:80px;width:80px;object-fit:contain;cursor:pointer;border:1px solid grey;padding:6px;position:relative;box-sizing:border-box}.add-button{cursor:pointer;position:relative;box-sizing:border-box;padding:2px}\n"] }]
|
|
1242
|
+
}], ctorParameters: () => [] });
|
|
1243
|
+
|
|
1244
|
+
class CourseDetailsDialogComponent {
|
|
1245
|
+
constructor(dialogRef, data, courseService, snackBar, dialog) {
|
|
1246
|
+
this.dialogRef = dialogRef;
|
|
1247
|
+
this.data = data;
|
|
1248
|
+
this.courseService = courseService;
|
|
1249
|
+
this.snackBar = snackBar;
|
|
1250
|
+
this.dialog = dialog;
|
|
1251
|
+
this.details = [];
|
|
1252
|
+
this.courseId = data.courseId;
|
|
1253
|
+
}
|
|
1254
|
+
close() {
|
|
1255
|
+
this.dialogRef.close();
|
|
1256
|
+
}
|
|
1257
|
+
addDetail() {
|
|
1258
|
+
this.courseService
|
|
1259
|
+
.addDetail(this.courseId, {
|
|
1260
|
+
title: '',
|
|
1261
|
+
description: '',
|
|
1262
|
+
content: '',
|
|
1263
|
+
media: [],
|
|
1264
|
+
})
|
|
1265
|
+
.subscribe({
|
|
1266
|
+
next: (res) => {
|
|
1267
|
+
const detail = res.data;
|
|
1268
|
+
this.details.push({
|
|
1269
|
+
id: detail.id,
|
|
1270
|
+
title: '',
|
|
1271
|
+
description: '',
|
|
1272
|
+
content: '',
|
|
1273
|
+
media: [],
|
|
1274
|
+
});
|
|
1275
|
+
},
|
|
1276
|
+
error: (e) => {
|
|
1277
|
+
this.snackBar.open(e.message);
|
|
1278
|
+
},
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
onDetailMediaUpload(event) { }
|
|
1282
|
+
onDetailMediaDelete(event) { }
|
|
1283
|
+
onDetailSave(event) { }
|
|
1284
|
+
onDetailDelete(detail) {
|
|
1285
|
+
this.courseService.deleteDetail(this.courseId, detail.id).subscribe({
|
|
1286
|
+
next: (res) => {
|
|
1287
|
+
this.snackBar.open(res.data);
|
|
1288
|
+
remove(this.details, {
|
|
1289
|
+
id: detail.id,
|
|
1290
|
+
});
|
|
1291
|
+
},
|
|
1292
|
+
error: (e) => {
|
|
1293
|
+
this.snackBar.open(e.message);
|
|
1294
|
+
},
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseDetailsDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: CourseService }, { token: i3$3.MatSnackBar }, { token: i1$2.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1298
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseDetailsDialogComponent, isStandalone: true, selector: "rolatech-course-details-dialog", ngImport: i0, template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto\">\n <form #detailForm=\"ngForm\" class=\"p-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of details; track item) {\n <rolatech-detail-item\n [detail]=\"item\"\n (upload)=\"onDetailMediaUpload($event)\"\n (deleteMedia)=\"onDetailMediaDelete($event)\"\n (save)=\"onDetailSave($event)\"\n (delete)=\"onDetailDelete($event)\"\n ></rolatech-detail-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addDetail()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BE6\u60C5</span>\n </button>\n </div>\n </form>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n <button mat-button [mat-dialog-close]=\"true\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatStepperModule }, { kind: "directive", type: i7$1.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: DetailItemComponent, selector: "rolatech-detail-item", inputs: ["isUploading", "detail", "shadow", "actions", "selectMedia"], outputs: ["upload", "delete", "save", "deleteMedia"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }] }); }
|
|
1299
|
+
}
|
|
1300
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseDetailsDialogComponent, decorators: [{
|
|
1301
|
+
type: Component,
|
|
1302
|
+
args: [{ selector: 'rolatech-course-details-dialog', standalone: true, imports: [
|
|
1303
|
+
MatIconModule,
|
|
1304
|
+
MatDividerModule,
|
|
1305
|
+
FormsModule,
|
|
1306
|
+
MatStepperModule,
|
|
1307
|
+
DetailItemComponent,
|
|
1308
|
+
MatButtonModule,
|
|
1309
|
+
MatDialogClose,
|
|
1310
|
+
], template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto\">\n <form #detailForm=\"ngForm\" class=\"p-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of details; track item) {\n <rolatech-detail-item\n [detail]=\"item\"\n (upload)=\"onDetailMediaUpload($event)\"\n (deleteMedia)=\"onDetailMediaDelete($event)\"\n (save)=\"onDetailSave($event)\"\n (delete)=\"onDetailDelete($event)\"\n ></rolatech-detail-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addDetail()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BE6\u60C5</span>\n </button>\n </div>\n </form>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n <button mat-button [mat-dialog-close]=\"true\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n" }]
|
|
1311
|
+
}], ctorParameters: () => [{ type: i1$2.MatDialogRef }, { type: undefined, decorators: [{
|
|
1312
|
+
type: Inject,
|
|
1313
|
+
args: [MAT_DIALOG_DATA]
|
|
1314
|
+
}] }, { type: CourseService }, { type: i3$3.MatSnackBar }, { type: i1$2.MatDialog }] });
|
|
1315
|
+
|
|
1316
|
+
class CourseEditDialogComponent {
|
|
1317
|
+
constructor(dialogRef, data, categoryService, courseService, snackBar, dialog) {
|
|
1318
|
+
this.dialogRef = dialogRef;
|
|
1319
|
+
this.data = data;
|
|
1320
|
+
this.categoryService = categoryService;
|
|
1321
|
+
this.courseService = courseService;
|
|
1322
|
+
this.snackBar = snackBar;
|
|
1323
|
+
this.dialog = dialog;
|
|
1324
|
+
this.isUploading = false;
|
|
1325
|
+
this.courseType = [
|
|
1326
|
+
{
|
|
1327
|
+
key: 'ONLINE',
|
|
1328
|
+
value: '线上',
|
|
1329
|
+
},
|
|
1330
|
+
{
|
|
1331
|
+
key: 'OFFLINE',
|
|
1332
|
+
value: '线下',
|
|
1333
|
+
},
|
|
1334
|
+
{
|
|
1335
|
+
key: 'MIXED',
|
|
1336
|
+
value: '混合',
|
|
1337
|
+
},
|
|
1338
|
+
];
|
|
1339
|
+
this.date = ScheduleDate;
|
|
1340
|
+
this.lastStepper = false;
|
|
1341
|
+
this.firstStepper = true;
|
|
1342
|
+
this.stepper = viewChild.required(MatStepper);
|
|
1343
|
+
this.course = data.course;
|
|
1344
|
+
this.classrooms = data.classrooms;
|
|
1345
|
+
}
|
|
1346
|
+
ngOnInit() {
|
|
1347
|
+
this.categoryService.find({}).subscribe({
|
|
1348
|
+
next: (res) => {
|
|
1349
|
+
this.categories = res.data;
|
|
1350
|
+
},
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1353
|
+
close() {
|
|
1354
|
+
this.dialogRef.close();
|
|
1355
|
+
}
|
|
1356
|
+
compareFn(o1, o2) {
|
|
1357
|
+
return o1.id === o2.id;
|
|
1358
|
+
}
|
|
1359
|
+
addDetail() {
|
|
1360
|
+
if (!this.course.details) {
|
|
1361
|
+
this.course.details = [];
|
|
1362
|
+
}
|
|
1363
|
+
this.courseService
|
|
1364
|
+
.addDetail(this.course.id, {
|
|
1365
|
+
title: '',
|
|
1366
|
+
description: '',
|
|
1367
|
+
content: '',
|
|
1368
|
+
media: [],
|
|
1369
|
+
})
|
|
1370
|
+
.subscribe({
|
|
1371
|
+
next: (res) => {
|
|
1372
|
+
const detail = res.data;
|
|
1373
|
+
this.course.details.push({
|
|
1374
|
+
id: detail.id,
|
|
1375
|
+
title: '',
|
|
1376
|
+
description: '',
|
|
1377
|
+
content: '',
|
|
1378
|
+
media: [],
|
|
1379
|
+
});
|
|
1380
|
+
},
|
|
1381
|
+
error: (e) => {
|
|
1382
|
+
this.snackBar.open(e.message);
|
|
1383
|
+
},
|
|
1384
|
+
});
|
|
1385
|
+
}
|
|
1386
|
+
addSchedule() {
|
|
1387
|
+
if (!this.course.schedule) {
|
|
1388
|
+
this.course.schedule = [];
|
|
1389
|
+
}
|
|
1390
|
+
this.course.schedule.push({
|
|
1391
|
+
title: '',
|
|
1392
|
+
content: '',
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
addPricing() {
|
|
1396
|
+
if (!this.course.pricing) {
|
|
1397
|
+
this.course.pricing = [];
|
|
1398
|
+
}
|
|
1399
|
+
this.course.pricing.push({
|
|
1400
|
+
min: 0,
|
|
1401
|
+
max: 0,
|
|
1402
|
+
total: 0,
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
onSelectionChange(event) {
|
|
1406
|
+
this.selectedCategoyIds = event.value;
|
|
1407
|
+
}
|
|
1408
|
+
onStepperChange(event) {
|
|
1409
|
+
this.lastStepper = event.selectedIndex === 3;
|
|
1410
|
+
this.firstStepper = event.selectedIndex === 0;
|
|
1411
|
+
}
|
|
1412
|
+
previous() {
|
|
1413
|
+
this.stepper().previous();
|
|
1414
|
+
}
|
|
1415
|
+
next() {
|
|
1416
|
+
this.stepper().next();
|
|
1417
|
+
}
|
|
1418
|
+
onDetailMediaUpload(event) { }
|
|
1419
|
+
onDetailMediaDelete(event) { }
|
|
1420
|
+
onDetailSave(event) { }
|
|
1421
|
+
onDetailDelete(detail) {
|
|
1422
|
+
this.courseService.deleteDetail(this.course.id, detail.id).subscribe({
|
|
1423
|
+
next: (res) => {
|
|
1424
|
+
this.snackBar.open(res.message);
|
|
1425
|
+
remove(this.details, {
|
|
1426
|
+
id: detail.id,
|
|
1427
|
+
});
|
|
1428
|
+
},
|
|
1429
|
+
error: (e) => {
|
|
1430
|
+
this.snackBar.open(e.message);
|
|
1431
|
+
},
|
|
1432
|
+
});
|
|
659
1433
|
}
|
|
660
1434
|
onImageClick(i) {
|
|
661
1435
|
const dialogRef = this.dialog.open(MediaPreviewDialogComponent, {
|
|
@@ -665,68 +1439,182 @@ class CourseMediaComponent {
|
|
|
665
1439
|
width: '80%',
|
|
666
1440
|
panelClass: 'full-screen-modal',
|
|
667
1441
|
data: {
|
|
668
|
-
media: this.media,
|
|
1442
|
+
media: this.course.media,
|
|
669
1443
|
selected: i,
|
|
670
1444
|
},
|
|
671
1445
|
});
|
|
672
|
-
dialogRef.afterClosed().subscribe((result) => { });
|
|
673
1446
|
}
|
|
674
|
-
|
|
675
|
-
|
|
1447
|
+
onUpload(event) {
|
|
1448
|
+
const file = event.target.files[0];
|
|
1449
|
+
if (file) {
|
|
1450
|
+
const reader = new FileReader();
|
|
1451
|
+
reader.readAsDataURL(file);
|
|
1452
|
+
reader.onload = () => {
|
|
1453
|
+
if (this.course.media) {
|
|
1454
|
+
this.course.media.push({
|
|
1455
|
+
url: reader.result,
|
|
1456
|
+
alt: 'upload image',
|
|
1457
|
+
});
|
|
1458
|
+
}
|
|
1459
|
+
else {
|
|
1460
|
+
this.course.media = [];
|
|
1461
|
+
this.course.media.push({
|
|
1462
|
+
url: reader.result,
|
|
1463
|
+
alt: 'upload image',
|
|
1464
|
+
});
|
|
1465
|
+
}
|
|
1466
|
+
this.isUploading = true;
|
|
1467
|
+
const formData = new FormData();
|
|
1468
|
+
formData.append('file', file);
|
|
1469
|
+
this.courseService.upload(formData).subscribe({
|
|
1470
|
+
next: (res) => {
|
|
1471
|
+
this.isUploading = false;
|
|
1472
|
+
const index = findLastIndex(this.course.media);
|
|
1473
|
+
// Replace item at index using native splice
|
|
1474
|
+
this.course.media.splice(index, 1, res.data);
|
|
1475
|
+
},
|
|
1476
|
+
error: (e) => {
|
|
1477
|
+
this.isUploading = false;
|
|
1478
|
+
this.snackBar.open('上传失败: ' + e.message);
|
|
1479
|
+
},
|
|
1480
|
+
});
|
|
1481
|
+
};
|
|
1482
|
+
reader.onerror = (error) => {
|
|
1483
|
+
this.isUploading = false;
|
|
1484
|
+
};
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseEditDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: CategoryService }, { token: CourseService }, { token: i3$3.MatSnackBar }, { token: i1$2.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1488
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseEditDialogComponent, isStandalone: true, selector: "rolatech-course-edit-dialog", viewQueries: [{ propertyName: "stepper", first: true, predicate: MatStepper, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto\">\n <mat-stepper #stepper (selectionChange)=\"onStepperChange($event)\">\n <mat-step [editable]=\"true\">\n <form #infoForm=\"ngForm\" class=\"py-3\">\n <ng-template matStepLabel>\u57FA\u672C\u4FE1\u606F</ng-template>\n <div class=\"flex flex-col\">\n <mat-form-field appearance=\"fill\">\n <mat-label> \u8BFE\u7A0B\u540D\u79F0 </mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"course.name\" name=\"name\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label> \u8BFE\u7A0B\u63CF\u8FF0 </mat-label>\n <textarea\n matInput\n type=\"text\"\n [(ngModel)]=\"course.description\"\n name=\"description\"\n required\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"3\"\n ></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"fill\" ngModelGroup=\"categories\">\n <mat-label>\u5206\u7C7B</mat-label>\n <mat-select\n multiple\n name=\"id\"\n [compareWith]=\"compareFn\"\n [(ngModel)]=\"course.categories\"\n #select=\"matSelect\"\n (selectionChange)=\"onSelectionChange($event)\"\n >\n @for (item of categories; track item) {\n <mat-option [value]=\"item\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>\u7C7B\u578B</mat-label>\n <mat-select name=\"type\" [(ngModel)]=\"course.type\">\n @for (item of courseType; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (course.type.toString() !== 'ONLINE') {\n <mat-form-field appearance=\"fill\" ngModelGroup=\"classroom\">\n <mat-label>\u6559\u5BA4</mat-label>\n <mat-select [(ngModel)]=\"course.classroom\" name=\"id\">\n @for (classroom of classrooms; track classroom) {\n <mat-option [value]=\"classroom.id\">\n <div class=\"flex gap-3\">\n <span>{{ classroom.name }}</span>\n <span> {{ classroom.address }}</span>\n </div>\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n </div>\n <div>\n <div class=\"py-3\">\n <h2>\u56FE\u7247\u4FE1\u606F</h2>\n </div>\n <rolatech-media-list (upload)=\"onUpload($event)\" [isUploading]=\"isUploading\">\n @for (item of course.media; track item; let i = $index) {\n <rolatech-media-list-item [media]=\"item\" (mediaItemClick)=\"onImageClick(i)\"></rolatech-media-list-item>\n }\n </rolatech-media-list>\n </div>\n </form>\n </mat-step>\n <mat-step [editable]=\"true\">\n <form #detailForm=\"ngForm\" class=\"py-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of course.details; track item) {\n <rolatech-detail-item\n [detail]=\"item\"\n (upload)=\"onDetailMediaUpload($event)\"\n (deleteMedia)=\"onDetailMediaDelete($event)\"\n (save)=\"onDetailSave($event)\"\n (delete)=\"onDetailDelete($event)\"\n ></rolatech-detail-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addDetail()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BE6\u60C5</span>\n </button>\n </div>\n </form>\n </mat-step>\n <mat-step [editable]=\"true\">\n <form #pricingForm=\"ngForm\" class=\"py-3\">\n <ng-template matStepLabel>\u4EF7\u683C</ng-template>\n <div>\n @for (item of course.pricing; track item) {\n <rolatech-pricing-item [pricing]=\"item\"> </rolatech-pricing-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addPricing()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u4EF7\u683C</span>\n </button>\n </div>\n </div>\n </form>\n </mat-step>\n <mat-step>\n <form #scheduleForm=\"ngForm\">\n <ng-template matStepLabel>\u8BFE\u8868</ng-template>\n <div class=\"flex flex-col\">\n @for (item of course.schedule; track item) {\n <rolatech-schedule-item [value]=\"item\"></rolatech-schedule-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addSchedule()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BFE\u8868</span>\n </button>\n </div>\n </div>\n </form>\n </mat-step>\n </mat-stepper>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n @if (!firstStepper) {\n <button mat-button mat-button (click)=\"previous()\">\u4E0A\u4E00\u6B65</button>\n }\n @if (!lastStepper) {\n <button mat-button (click)=\"next()\">\u4E0B\u4E00\u6B65</button>\n }\n @if (lastStepper) {\n <button mat-button [mat-dialog-close]=\"course\" cdkFocusInitial>\u4FDD\u5B58</button>\n }\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatStepperModule }, { kind: "component", type: i7$1.MatStep, selector: "mat-step", inputs: ["color"], exportAs: ["matStep"] }, { kind: "directive", type: i7$1.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: i7$1.MatStepper, selector: "mat-stepper, mat-vertical-stepper, mat-horizontal-stepper, [matStepper]", inputs: ["disableRipple", "color", "labelPosition", "headerPosition", "animationDuration"], outputs: ["animationDone"], exportAs: ["matStepper", "matVerticalStepper", "matHorizontalStepper"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i6.NgModelGroup, selector: "[ngModelGroup]", inputs: ["ngModelGroup"], exportAs: ["ngModelGroup"] }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i3$1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "ngmodule", type: TextFieldModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i7.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "component", type: MediaListComponent, selector: "rolatech-media-list", inputs: ["isUploading", "media", "showAdd"], outputs: ["mediaItemClick", "upload"] }, { kind: "component", type: MediaListItemComponent, selector: "rolatech-media-list-item", inputs: ["media", "uploadProgress"], outputs: ["mediaItemClick", "deleteMedia"] }, { kind: "component", type: DetailItemComponent, selector: "rolatech-detail-item", inputs: ["isUploading", "detail", "shadow", "actions", "selectMedia"], outputs: ["upload", "delete", "save", "deleteMedia"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: PricingItemComponent, selector: "rolatech-pricing-item", inputs: ["actions", "shadow", "pricing"], outputs: ["pricingChange", "delete", "save"] }, { kind: "component", type: ScheduleItemComponent, selector: "rolatech-schedule-item", inputs: ["value", "actions", "shadow"], outputs: ["delete", "save"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }] }); }
|
|
676
1489
|
}
|
|
677
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type:
|
|
1490
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseEditDialogComponent, decorators: [{
|
|
678
1491
|
type: Component,
|
|
679
|
-
args: [{ selector: 'rolatech-course-
|
|
680
|
-
|
|
1492
|
+
args: [{ selector: 'rolatech-course-edit-dialog', standalone: true, imports: [
|
|
1493
|
+
MatIconModule,
|
|
1494
|
+
MatDividerModule,
|
|
1495
|
+
MatStepperModule,
|
|
1496
|
+
FormsModule,
|
|
1497
|
+
MatFormFieldModule,
|
|
1498
|
+
MatInputModule,
|
|
1499
|
+
TextFieldModule,
|
|
1500
|
+
MatSelectModule,
|
|
1501
|
+
MatOptionModule,
|
|
1502
|
+
MediaListComponent,
|
|
1503
|
+
MediaListItemComponent,
|
|
1504
|
+
DetailItemComponent,
|
|
1505
|
+
MatButtonModule,
|
|
1506
|
+
PricingItemComponent,
|
|
1507
|
+
ScheduleItemComponent,
|
|
1508
|
+
MatDialogClose,
|
|
1509
|
+
], template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto\">\n <mat-stepper #stepper (selectionChange)=\"onStepperChange($event)\">\n <mat-step [editable]=\"true\">\n <form #infoForm=\"ngForm\" class=\"py-3\">\n <ng-template matStepLabel>\u57FA\u672C\u4FE1\u606F</ng-template>\n <div class=\"flex flex-col\">\n <mat-form-field appearance=\"fill\">\n <mat-label> \u8BFE\u7A0B\u540D\u79F0 </mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"course.name\" name=\"name\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label> \u8BFE\u7A0B\u63CF\u8FF0 </mat-label>\n <textarea\n matInput\n type=\"text\"\n [(ngModel)]=\"course.description\"\n name=\"description\"\n required\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"3\"\n ></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"fill\" ngModelGroup=\"categories\">\n <mat-label>\u5206\u7C7B</mat-label>\n <mat-select\n multiple\n name=\"id\"\n [compareWith]=\"compareFn\"\n [(ngModel)]=\"course.categories\"\n #select=\"matSelect\"\n (selectionChange)=\"onSelectionChange($event)\"\n >\n @for (item of categories; track item) {\n <mat-option [value]=\"item\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>\u7C7B\u578B</mat-label>\n <mat-select name=\"type\" [(ngModel)]=\"course.type\">\n @for (item of courseType; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (course.type.toString() !== 'ONLINE') {\n <mat-form-field appearance=\"fill\" ngModelGroup=\"classroom\">\n <mat-label>\u6559\u5BA4</mat-label>\n <mat-select [(ngModel)]=\"course.classroom\" name=\"id\">\n @for (classroom of classrooms; track classroom) {\n <mat-option [value]=\"classroom.id\">\n <div class=\"flex gap-3\">\n <span>{{ classroom.name }}</span>\n <span> {{ classroom.address }}</span>\n </div>\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n </div>\n <div>\n <div class=\"py-3\">\n <h2>\u56FE\u7247\u4FE1\u606F</h2>\n </div>\n <rolatech-media-list (upload)=\"onUpload($event)\" [isUploading]=\"isUploading\">\n @for (item of course.media; track item; let i = $index) {\n <rolatech-media-list-item [media]=\"item\" (mediaItemClick)=\"onImageClick(i)\"></rolatech-media-list-item>\n }\n </rolatech-media-list>\n </div>\n </form>\n </mat-step>\n <mat-step [editable]=\"true\">\n <form #detailForm=\"ngForm\" class=\"py-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of course.details; track item) {\n <rolatech-detail-item\n [detail]=\"item\"\n (upload)=\"onDetailMediaUpload($event)\"\n (deleteMedia)=\"onDetailMediaDelete($event)\"\n (save)=\"onDetailSave($event)\"\n (delete)=\"onDetailDelete($event)\"\n ></rolatech-detail-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addDetail()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BE6\u60C5</span>\n </button>\n </div>\n </form>\n </mat-step>\n <mat-step [editable]=\"true\">\n <form #pricingForm=\"ngForm\" class=\"py-3\">\n <ng-template matStepLabel>\u4EF7\u683C</ng-template>\n <div>\n @for (item of course.pricing; track item) {\n <rolatech-pricing-item [pricing]=\"item\"> </rolatech-pricing-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addPricing()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u4EF7\u683C</span>\n </button>\n </div>\n </div>\n </form>\n </mat-step>\n <mat-step>\n <form #scheduleForm=\"ngForm\">\n <ng-template matStepLabel>\u8BFE\u8868</ng-template>\n <div class=\"flex flex-col\">\n @for (item of course.schedule; track item) {\n <rolatech-schedule-item [value]=\"item\"></rolatech-schedule-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addSchedule()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BFE\u8868</span>\n </button>\n </div>\n </div>\n </form>\n </mat-step>\n </mat-stepper>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n @if (!firstStepper) {\n <button mat-button mat-button (click)=\"previous()\">\u4E0A\u4E00\u6B65</button>\n }\n @if (!lastStepper) {\n <button mat-button (click)=\"next()\">\u4E0B\u4E00\u6B65</button>\n }\n @if (lastStepper) {\n <button mat-button [mat-dialog-close]=\"course\" cdkFocusInitial>\u4FDD\u5B58</button>\n }\n </div>\n</div>\n" }]
|
|
1510
|
+
}], ctorParameters: () => [{ type: i1$2.MatDialogRef }, { type: undefined, decorators: [{
|
|
1511
|
+
type: Inject,
|
|
1512
|
+
args: [MAT_DIALOG_DATA]
|
|
1513
|
+
}] }, { type: CategoryService }, { type: CourseService }, { type: i3$3.MatSnackBar }, { type: i1$2.MatDialog }] });
|
|
681
1514
|
|
|
682
|
-
class
|
|
1515
|
+
class CourseDetailsComponent {
|
|
683
1516
|
constructor() {
|
|
684
|
-
this.
|
|
1517
|
+
this.details = input.required();
|
|
1518
|
+
this.instructor = input();
|
|
1519
|
+
this.username = input();
|
|
1520
|
+
this.el = inject(ElementRef);
|
|
1521
|
+
this.viewportScroller = inject(ViewportScroller);
|
|
1522
|
+
this.platformId = inject(PLATFORM_ID);
|
|
1523
|
+
this.show = false;
|
|
1524
|
+
this.mediaIndex = 0;
|
|
1525
|
+
this.finalSchedule = [];
|
|
685
1526
|
}
|
|
686
|
-
|
|
687
|
-
|
|
1527
|
+
ngOnInit() { }
|
|
1528
|
+
onClickScroller(id) {
|
|
1529
|
+
this.viewportScroller.scrollToAnchor(id);
|
|
1530
|
+
}
|
|
1531
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1532
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseDetailsComponent, isStandalone: true, selector: "rolatech-course-details", inputs: { details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: true, transformFunction: null }, instructor: { classPropertyName: "instructor", publicName: "instructor", isSignal: true, isRequired: false, transformFunction: null }, username: { classPropertyName: "username", publicName: "username", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"py-3\" id=\"details\">\n <div class=\"text-xl font-medium py-2\">\u8BE6\u60C5</div>\n @if (details()) {\n @for (detail of details(); track $index) {\n <div>\n @if (detail.title) {\n <div class=\"py-3 flex items-center gap-3\">\n <span class=\"h-4 w-1 bg-orange-500 inline-block\"></span>\n <span class=\"text-lg font-medium py-1\"> {{ detail.title }}</span>\n </div>\n }\n @if (detail.content) {\n <div>\n {{ detail.content }}\n </div>\n }\n @if (detail.media) {\n <div class=\"w-80%\">\n @for (item of detail.media; track item) {\n <div class=\"py-3\">\n <img class=\"object-cover\" [src]=\"item.url + '?imageMogr2/format/avif'\" />\n </div>\n }\n </div>\n }\n </div>\n }\n }\n</div>\n", styles: [""] }); }
|
|
688
1533
|
}
|
|
689
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type:
|
|
1534
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseDetailsComponent, decorators: [{
|
|
690
1535
|
type: Component,
|
|
691
|
-
args: [{ selector: 'rolatech-course-
|
|
1536
|
+
args: [{ selector: 'rolatech-course-details', standalone: true, imports: [], template: "<div class=\"py-3\" id=\"details\">\n <div class=\"text-xl font-medium py-2\">\u8BE6\u60C5</div>\n @if (details()) {\n @for (detail of details(); track $index) {\n <div>\n @if (detail.title) {\n <div class=\"py-3 flex items-center gap-3\">\n <span class=\"h-4 w-1 bg-orange-500 inline-block\"></span>\n <span class=\"text-lg font-medium py-1\"> {{ detail.title }}</span>\n </div>\n }\n @if (detail.content) {\n <div>\n {{ detail.content }}\n </div>\n }\n @if (detail.media) {\n <div class=\"w-80%\">\n @for (item of detail.media; track item) {\n <div class=\"py-3\">\n <img class=\"object-cover\" [src]=\"item.url + '?imageMogr2/format/avif'\" />\n </div>\n }\n </div>\n }\n </div>\n }\n }\n</div>\n" }]
|
|
692
1537
|
}] });
|
|
693
1538
|
|
|
694
|
-
class
|
|
1539
|
+
class CourseMediaOwnerRendererComponent {
|
|
695
1540
|
constructor() {
|
|
696
|
-
this.
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
// this.formatSchedule();
|
|
1541
|
+
this.name = input();
|
|
1542
|
+
this.avatar = input();
|
|
1543
|
+
this.username = input();
|
|
700
1544
|
}
|
|
701
|
-
|
|
702
|
-
static { this.ɵ
|
|
703
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseScheduleComponent, isStandalone: true, selector: "rolatech-course-schedule", inputs: { schedule: { classPropertyName: "schedule", publicName: "schedule", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<!-- \u8BFE\u8868 -->\n@if (schedule()) {\n <div class=\"py-3\" id=\"schedule\">\n <div class=\"text-xl font-medium py-2\">\u8BFE\u8868</div>\n @for (item of schedule(); track $index) {\n <mat-expansion-panel #panel [class.mat-elevation-z0]=\"true\" hideToggle [expanded]=\"$index === 0\">\n <mat-expansion-panel-header class=\"bg-red\">\n <mat-panel-title>\n <span class=\"text-[1rem]\">{{ item.title }}</span>\n </mat-panel-title>\n <mat-icon\n class=\"toggle-icon\"\n style=\"transition-duration:.5s;transform: {{ panel.expanded ? 'rotate(180deg)' : 'rotate(0deg)' }};\"\n >expand_more</mat-icon\n >\n </mat-expansion-panel-header>\n <div class=\"bg-white\">\n <div class=\"text-gray-600 font-thin pt-2\">\n <span>{{ item.startAt }} - {{ item.endAt }}</span>\n </div>\n <div class=\"py-3\">\n <div>{{ item.content }}</div>\n </div>\n </div>\n </mat-expansion-panel>\n }\n </div>\n}\n", styles: ["mat-expansion-panel{margin:0!important}.mat-expansion-panel-header{padding:0 16px;background:#f3f4f6!important}.mat-expansion-panel .mat-expansion-panel-header:not([aria-disabled=true]):hover{background:#dee0e2}.mat-expansion-panel-header{height:56px!important}.mat-expansion-panel .mat-expansion-panel-header{margin-bottom:8px;height:44px!important;padding:0 12px!important}.mat-expansion-panel-header .mat-expanded{height:56px!important}mat-expansion-panel .mat-expansion-panel-body{padding:0 8px 8px 4px!important}\n"], dependencies: [{ kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i1$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i1$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i1$1.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
|
|
1545
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseMediaOwnerRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1546
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseMediaOwnerRendererComponent, isStandalone: true, selector: "rolatech-course-media-owner-renderer", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, avatar: { classPropertyName: "avatar", publicName: "avatar", isSignal: true, isRequired: false, transformFunction: null }, username: { classPropertyName: "username", publicName: "username", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"flex flex-row items-center\">\n <div class=\"flex mr-3 gap-2 items-center\">\n @if (avatar()) {\n <div class=\"cursor-pointer\" [routerLink]=\"['/instructors/', '@' + username()]\">\n <img [src]=\"avatar()\" class=\"w-11 h-11 rounded-full\" />\n </div>\n } @else {\n <div class=\"w-11 h-11 rounded-full bg-orange-600\"></div>\n }\n <div class=\"flex items-center text-lg font-bold cursor-pointer\">\n <a [routerLink]=\"['/instructors/', '@' + username()]\">\n <span>{{ name() }}</span>\n </a>\n <mat-icon color=\"primary\">verified</mat-icon>\n </div>\n </div>\n</div>\n", styles: ["mat-icon{transform:scale(.8)}\n"], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "directive", type: i1$3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
|
|
704
1547
|
}
|
|
705
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type:
|
|
1548
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseMediaOwnerRendererComponent, decorators: [{
|
|
706
1549
|
type: Component,
|
|
707
|
-
args: [{ selector: 'rolatech-course-
|
|
1550
|
+
args: [{ selector: 'rolatech-course-media-owner-renderer', standalone: true, imports: [AngularCommonModule, MatIconModule], template: "<div class=\"flex flex-row items-center\">\n <div class=\"flex mr-3 gap-2 items-center\">\n @if (avatar()) {\n <div class=\"cursor-pointer\" [routerLink]=\"['/instructors/', '@' + username()]\">\n <img [src]=\"avatar()\" class=\"w-11 h-11 rounded-full\" />\n </div>\n } @else {\n <div class=\"w-11 h-11 rounded-full bg-orange-600\"></div>\n }\n <div class=\"flex items-center text-lg font-bold cursor-pointer\">\n <a [routerLink]=\"['/instructors/', '@' + username()]\">\n <span>{{ name() }}</span>\n </a>\n <mat-icon color=\"primary\">verified</mat-icon>\n </div>\n </div>\n</div>\n", styles: ["mat-icon{transform:scale(.8)}\n"] }]
|
|
708
1551
|
}] });
|
|
709
1552
|
|
|
710
|
-
class
|
|
1553
|
+
class CourseCategoryComponent extends BaseComponent {
|
|
711
1554
|
constructor() {
|
|
712
|
-
|
|
713
|
-
this.
|
|
714
|
-
this.
|
|
715
|
-
this.
|
|
716
|
-
this.
|
|
1555
|
+
super(...arguments);
|
|
1556
|
+
this.categoryService = inject(CategoryService);
|
|
1557
|
+
this.courseService = inject(CourseService);
|
|
1558
|
+
this.courses = [];
|
|
1559
|
+
this.categories = [];
|
|
1560
|
+
this.loading = false;
|
|
717
1561
|
}
|
|
718
|
-
|
|
719
|
-
this.
|
|
1562
|
+
ngOnInit() {
|
|
1563
|
+
this.findAllCategories();
|
|
1564
|
+
this.route.paramMap.subscribe((params) => {
|
|
1565
|
+
const id = params.get('id');
|
|
1566
|
+
this.findCategoryById(id);
|
|
1567
|
+
this.findCoursesByCategoryId(id);
|
|
1568
|
+
});
|
|
720
1569
|
}
|
|
721
|
-
|
|
722
|
-
this.
|
|
1570
|
+
findAllCategories() {
|
|
1571
|
+
this.categoryService.find({}).subscribe({
|
|
1572
|
+
next: (res) => {
|
|
1573
|
+
this.categories = res.data;
|
|
1574
|
+
},
|
|
1575
|
+
});
|
|
723
1576
|
}
|
|
724
|
-
|
|
725
|
-
|
|
1577
|
+
findCategoryById(id) {
|
|
1578
|
+
this.categoryService.get(id).subscribe({
|
|
1579
|
+
next: (res) => {
|
|
1580
|
+
this.category = res.data;
|
|
1581
|
+
},
|
|
1582
|
+
});
|
|
1583
|
+
}
|
|
1584
|
+
findAllCourses() {
|
|
1585
|
+
this.courseService.find({}).subscribe({
|
|
1586
|
+
next: (res) => {
|
|
1587
|
+
this.courses = res.data;
|
|
1588
|
+
},
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
findCoursesByCategoryId(id) {
|
|
1592
|
+
this.loading = true;
|
|
1593
|
+
const options = {
|
|
1594
|
+
filter: `categories:${id},published:true`,
|
|
1595
|
+
};
|
|
1596
|
+
this.courseService.find(options).subscribe({
|
|
1597
|
+
next: (res) => {
|
|
1598
|
+
this.courses = res.data;
|
|
1599
|
+
this.loading = false;
|
|
1600
|
+
},
|
|
1601
|
+
error: (error) => {
|
|
1602
|
+
this.loading = false;
|
|
1603
|
+
},
|
|
1604
|
+
});
|
|
1605
|
+
}
|
|
1606
|
+
loadCoursesByCategory(item) {
|
|
1607
|
+
// [routerLink] = "['../../', item.id]";
|
|
1608
|
+
this.router.navigate([`../../${item.id}`], {
|
|
1609
|
+
relativeTo: this.route,
|
|
1610
|
+
});
|
|
1611
|
+
}
|
|
1612
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseCategoryComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
1613
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseCategoryComponent, isStandalone: true, selector: "rolatech-course-category", usesInheritance: true, ngImport: i0, template: "<div>\n @if (category) {\n <div class=\"p-3 hidden sm:block text-2xl font-medium\">{{ category.name }}</div>\n } @else {\n <div class=\"flex flex-row animate-pulse w-full\">\n <div class=\"h-4 bg-slate-200 rounded col-span-2\"></div>\n </div>\n }\n @if (loading) {\n @for (number of [0, 1, 2, 3, 4, 5]; track number) {\n <div class=\"flex flex-row animate-pulse mt-3 mr-4 cursor-pointer w-full\">\n <div class=\"h-fit w-2/5 sm:w-1/4 aspect-video bg-gray-200 rounded-lg\"></div>\n <div class=\"w-3/5 sm:w-3/4 ml-3 py-1 flex flex-col justify-between\">\n <div class=\"space-y-3\">\n <div class=\"h-4 bg-slate-200 rounded col-span-2\"></div>\n <div class=\"h-2 bg-slate-200 rounded col-span-1\"></div>\n <div class=\"h-2 bg-slate-200 rounded col-span-1 py-1\"></div>\n </div>\n <div>\n <div class=\"h-2 bg-slate-200 rounded col-span-2 py-1\"></div>\n </div>\n </div>\n </div>\n }\n } @else {\n @for (item of courses; track item) {\n <div\n class=\"py-2 cursor-pointer min-w-[80%] md:min-w-[25%] sm:min-w-[33%] hover:bg-gray-100\"\n [routerLink]=\"['../../', item.id]\"\n >\n <rolatech-course-item [course]=\"item\"></rolatech-course-item>\n </div>\n }\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "directive", type: i1$3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: CourseItemComponent, selector: "rolatech-course-item", inputs: ["course", "row"] }] }); }
|
|
726
1614
|
}
|
|
727
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type:
|
|
1615
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseCategoryComponent, decorators: [{
|
|
728
1616
|
type: Component,
|
|
729
|
-
args: [{
|
|
1617
|
+
args: [{ standalone: true, imports: [AngularCommonModule, AngularComponentsModule, CourseItemComponent], selector: 'rolatech-course-category', template: "<div>\n @if (category) {\n <div class=\"p-3 hidden sm:block text-2xl font-medium\">{{ category.name }}</div>\n } @else {\n <div class=\"flex flex-row animate-pulse w-full\">\n <div class=\"h-4 bg-slate-200 rounded col-span-2\"></div>\n </div>\n }\n @if (loading) {\n @for (number of [0, 1, 2, 3, 4, 5]; track number) {\n <div class=\"flex flex-row animate-pulse mt-3 mr-4 cursor-pointer w-full\">\n <div class=\"h-fit w-2/5 sm:w-1/4 aspect-video bg-gray-200 rounded-lg\"></div>\n <div class=\"w-3/5 sm:w-3/4 ml-3 py-1 flex flex-col justify-between\">\n <div class=\"space-y-3\">\n <div class=\"h-4 bg-slate-200 rounded col-span-2\"></div>\n <div class=\"h-2 bg-slate-200 rounded col-span-1\"></div>\n <div class=\"h-2 bg-slate-200 rounded col-span-1 py-1\"></div>\n </div>\n <div>\n <div class=\"h-2 bg-slate-200 rounded col-span-2 py-1\"></div>\n </div>\n </div>\n </div>\n }\n } @else {\n @for (item of courses; track item) {\n <div\n class=\"py-2 cursor-pointer min-w-[80%] md:min-w-[25%] sm:min-w-[33%] hover:bg-gray-100\"\n [routerLink]=\"['../../', item.id]\"\n >\n <rolatech-course-item [course]=\"item\"></rolatech-course-item>\n </div>\n }\n }\n</div>\n" }]
|
|
730
1618
|
}] });
|
|
731
1619
|
|
|
732
1620
|
class CourseDetailComponent extends BaseComponent {
|
|
@@ -909,7 +1797,7 @@ class CourseIndexComponent extends BaseComponent {
|
|
|
909
1797
|
});
|
|
910
1798
|
}
|
|
911
1799
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseIndexComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
912
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseIndexComponent, isStandalone: true, selector: "rolatech-course-index", usesInheritance: true, ngImport: i0, template: "<div class=\"min-w-[320px] max-w-[1120px] m-auto\">\n <div class=\"p-3 hidden sm:block text-2xl font-medium\">\u5168\u90E8\u8BFE\u7A0B</div>\n @if (loading) {\n @for (number of [0, 1, 2, 3, 4, 5]; track number) {\n <div class=\"flex flex-row animate-pulse mt-3 mr-4 cursor-pointer w-full\">\n <div class=\"h-fit w-2/5 sm:w-1/4 aspect-video bg-gray-200 rounded-lg\"></div>\n <div class=\"w-3/5 sm:w-3/4 ml-3 py-1 flex flex-col justify-between\">\n <div class=\"space-y-3\">\n <div class=\"h-4 bg-slate-200 rounded col-span-2\"></div>\n <div class=\"h-2 bg-slate-200 rounded col-span-1\"></div>\n <div class=\"h-2 bg-slate-200 rounded col-span-1 py-1\"></div>\n </div>\n <div>\n <div class=\"h-2 bg-slate-200 rounded col-span-2 py-1\"></div>\n </div>\n </div>\n </div>\n }\n } @else {\n @for (item of courses; track $index) {\n <div\n class=\"py-2 cursor-pointer min-w-[80%] md:min-w-[25%] sm:min-w-[33%] hover:bg-gray-100\"\n [routerLink]=\"['./', item.id]\"\n >\n <rolatech-course-item [course]=\"item\"></rolatech-course-item>\n </div>\n }\n }\n</div>\n", styles: ["img:before{border-radius:12px}\n"], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: CourseItemComponent, selector: "rolatech-course-item", inputs: ["course", "row"] }] }); }
|
|
1800
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseIndexComponent, isStandalone: true, selector: "rolatech-course-index", usesInheritance: true, ngImport: i0, template: "<div class=\"min-w-[320px] max-w-[1120px] m-auto\">\n <div class=\"p-3 hidden sm:block text-2xl font-medium\">\u5168\u90E8\u8BFE\u7A0B</div>\n @if (loading) {\n @for (number of [0, 1, 2, 3, 4, 5]; track number) {\n <div class=\"flex flex-row animate-pulse mt-3 mr-4 cursor-pointer w-full\">\n <div class=\"h-fit w-2/5 sm:w-1/4 aspect-video bg-gray-200 rounded-lg\"></div>\n <div class=\"w-3/5 sm:w-3/4 ml-3 py-1 flex flex-col justify-between\">\n <div class=\"space-y-3\">\n <div class=\"h-4 bg-slate-200 rounded col-span-2\"></div>\n <div class=\"h-2 bg-slate-200 rounded col-span-1\"></div>\n <div class=\"h-2 bg-slate-200 rounded col-span-1 py-1\"></div>\n </div>\n <div>\n <div class=\"h-2 bg-slate-200 rounded col-span-2 py-1\"></div>\n </div>\n </div>\n </div>\n }\n } @else {\n @for (item of courses; track $index) {\n <div\n class=\"py-2 cursor-pointer min-w-[80%] md:min-w-[25%] sm:min-w-[33%] hover:bg-gray-100\"\n [routerLink]=\"['./', item.id]\"\n >\n <rolatech-course-item [course]=\"item\"></rolatech-course-item>\n </div>\n }\n }\n</div>\n", styles: ["img:before{border-radius:12px}\n"], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "directive", type: i1$3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: CourseItemComponent, selector: "rolatech-course-item", inputs: ["course", "row"] }] }); }
|
|
913
1801
|
}
|
|
914
1802
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseIndexComponent, decorators: [{
|
|
915
1803
|
type: Component,
|
|
@@ -952,27 +1840,13 @@ class CourseLayoutComponent extends BaseComponent {
|
|
|
952
1840
|
}
|
|
953
1841
|
nextCategory() { }
|
|
954
1842
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseLayoutComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
955
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseLayoutComponent, isStandalone: true, selector: "rolatech-course-layout", usesInheritance: true, ngImport: i0, template: "@if (categories) {\n <rolatech-app-container>\n <div class=\"flex flex-col sm:flex-row min-w-[320px] max-w-[1280px] m-auto\">\n <div class=\"h-14 sm:h-auto min-w-[256px] sm:py-3\">\n <div class=\"hidden sm:block text-2xl font-medium p-3\">\u5206\u7C7B</div>\n <div\n class=\"flex flex-row sm:flex-col sm:h-full items-center sm:items-start h-14 overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <a\n class=\"cursor-pointer h-8 sm:hover:bg-gray-200 hover:rounded flex items-center sm:mb-1\"\n routerLinkActive=\"active\"\n routerLink=\"/courses\"\n [routerLinkActiveOptions]=\"{ exact: true }\"\n >\n <span class=\"px-3 text-md sm:text-lg\">\u5168\u90E8</span>\n </a>\n @for (category of categories; track category; let index = $index) {\n <a\n class=\"cursor-pointer h-8 sm:hover:bg-gray-200 hover:rounded flex items-center sm:mb-1\"\n routerLinkActive=\"active\"\n [routerLink]=\"['../courses/categories/', category.id]\"\n [routerLinkActiveOptions]=\"{ exact: true }\"\n >\n <span class=\"px-3 text-md sm:text-lg\">{{ category.name }}</span>\n </a>\n }\n </div>\n </div>\n <div class=\"w-full sm:py-3\">\n <router-outlet></router-outlet>\n </div>\n </div>\n </rolatech-app-container>\n}\n", styles: [".active{border-radius:8px;color:#ff4500}@media (max-width: 600px){.active{border-radius:8px;background-color:#303030;color:#fff}}.scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: i1.RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: AppContainerComponent, selector: "rolatech-app-container" }] }); }
|
|
1843
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseLayoutComponent, isStandalone: true, selector: "rolatech-course-layout", usesInheritance: true, ngImport: i0, template: "@if (categories) {\n <rolatech-app-container>\n <div class=\"flex flex-col sm:flex-row min-w-[320px] max-w-[1280px] m-auto\">\n <div class=\"h-14 sm:h-auto min-w-[256px] sm:py-3\">\n <div class=\"hidden sm:block text-2xl font-medium p-3\">\u5206\u7C7B</div>\n <div\n class=\"flex flex-row sm:flex-col sm:h-full items-center sm:items-start h-14 overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <a\n class=\"cursor-pointer h-8 sm:hover:bg-gray-200 hover:rounded flex items-center sm:mb-1\"\n routerLinkActive=\"active\"\n routerLink=\"/courses\"\n [routerLinkActiveOptions]=\"{ exact: true }\"\n >\n <span class=\"px-3 text-md sm:text-lg\">\u5168\u90E8</span>\n </a>\n @for (category of categories; track category; let index = $index) {\n <a\n class=\"cursor-pointer h-8 sm:hover:bg-gray-200 hover:rounded flex items-center sm:mb-1\"\n routerLinkActive=\"active\"\n [routerLink]=\"['../courses/categories/', category.id]\"\n [routerLinkActiveOptions]=\"{ exact: true }\"\n >\n <span class=\"px-3 text-md sm:text-lg\">{{ category.name }}</span>\n </a>\n }\n </div>\n </div>\n <div class=\"w-full sm:py-3\">\n <router-outlet></router-outlet>\n </div>\n </div>\n </rolatech-app-container>\n}\n", styles: [".active{border-radius:8px;color:#ff4500}@media (max-width: 600px){.active{border-radius:8px;background-color:#303030;color:#fff}}.scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "directive", type: i1$3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1$3.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: i1$3.RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: AppContainerComponent, selector: "rolatech-app-container" }] }); }
|
|
956
1844
|
}
|
|
957
1845
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseLayoutComponent, decorators: [{
|
|
958
1846
|
type: Component,
|
|
959
1847
|
args: [{ standalone: true, imports: [AngularCommonModule, AngularComponentsModule, AppContainerComponent], selector: 'rolatech-course-layout', template: "@if (categories) {\n <rolatech-app-container>\n <div class=\"flex flex-col sm:flex-row min-w-[320px] max-w-[1280px] m-auto\">\n <div class=\"h-14 sm:h-auto min-w-[256px] sm:py-3\">\n <div class=\"hidden sm:block text-2xl font-medium p-3\">\u5206\u7C7B</div>\n <div\n class=\"flex flex-row sm:flex-col sm:h-full items-center sm:items-start h-14 overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <a\n class=\"cursor-pointer h-8 sm:hover:bg-gray-200 hover:rounded flex items-center sm:mb-1\"\n routerLinkActive=\"active\"\n routerLink=\"/courses\"\n [routerLinkActiveOptions]=\"{ exact: true }\"\n >\n <span class=\"px-3 text-md sm:text-lg\">\u5168\u90E8</span>\n </a>\n @for (category of categories; track category; let index = $index) {\n <a\n class=\"cursor-pointer h-8 sm:hover:bg-gray-200 hover:rounded flex items-center sm:mb-1\"\n routerLinkActive=\"active\"\n [routerLink]=\"['../courses/categories/', category.id]\"\n [routerLinkActiveOptions]=\"{ exact: true }\"\n >\n <span class=\"px-3 text-md sm:text-lg\">{{ category.name }}</span>\n </a>\n }\n </div>\n </div>\n <div class=\"w-full sm:py-3\">\n <router-outlet></router-outlet>\n </div>\n </div>\n </rolatech-app-container>\n}\n", styles: [".active{border-radius:8px;color:#ff4500}@media (max-width: 600px){.active{border-radius:8px;background-color:#303030;color:#fff}}.scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"] }]
|
|
960
1848
|
}] });
|
|
961
1849
|
|
|
962
|
-
class CourseMediaOwnerRendererComponent {
|
|
963
|
-
constructor() {
|
|
964
|
-
this.name = input();
|
|
965
|
-
this.avatar = input();
|
|
966
|
-
this.username = input();
|
|
967
|
-
}
|
|
968
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseMediaOwnerRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
969
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.0", type: CourseMediaOwnerRendererComponent, isStandalone: true, selector: "rolatech-course-media-owner-renderer", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, avatar: { classPropertyName: "avatar", publicName: "avatar", isSignal: true, isRequired: false, transformFunction: null }, username: { classPropertyName: "username", publicName: "username", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"flex flex-row items-center\">\n <div class=\"flex mr-3 gap-2 items-center\">\n @if (avatar()) {\n <div class=\"cursor-pointer\" [routerLink]=\"['/instructors/', '@' + username()]\">\n <img [src]=\"avatar()\" class=\"w-11 h-11 rounded-full\" />\n </div>\n } @else {\n <div class=\"w-11 h-11 rounded-full bg-orange-600\"></div>\n }\n <div class=\"flex items-center text-lg font-bold cursor-pointer\">\n <a [routerLink]=\"['/instructors/', '@' + username()]\">\n <span>{{ name() }}</span>\n </a>\n <mat-icon color=\"primary\">verified</mat-icon>\n </div>\n </div>\n</div>\n", styles: ["mat-icon{transform:scale(.8)}\n"], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
|
|
970
|
-
}
|
|
971
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: CourseMediaOwnerRendererComponent, decorators: [{
|
|
972
|
-
type: Component,
|
|
973
|
-
args: [{ selector: 'rolatech-course-media-owner-renderer', standalone: true, imports: [AngularCommonModule, MatIconModule], template: "<div class=\"flex flex-row items-center\">\n <div class=\"flex mr-3 gap-2 items-center\">\n @if (avatar()) {\n <div class=\"cursor-pointer\" [routerLink]=\"['/instructors/', '@' + username()]\">\n <img [src]=\"avatar()\" class=\"w-11 h-11 rounded-full\" />\n </div>\n } @else {\n <div class=\"w-11 h-11 rounded-full bg-orange-600\"></div>\n }\n <div class=\"flex items-center text-lg font-bold cursor-pointer\">\n <a [routerLink]=\"['/instructors/', '@' + username()]\">\n <span>{{ name() }}</span>\n </a>\n <mat-icon color=\"primary\">verified</mat-icon>\n </div>\n </div>\n</div>\n", styles: ["mat-icon{transform:scale(.8)}\n"] }]
|
|
974
|
-
}] });
|
|
975
|
-
|
|
976
1850
|
class CourseSectionContentComponent {
|
|
977
1851
|
constructor() {
|
|
978
1852
|
this.route = inject(ActivatedRoute);
|
|
@@ -1135,5 +2009,5 @@ const courseRoutes = [
|
|
|
1135
2009
|
* Generated bundle index. Do not edit.
|
|
1136
2010
|
*/
|
|
1137
2011
|
|
|
1138
|
-
export { CourseRequestStatus, CourseReviewStatus, CourseSectionLectureContentType, CourseStatus, CourseType, ScheduleDate, courseRoutes, provideAngulaCourse };
|
|
2012
|
+
export { CourseActionComponent, CourseDetailsComponent, CourseDetailsDialogComponent, CourseEditDialogComponent, CourseInfoComponent, CourseItemComponent, CourseMediaComponent, CourseMediaOwnerRendererComponent, CoursePreviewComponent, CoursePricingAddDialogComponent, CoursePricingComponent, CoursePricingDialogComponent, CourseRequestStatus, CourseReviewStatus, CourseScheduleAddDialogComponent, CourseScheduleComponent, CourseScheduleDialogComponent, CourseSectionItemComponent, CourseSectionLectureContentType, CourseSectionLectureItemComponent, CourseSectionLectureVideoDialogComponent, CourseSectionLectureVideoItemComponent, CourseSectionsComponent, CourseStatus, CourseType, DetailItemComponent, PricingItemComponent, ScheduleDate, ScheduleItemComponent, courseRoutes, provideAngulaCourse };
|
|
1139
2013
|
//# sourceMappingURL=rolatech-angular-course.mjs.map
|