Skip to content

Commit f96dde4

Browse files
committed
fix description expand & video relations
1 parent c90526c commit f96dde4

17 files changed

Lines changed: 199 additions & 178 deletions

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,15 @@
2121
<p class="exclude__text text-body-12-bold">{{ data.answerTitle | truncate: 110 }}</p>
2222
}
2323

24-
<p #descEl class="text-body-12 exclude__description">{{ data.bodyText | truncate: 700 }}</p>
24+
<p
25+
#descEl
26+
class="text-body-12 exclude__description"
27+
[innerHTML]="
28+
readFullDescription ? data.bodyText : (data.bodyText | truncateHtml: truncateLimit)
29+
"
30+
></p>
2531
@if (descriptionExpandable) {
26-
<div
27-
class="read-more text-body-10"
28-
(click)="onExpandDescription(descEl, 'expanded', readFullDescription)"
29-
>
32+
<div class="read-more text-body-10" (click)="onToggleDescription(descEl)">
3033
{{ readFullDescription ? "скрыть" : "подробнее" }}
3134
</div>
3235
}

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

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@
2727

2828
iframe {
2929
display: block;
30+
align-self: center;
3031
width: 100%;
31-
max-width: 400px;
32-
height: auto;
32+
max-width: 295px;
33+
height: 223px;
3334
aspect-ratio: 16 / 9;
3435
border: 0;
3536
border-radius: var(--rounded-lg);
@@ -76,19 +77,8 @@
7677
}
7778

7879
&__description {
79-
display: box;
80-
overflow: hidden;
8180
text-align: justify;
82-
-webkit-box-orient: vertical;
83-
-webkit-line-clamp: 6;
84-
transition: all 0.7s ease-in-out;
85-
86-
&.expanded {
87-
display: block;
88-
max-height: 200px;
89-
overflow-y: auto;
90-
-webkit-line-clamp: unset;
91-
}
81+
white-space: pre-line;
9282
}
9383

