Skip to content

Commit 68d86fc

Browse files
committed
fix info-task & add news design
1 parent 9a51878 commit 68d86fc

9 files changed

Lines changed: 139 additions & 130 deletions

File tree

projects/social_platform/src/app/office/courses/lesson/lesson.component.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<div class="task">
55
<div class="task__wrapper">
66
<div class="task__tasks">
7-
<p class="task__name text-bold-body-14">модуль {{ lessonInfo()?.moduleId }}</p>
7+
<p class="task__name text-bold-body-14">модуль {{ lessonInfo()?.moduleOrder }}</p>
88
</div>
99

1010
<div class="task__progress">
@@ -34,8 +34,8 @@
3434
<div class="task__content">
3535
<!-- informationalType === "text" или "video_text" и answerType === null → info-task -->
3636
@if (task.answerType === null && (task.informationalType === 'text' || task.informationalType
37-
=== 'video_text')) {
38-
<app-info-task [data]="$any(task)"></app-info-task>
37+
=== 'video_text' || task.informationalType === 'text_image')) {
38+
<app-info-task [data]="task"></app-info-task>
3939
}
4040

4141
<!-- answerType === "text" или "text_and_files" → write-task -->
@@ -60,7 +60,7 @@
6060
<!-- answerType === "single_choice" → radio-select-task -->
6161
@if (task.answerType === 'single_choice') {
6262
<app-radio-select-task
63-
[data]="$any(task)"
63+
[data]="task"
6464
[success]="success()"
6565
[error]="hasError()"
6666
(update)="onAnswerChange([$event.answerId])"

projects/social_platform/src/app/office/courses/lesson/lesson.component.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { ActivatedRoute, NavigationEnd, Router, RouterOutlet } from "@angular/ro
77
import { filter, map, tap } from "rxjs";
88
import { CourseLesson, Task } from "@office/models/courses.model";
99
import { CoursesService } from "../courses.service";
10-
import { ParseBreaksPipe, ParseLinksPipe } from "@corelib";
1110
import { ButtonComponent } from "@ui/components";
1211
import { SnackbarService } from "@ui/services/snackbar.service";
1312
import { InfoTaskComponent } from "./shared/video-task/info-task.component";

projects/social_platform/src/app/office/courses/lesson/shared/file-task/file-task.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
[class.file-task__content--error]="error"
6363
>
6464
<p class="file-task__label text-body-12">ответ</p>
65-
<!-- <p class="file-task__title text-body-12-bold">{{ data.title | truncate: 80 }}</p> -->
65+
<p class="file-task__title text-body-12-bold">{{ data.answerTitle | truncate: 80 }}</p>
6666

6767
<div class="file-task__files">
6868
<app-upload-file [resetAfterUpload]="true" (uploaded)="onFileUploaded($event)">
Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,59 @@
11
<!-- @format -->
22

3-
<div
4-
class="video"
5-
[class.video--hasVideo]="sourceType === 'embed'"
6-
[class.video--hasImage]="sourceType === 'img'"
7-
>
8-
<div class="video__text-content" [class.video__text-content--hasVideo]="!!mediaUrl">
9-
<p class="video__title text-body-12-bold">
10-
{{ data.text | truncate: (sourceType === "embed" ? 80 : sourceType === "img" ? 100 : 200) }}
11-
</p>
12-
<p
13-
class="video__text text-body-12"
14-
[innerHTML]="
15-
data.description
16-
| truncateHtml: (sourceType === 'embed' ? 627 : sourceType === 'img' ? 500 : 1000)
17-
"
18-
></p>
19-
</div>
3+
<div class="video">
4+
<div
5+
class="video__body"
6+
[class.video__body--hasVideo]="data.videoUrl"
7+
[class.video__body--hasImage]="data.imageUrl"
8+
>
9+
@if ((data.videoUrl || data.attachmentUrl) && !data.imageUrl) {
10+
<p class="video__task text-body-12">задание {{ data.order }}</p>
11+
}
2012

21-
@if (sourceType === 'embed') {
22-
<div class="video__wrapper" [class.video__wrapper--hasVideo]="sourceType === 'embed'">
23-
<div class="video__frame" [class.video__frame--hasVideo]="sourceType === 'embed'">
24-
<iframe [src]="mediaUrl" width="395px" height="223px" frameborder="0" allowfullscreen>
13+
<div
14+
class="video__wrapper"
15+
[class.video__wrapper--hasVideo]="data.videoUrl"
16+
[class.video__wrapper--hasImage]="data.imageUrl"
17+
>
18+
@if (data.videoUrl) { @if (getSafeVideoUrl(); as videoUrl) {
19+
<iframe
20+
[src]="videoUrl"
21+
width="395px"
22+
height="222px"
23+
frameborder="0"
24+
allowfullscreen
25+
allowtransparency="true"
26+
>
2527
</iframe>
28+
} } @if (data.imageUrl) {
29+
<img appImagePreview class="video__img" [src]="data.imageUrl" />
30+
}
31+
32+
<div class="video__text-content">
33+
@if (!data.videoUrl) {
34+
<p class="video__task text-body-12">задание {{ data.order }}</p>
35+
}
36+
37+
<p class="video__title text-body-12-bold">
38+
{{ data.title | truncate: (hasVideoUrl() ? 80 : data.imageUrl ? 100 : 200) }}
39+
</p>
40+
<div
41+
class="video__text text-body-12"
42+
[innerHTML]="
43+
data.bodyText | truncateHtml: (hasVideoUrl() ? 627 : data.imageUrl ? 500 : 1000)
44+
"
45+
></div>
46+
47+
@if (data.attachmentUrl) {
48+
<app-file-item
49+
mode="preview"
50+
[type]="'file'"
51+
name="файл с заданием"
52+
[size]="0"
53+
[link]="data.attachmentUrl"
54+
></app-file-item>
55+
}
56+
</div>
2657
</div>
2758
</div>
28-
} @if (data.files.length) {
29-
<img appImagePreview class="video__img" [src]="data.files[0]" />
30-
}
3159
</div>

projects/social_platform/src/app/office/courses/lesson/shared/video-task/info-task.component.scss

Lines changed: 39 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,69 @@
11
@use "styles/responsive";
2-
@use "styles/typography";
32

43
.video {
5-
display: flex;
6-
flex-direction: column-reverse;
7-
gap: 20px;
8-
align-items: center;
9-
min-height: 336px;
10-
padding: 24px;
11-
background-color: var(--light-white);
12-
border: 0.5px solid var(--medium-grey-for-outline);
13-
border-radius: var(--rounded-lg);
4+
width: 100%;
145

15-
@include responsive.apply-desktop {
16-
flex-direction: row-reverse;
17-
}
6+
&__body {
7+
display: flex;
8+
flex-direction: row;
9+
gap: 24px;
10+
min-height: 358px;
11+
padding: 24px;
12+
background-color: var(--light-white);
13+
border: 0.5px solid var(--medium-grey-for-outline);
14+
border-radius: var(--rounded-lg);
1815

19-
&--hasVideo {
20-
@include responsive.apply-desktop {
21-
align-items: center;
16+
iframe {
17+
display: block;
18+
width: 100%;
19+
max-width: 400px;
20+
height: auto;
21+
aspect-ratio: 16 / 9;
22+
border: 0;
23+
border-radius: var(--rounded-lg);
2224
}
23-
}
2425

25-
&--hasImage {
26-
@include responsive.apply-desktop {
27-
flex-direction: row;
28-
gap: 114px;
29-
align-items: center;
30-
justify-content: space-between;
31-
padding: 24px 90px 24px 24px;
26+
&--hasImage {
27+
flex-direction: row-reverse;
3228
}
33-
}
3429

35-
&__img {
36-
width: 100%;
37-
max-width: 200px;
38-
height: 100%;
39-
max-height: 200px;
40-
object-fit: contain;
30+
&--hasVideo {
31+
flex-direction: column;
32+
}
4133
}
4234

4335
&__wrapper {
4436
display: flex;
45-
justify-content: center;
46-
width: 100%;
37+
gap: 24px;
4738

4839
&--hasVideo {
49-
align-self: center;
50-
justify-content: center;
51-
border-radius: var(--rounded-lg);
40+
flex-direction: row;
5241
}
5342

54-
@include responsive.apply-desktop {
55-
justify-content: flex-end;
56-
width: 100%;
57-
58-
&--hasVideo {
59-
align-self: center;
60-
justify-content: center;
61-
border-radius: var(--rounded-lg);
62-
}
43+
&--hasImage {
44+
flex-direction: row-reverse;
6345
}
6446
}
6547

66-
&__frame {
67-
width: 100%;
68-
69-
&--hasVideo {
70-
align-self: center;
71-
width: 100%;
72-
height: 100%;
73-
}
74-
75-
@include responsive.apply-desktop {
76-
width: 100%;
77-
margin-left: 50px;
78-
79-
&--hasVideo {
80-
align-self: center;
81-
width: 100%;
82-
height: 100%;
83-
margin-left: 0;
84-
}
85-
}
48+
&__task {
49+
color: var(--grey-for-text);
50+
}
8651

87-
iframe {
88-
display: block;
89-
width: 100%;
90-
max-width: 400px;
91-
height: auto;
92-
aspect-ratio: 16 / 9;
93-
border: 0;
94-
border-radius: var(--rounded-lg);
95-
}
52+
&__img {
53+
align-self: center;
54+
width: 100%;
55+
max-width: 300px;
56+
height: 100%;
57+
max-height: 200px;
58+
object-fit: cover;
59+
border-radius: var(--rounded-lg);
9660
}
9761

9862
&__text-content {
9963
display: flex;
10064
flex-direction: column;
10165
gap: 24px;
66+
width: 100%;
10267
}
10368

10469
&__text {
Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
/** @format */
22

3-
import { Component, inject, Input, type OnChanges } from "@angular/core";
3+
import { Component, inject, Input } from "@angular/core";
44
import { CommonModule } from "@angular/common";
55
import { DomSanitizer, type SafeResourceUrl } from "@angular/platform-browser";
66
import { TruncateHtmlPipe } from "projects/core/src/lib/pipes/truncate-html.pipe";
77
import { TruncatePipe } from "projects/core/src/lib/pipes/truncate.pipe";
8-
import { InfoSlide } from "projects/skills/src/models/step.model";
98
import { resolveVideoUrlForIframe } from "@utils/video-url-embed";
109
import { ImagePreviewDirective } from "../image-preview/image-preview.directive";
10+
import { Task } from "@office/models/courses.model";
11+
import { FileItemComponent } from "@ui/components/file-item/file-item.component";
1112

1213
/**
1314
* Компонент информационного слайда с видео/изображением
1415
* Отображает информационный контент с поддержкой различных медиа-форматов
1516
*
1617
* Входные параметры:
17-
* @Input data - данные информационного слайда типа InfoSlide
18+
* @Input data - данные информационной задачи типа Task
1819
*
1920
* Функциональность:
2021
* - Отображает текст и описание слайда
@@ -25,31 +26,33 @@ import { ImagePreviewDirective } from "../image-preview/image-preview.directive"
2526
@Component({
2627
selector: "app-info-task",
2728
standalone: true,
28-
imports: [CommonModule, TruncateHtmlPipe, TruncatePipe, ImagePreviewDirective],
29+
imports: [CommonModule, TruncateHtmlPipe, TruncatePipe, ImagePreviewDirective, FileItemComponent],
2930
templateUrl: "./info-task.component.html",
3031
styleUrl: "./info-task.component.scss",
3132
})
32-
export class InfoTaskComponent implements OnChanges {
33-
@Input({ required: true }) data!: InfoSlide; // Данные информационного слайда
33+
export class InfoTaskComponent {
34+
@Input({ required: true }) data!: Task; // Данные информационной задачи
3435

35-
sanitizer = inject(DomSanitizer); // Сервис для безопасной работы с HTML
36+
private readonly sanitizer = inject(DomSanitizer); // Сервис для безопасной работы с HTML
3637

37-
sourceType: "embed" | "img" | null = null;
38-
mediaUrl?: SafeResourceUrl | string;
39-
40-
ngOnChanges(): void {
41-
this.mediaUrl = undefined;
42-
this.sourceType = null;
38+
private getVideoUrl(): string | null {
39+
return resolveVideoUrlForIframe(this.data?.videoUrl);
40+
}
4341

44-
const firstFile = this.data.files[0]?.toLowerCase();
45-
if (firstFile && /\.(webp|png|jpe?g|gif|svg)(?:$|[?#])/i.test(firstFile)) {
46-
this.sourceType = "img";
42+
getSafeVideoUrl(): SafeResourceUrl | null {
43+
const iframeUrl = this.getVideoUrl();
44+
if (!iframeUrl) {
45+
return null;
4746
}
4847

49-
const iframeUrl = resolveVideoUrlForIframe(this.data.videoUrl);
50-
if (iframeUrl) {
51-
this.mediaUrl = this.sanitizer.bypassSecurityTrustResourceUrl(iframeUrl);
52-
this.sourceType = "embed";
53-
}
48+
return this.sanitizer.bypassSecurityTrustResourceUrl(iframeUrl);
49+
}
50+
51+
hasVideoUrl(): boolean {
52+
return !!this.getVideoUrl();
53+
}
54+
55+
hasContent(): boolean {
56+
return this.hasVideoUrl() || !!this.data?.imageUrl;
5457
}
5558
}

projects/social_platform/src/app/office/courses/lesson/shared/write-task/write-task.component.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@
2020
allowtransparency="true"
2121
></iframe>
2222
} @else if (data.imageUrl) {
23-
<img appImagePreview class="write-task__image" [src]="data.imageUrl" />
23+
<div class="write-task__block">
24+
<img appImagePreview class="write-task__image" [src]="data.imageUrl" />
25+
<p class="text-body-12-bold">{{ data.title | truncate: 50 }}</p>
26+
</div>
2427
}
2528
<div [innerHTML]="data.bodyText | truncate: (type === 'text-file' ? 650 : 700)"></div>
2629

projects/social_platform/src/app/office/courses/lesson/shared/write-task/write-task.component.scss

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
}
2323

2424
&__content {
25-
max-width: 333px;
25+
min-width: 333px;
2626
padding: 12px 24px;
2727
}
2828

@@ -72,11 +72,20 @@
7272
color: var(--grey-for-text);
7373
}
7474

75+
&__block {
76+
display: flex;
77+
align-items: center;
78+
align-self: center;
79+
text-align: center;
80+
flex-direction: column;
81+
gap: 5px;
82+
}
83+
7584
&__image {
7685
width: 100%;
77-
max-width: 397px;
78-
max-height: 223px;
79-
object-fit: contain;
86+
max-width: 300px;
87+
max-height: 150px;
88+
object-fit: cover;
8089
border-radius: var(--rounded-lg);
8190
}
8291

0 commit comments

Comments
 (0)