9484
.read-more {

projects/social_platform/src/app/office/courses/lesson/shared/exclude-task/exclude-task.component.ts

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
11
/** @format */
22

33
import {
4-
AfterViewInit,
54
ChangeDetectorRef,
65
Component,
7-
ElementRef,
86
EventEmitter,
97
inject,
108
Input,
119
type OnInit,
1210
Output,
1311
signal,
14-
ViewChild,
1512
} from "@angular/core";
1613
import { CommonModule } from "@angular/common";
1714
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
1815
import { CheckboxComponent } from "@ui/components";
1916
import { TruncatePipe } from "projects/core/src/lib/pipes/truncate.pipe";
17+
import { TruncateHtmlPipe } from "projects/core/src/lib/pipes/truncate-html.pipe";
2018
import { Task } from "@office/models/courses.model";
2119
import { resolveVideoUrlForIframe } from "@utils/video-url-embed";
22-
import { expandElement } from "@utils/expand-element";
20+
import { animateContentHeight } from "@utils/animate-content-height";
21+
import { isHtmlTextTruncated } from "@utils/is-html-text-truncated";
2322
import { ImagePreviewDirective } from "../image-preview/image-preview.directive";
2423

2524
/**
@@ -45,16 +44,14 @@ import { ImagePreviewDirective } from "../image-preview/image-preview.directive"
4544
@Component({
4645
selector: "app-exclude-task",
4746
standalone: true,
48-
imports: [CommonModule, TruncatePipe, CheckboxComponent, ImagePreviewDirective],
47+
imports: [CommonModule, TruncatePipe, TruncateHtmlPipe, CheckboxComponent, ImagePreviewDirective],
4948
templateUrl: "./exclude-task.component.html",
5049
styleUrl: "./exclude-task.component.scss",
5150
})
52-
export class ExcludeTaskComponent implements OnInit, AfterViewInit {
51+
export class ExcludeTaskComponent implements OnInit {
5352
private readonly sanitizer = inject(DomSanitizer);
5453
private readonly cdRef = inject(ChangeDetectorRef);
5554

56-
@ViewChild("descEl") descEl?: ElementRef<HTMLElement>;
57-
5855
@Input({ required: true }) data!: Task; // Данные вопроса
5956
@Input() hint!: string; // Текст подсказки
6057
@Output() update = new EventEmitter<number[]>(); // Событие обновления выбранных ответов
@@ -79,9 +76,13 @@ export class ExcludeTaskComponent implements OnInit, AfterViewInit {
7976

8077
result = signal<number[]>([]);
8178
_error = signal<boolean>(false);
82-
descriptionExpandable = false;
8379
readFullDescription = false;
8480
cachedVideoUrl: SafeResourceUrl | null = null;
81+
readonly truncateLimit = 700;
82+
83+
get descriptionExpandable(): boolean {
84+
return isHtmlTextTruncated(this.data?.bodyText, this.truncateLimit);
85+
}
8586

8687
ngOnInit(): void {
8788
const iframeUrl = resolveVideoUrlForIframe(this.data?.videoUrl);
@@ -90,17 +91,11 @@ export class ExcludeTaskComponent implements OnInit, AfterViewInit {
9091
: null;
9192
}
9293

93-
ngAfterViewInit(): void {
94-
const el = this.descEl?.nativeElement;
95-
if (el) {
96-
this.descriptionExpandable = el.scrollHeight > el.clientHeight;
94+
onToggleDescription(elem: HTMLElement): void {
95+
animateContentHeight(elem, () => {
96+
this.readFullDescription = !this.readFullDescription;
9797
this.cdRef.detectChanges();
98-
}
99-
}
100-
101-
onExpandDescription(elem: HTMLElement, expandedClass: string, isExpanded: boolean): void {
102-
expandElement(elem, expandedClass, isExpanded);
103-
this.readFullDescription = !isExpanded;
98+
});
10499
}
105100

106101
/**

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,13 @@
2929
<div
3030
#descEl
3131
class="file-task__desc text-body-12"
32-
[innerHTML]="data.bodyText | truncate: 700"
32+
[innerHTML]="
33+
readFullDescription ? data.bodyText : (data.bodyText | truncateHtml: truncateLimit)
34+
"
3335
></div>
3436

3537
@if (descriptionExpandable) {
36-
<div
37-
class="read-more text-body-10"
38-
(click)="onExpandDescription(descEl, 'expanded', readFullDescription)"
39-
>
38+
<div class="read-more text-body-10" (click)="onToggleDescription(descEl)">
4039
{{ readFullDescription ? "скрыть" : "подробнее" }}
4140
</div>
4241
}

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

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,10 @@
9999

100100
iframe {
101101
display: block;
102+
align-self: center;
102103
width: 100%;
103-
max-width: 400px;
104-
height: auto;
104+
max-width: 295px;
105+
height: 223px;
105106
aspect-ratio: 16 / 9;
106107
border: 0;
107108
border-radius: var(--rounded-lg);
@@ -137,19 +138,8 @@
137138
}
138139

139140
&__desc {
140-
display: box;
141-
overflow: hidden;
142141
text-align: justify;
143-
-webkit-box-orient: vertical;
144-
-webkit-line-clamp: 6;
145-
transition: all 0.7s ease-in-out;
146-
147-
&.expanded {
148-
display: block;
149-
max-height: 200px;
150-
overflow-y: auto;
151-
-webkit-line-clamp: unset;
152-
}
142+
white-space: pre-line;
153143
}
154144

155145
&__file {

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

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
/** @format */
22

33
import {
4-
AfterViewInit,
54
ChangeDetectorRef,
65
Component,
7-
ElementRef,
86
EventEmitter,
97
inject,
108
Input,
119
OnInit,
1210
Output,
1311
signal,
14-
ViewChild,
1512
} from "@angular/core";
1613
import { CommonModule } from "@angular/common";
1714
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
@@ -24,7 +21,8 @@ import { FileService } from "@core/services/file.service";
2421
import { Task } from "@office/models/courses.model";
2522
import { FileModel } from "@office/models/file.model";
2623
import { resolveVideoUrlForIframe } from "@utils/video-url-embed";
27-
import { expandElement } from "@utils/expand-element";
24+
import { animateContentHeight } from "@utils/animate-content-height";
25+
import { isHtmlTextTruncated } from "@utils/is-html-text-truncated";
2826
import { ImagePreviewDirective } from "../image-preview/image-preview.directive";
2927

3028
@Component({
@@ -42,13 +40,11 @@ import { ImagePreviewDirective } from "../image-preview/image-preview.directive"
4240
templateUrl: "./file-task.component.html",
4341
styleUrl: "./file-task.component.scss",
4442
})
45-
export class FileTaskComponent implements OnInit, AfterViewInit {
43+
export class FileTaskComponent implements OnInit {
4644
private readonly fileService = inject(FileService);
4745
private readonly sanitizer = inject(DomSanitizer);
4846
private readonly cdRef = inject(ChangeDetectorRef);
4947

50-
@ViewChild("descEl") descEl?: ElementRef<HTMLElement>;
51-
5248
@Input({ required: true }) data!: Task;
5349
@Input() success = false;
5450
@Input() hint = "";
@@ -74,9 +70,13 @@ export class FileTaskComponent implements OnInit, AfterViewInit {
7470

7571
_error = signal<boolean>(false);
7672
uploadedFiles = signal<FileModel[]>([]);
77-
descriptionExpandable = false;
7873
readFullDescription = false;
7974
cachedVideoUrl: SafeResourceUrl | null = null;
75+
readonly truncateLimit = 700;
76+
77+
get descriptionExpandable(): boolean {
78+
return isHtmlTextTruncated(this.data?.bodyText, this.truncateLimit);
79+
}
8080

8181
ngOnInit(): void {
8282
const iframeUrl = resolveVideoUrlForIframe(this.data?.videoUrl);
@@ -85,17 +85,11 @@ export class FileTaskComponent implements OnInit, AfterViewInit {
8585
: null;
8686
}
8787

88-
ngAfterViewInit(): void {
89-
const el = this.descEl?.nativeElement;
90-
if (el) {
91-
this.descriptionExpandable = el.scrollHeight > el.clientHeight;
88+
onToggleDescription(elem: HTMLElement): void {
89+
animateContentHeight(elem, () => {
90+
this.readFullDescription = !this.readFullDescription;
9291
this.cdRef.detectChanges();
93-
}
94-
}
95-
96-
onExpandDescription(elem: HTMLElement, expandedClass: string, isExpanded: boolean): void {
97-
expandElement(elem, expandedClass, isExpanded);
98-
this.readFullDescription = !isExpanded;
92+
});
9993
}
10094

10195
onFileUploaded(event: { url: string; name: string; size: number; mimeType: string }) {

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

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
<!-- @format -->
22

3-
<div class="radio" [class.radio--hasContent]="hasVideoUrl() || !!data.imageUrl">
4-
<div class="radio__body" [class.radio__body--hasContent]="!!data.imageUrl || hasVideoUrl()">
3+
<div class="radio" [class.radio--hasContent]="cachedVideoUrl || !!data.imageUrl">
4+
<div class="radio__body" [class.radio__body--hasContent]="!!data.imageUrl || cachedVideoUrl">
55
<p class="text-body-12 radio__answer">задание {{ data.order }}</p>
6-
@if (getSafeVideoUrl(); as videoUrl) {
7-
<iframe [src]="videoUrl" frameborder="0" allowfullscreen allowtransparency="true"></iframe>
6+
@if (cachedVideoUrl) {
7+
<iframe
8+
[src]="cachedVideoUrl"
9+
frameborder="0"
10+
allowfullscreen
11+
allowtransparency="true"
12+
></iframe>
813
} @if (data.imageUrl) {
914
<div class="radio__block">
1015
<img appImagePreview class="radio__img" [src]="data.imageUrl" />
@@ -14,8 +19,18 @@
1419
<p class="radio__title text-body-12-bold">{{ data.title | truncate: 110 }}</p>
1520
}
1621

17-
<p class="text-body-12 radio__description">{{ data.bodyText | truncate: 700 }}</p>
18-
@if (data.attachmentUrl) {
22+
<p
23+
#descEl
24+
class="text-body-12 radio__description"
25+
[innerHTML]="
26+
readFullDescription ? data.bodyText : (data.bodyText | truncateHtml: truncateLimit)
27+
"
28+
></p>
29+
@if (descriptionExpandable) {
30+
<div class="read-more text-body-10" (click)="onToggleDescription(descEl)">
31+
{{ readFullDescription ? "скрыть" : "подробнее" }}
32+
</div>
33+
} @if (data.attachmentUrl) {
1934
<app-file-item
2035
mode="preview"
2136
[type]="'file'"
@@ -28,7 +43,10 @@
2843
}
2944
</div>
3045

31-
<div class="radio__content" [class.radio__content--hasContent]="!!data.imageUrl || hasVideoUrl()">
46+
<div
47+
class="radio__content"
48+
[class.radio__content--hasContent]="!!data.imageUrl || cachedVideoUrl"
49+
>
3250
<p class="radio__answer text-body-12">ответ</p>
3351
<ul class="radio__list">
3452
<p class="radio__title text-body-12-bold">{{ data.answerTitle | truncate: 110 }}</p>

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@
2929

3030
&__description {
3131
text-align: justify;
32+
white-space: pre-line;
33+
}
34+
35+
.read-more {
36+
margin-top: 12px;
37+
color: var(--accent);
38+
cursor: pointer;
39+
transition: color 0.2s;
40+
41+
&:hover {
42+
color: var(--accent-dark);
43+
}
3244
}
3345

3446
&__img {
@@ -119,9 +131,10 @@
119131

120132
iframe {
121133
display: block;
134+
align-self: center;
122135
width: 100%;
123-
max-width: 288px;
124-
height: auto;
136+
max-width: 295px;
137+
height: 223px;
125138
aspect-ratio: 16 / 9;
126139
border: 0;
127140
border-radius: var(--rounded-lg);

0 commit comments

Comments
 (0)