Skip to content

Commit 3ed1503

Browse files
style(MC Authoring): UI Improvements (#2309)
- Add button to allow adding new choices at any position. Before, it only let you add a new choice at the end. - Moved move up/down buttons to the right of the choices, similar to moving components up/down in node editing view. - Improve responsiveness. Co-authored-by: Jonathan Lim-Breitbart <breity10@gmail.com>
1 parent 540de5e commit 3ed1503

10 files changed

Lines changed: 192 additions & 160 deletions

src/assets/wise5/authoringTool/components/translatable-asset-chooser/translatable-asset-chooser.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<button
22
class="enable-in-translation"
3-
mat-raised-button
3+
mat-icon-button
44
color="primary"
55
(click)="chooseAsset()"
66
[matTooltip]="tooltip"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<div class="flex flex-row justify-end items-center">
2+
<mat-divider class="choice-divider" [ngClass]="{ active: focus }" />
3+
<button
4+
mat-icon-button
5+
color="primary"
6+
(click)="newChoiceEvent.emit()"
7+
(mouseover)="focus = true"
8+
(mouseleave)="focus = false"
9+
(focusin)="focus = true"
10+
(focusout)="focus = false"
11+
i18n-matTooltip
12+
matTooltip="Add choice"
13+
matTooltipPosition="above"
14+
>
15+
<mat-icon>add_circle</mat-icon>
16+
</button>
17+
</div>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
.choice-divider {
2+
width: 100%;
3+
position: relative;
4+
5+
&:after {
6+
position: absolute;
7+
bottom: 0;
8+
left: 0;
9+
width: 100%;
10+
border-bottom-style: solid;
11+
content: "";
12+
border-bottom-width: var(--mdc-filled-text-field-focus-active-indicator-height);
13+
border-bottom-color: var(--mdc-filled-text-field-focus-active-indicator-color);
14+
transform: scaleX(0);
15+
transform-origin: 100%;
16+
transition: transform 360ms cubic-bezier(0.4, 0, 0.2, 1),opacity 360ms cubic-bezier(0.4, 0, 0.2, 1);
17+
opacity: 0;
18+
}
19+
20+
&.active {
21+
&:after {
22+
transform: scaleX(1);
23+
opacity: 1;
24+
}
25+
}
26+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { CommonModule } from '@angular/common';
2+
import { Component, EventEmitter, Output } from '@angular/core';
3+
import { MatButtonModule } from '@angular/material/button';
4+
import { MatDividerModule } from '@angular/material/divider';
5+
import { MatIconModule } from '@angular/material/icon';
6+
import { MatTooltipModule } from '@angular/material/tooltip';
7+
8+
@Component({
9+
imports: [CommonModule, MatButtonModule, MatDividerModule, MatIconModule, MatTooltipModule],
10+
selector: 'add-mc-choice',
11+
styleUrl: 'add-mc-choice.component.scss',
12+
templateUrl: 'add-mc-choice.component.html'
13+
})
14+
export class AddMCChoiceComponent {
15+
protected focus: boolean;
16+
@Output() newChoiceEvent: EventEmitter<void> = new EventEmitter<void>();
17+
}

src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.component.html

Lines changed: 85 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -13,101 +13,97 @@
1313
<mat-radio-button color="primary" value="checkbox" i18n>Multiple Answer</mat-radio-button>
1414
</mat-radio-group>
1515
</p>
16-
<span class="choices-label" i18n>Choices</span>
17-
<button
18-
mat-raised-button
19-
color="primary"
20-
class="add-choice-button"
21-
(click)="addChoice()"
22-
i18nMatTooltip
23-
matTooltip="Add Choice"
24-
matTooltipPosition="above"
25-
>
26-
<mat-icon>add</mat-icon>
27-
</button>
16+
<h2 class="mat-headline-6 !mb-0" i18n>Choices</h2>
17+
<add-mc-choice (newChoiceEvent)="addChoice(0)" />
2818
@if (componentContent.choices == null || componentContent.choices.length === 0) {
2919
<div class="info-block" i18n>
30-
There are no choices. Click the "Add Choice" button to add a choice.
20+
There are no choices. Click the "Add choice" button to add a choice.
3121
</div>
3222
}
33-
@for (choice of componentContent.choices; track choice.id; let last = $last; let first = $first) {
34-
<div class="choice-container">
35-
<div class="flex flex-row flex-wrap justify-start gap-2">
36-
<translatable-input
37-
[content]="choice"
38-
key="text"
39-
label="Choice Text"
40-
i18n-label
41-
placeholder="Type text or choose an image"
42-
i18n-placeholder
43-
(defaultLanguageTextChanged)="choiceTextChange.next($event)"
44-
class="choice-text-input-container"
45-
/>
46-
<translatable-asset-chooser
47-
[content]="choice"
48-
key="text"
49-
[processAsset]="processSelectedAsset"
50-
(defaultLanguageTextChanged)="componentChanged()"
51-
/>
52-
<div>
53-
<mat-checkbox
54-
color="primary"
55-
[(ngModel)]="choice.isCorrect"
56-
(change)="feedbackChanged()"
57-
i18n-aria-label
58-
aria-label="Is Correct"
59-
i18n
60-
>
61-
Is Correct
62-
</mat-checkbox>
23+
@for (choice of componentContent.choices; track choice.id; let last = $last; let i = $index) {
24+
<div class="flex">
25+
<div class="choice-container w-full @container">
26+
<div class="flex flex-col @md:flex-row items-start gap-2">
27+
<div class="flex flex-1 gap-2 order-2 @md:order-1 w-full @md:w-auto">
28+
<translatable-input
29+
[content]="choice"
30+
key="text"
31+
label="Choice Text"
32+
i18n-label
33+
placeholder="Type text or choose an image"
34+
i18n-placeholder
35+
(defaultLanguageTextChanged)="choiceTextChange.next($event)"
36+
class="choice-input-container"
37+
/>
38+
<translatable-asset-chooser
39+
[content]="choice"
40+
key="text"
41+
[processAsset]="processSelectedAsset"
42+
(defaultLanguageTextChanged)="componentChanged()"
43+
/>
44+
</div>
45+
<div class="flex items-center justify-between gap-2 order-1 @md:order-2 w-full @md:w-auto">
46+
<mat-checkbox
47+
color="primary"
48+
[(ngModel)]="choice.isCorrect"
49+
(change)="feedbackChanged()"
50+
i18n-aria-label
51+
aria-label="Is Correct"
52+
i18n
53+
>
54+
Is Correct
55+
</mat-checkbox>
56+
<button
57+
mat-icon-button
58+
color="primary"
59+
(click)="deleteChoice(choice)"
60+
i18n-matTooltip
61+
matTooltip="Delete choice"
62+
matTooltipPosition="above"
63+
>
64+
<mat-icon>delete</mat-icon>
65+
</button>
66+
</div>
67+
</div>
68+
<div class="flex flex-row flex-wrap justify-start">
69+
<translatable-input
70+
[content]="choice"
71+
key="feedback"
72+
label="Feedback"
73+
i18n-label
74+
placeholder="Optional"
75+
i18n-placeholder
76+
(defaultLanguageTextChanged)="feedbackTextChange.next($event)"
77+
class="choice-input-container"
78+
/>
6379
</div>
6480
</div>
65-
<div class="flex flex-row flex-wrap justify-start">
66-
<translatable-input
67-
[content]="choice"
68-
key="feedback"
69-
label="Feedback"
70-
i18n-label
71-
placeholder="Optional"
72-
i18n-placeholder
73-
(defaultLanguageTextChanged)="feedbackTextChange.next($event)"
74-
class="choice-feedback-input-container"
75-
/>
76-
<button
77-
mat-raised-button
78-
color="primary"
79-
class="choice-authoring-button"
80-
[disabled]="first"
81-
(click)="moveChoiceUp(choice)"
82-
i18n-matTooltip
83-
matTooltip="Move Up"
84-
matTooltipPosition="above"
85-
>
86-
<mat-icon>arrow_upward</mat-icon>
87-
</button>
88-
<button
89-
mat-raised-button
90-
color="primary"
91-
class="choice-authoring-button"
92-
[disabled]="last"
93-
(click)="moveChoiceDown(choice)"
94-
i18n-matTooltip
95-
matTooltip="Move Down"
96-
matTooltipPosition="above"
97-
>
98-
<mat-icon>arrow_downward</mat-icon>
99-
</button>
100-
<button
101-
mat-raised-button
102-
color="primary"
103-
class="choice-authoring-button"
104-
(click)="deleteChoice(choice)"
105-
i18n-matTooltip
106-
matTooltip="Delete"
107-
matTooltipPosition="above"
108-
>
109-
<mat-icon>delete</mat-icon>
110-
</button>
81+
<div class="flex flex-col">
82+
@if (i > 0) {
83+
<button
84+
mat-icon-button
85+
color="primary"
86+
(click)="moveChoiceUp(choice)"
87+
i18n-matTooltip
88+
matTooltip="Move up"
89+
matTooltipPosition="above"
90+
>
91+
<mat-icon>arrow_upward</mat-icon>
92+
</button>
93+
}
94+
@if (!last) {
95+
<button
96+
mat-icon-button
97+
color="primary"
98+
(click)="moveChoiceDown(choice)"
99+
i18n-matTooltip
100+
matTooltip="Move down"
101+
matTooltipPosition="above"
102+
>
103+
<mat-icon>arrow_downward</mat-icon>
104+
</button>
105+
}
111106
</div>
112107
</div>
108+
<add-mc-choice (newChoiceEvent)="addChoice(i + 1)" />
113109
}
Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,20 @@
11
@use 'style/abstracts/variables';
22

3-
/* TODO(mdc-migration): The following rule targets internal classes of radio that may no longer apply for the MDC version. */
4-
mat-radio-button {
5-
margin-right: 24px;
6-
}
7-
8-
label.mat-radio-label {
9-
display: inline-flex;
10-
}
11-
12-
.choices-label {
13-
margin-right: 10px;
14-
}
15-
16-
.add-choice-button {
17-
margin-top: 20px;
18-
margin-bottom: 20px;
19-
}
20-
213
.choice-container {
224
border: 2px solid #dddddd;
235
border-radius: variables.$card-border-radius;
24-
margin-bottom: 20px;
25-
padding: 20px 20px 10px 20px;
6+
padding: 16px 16px 0;
267
}
278

289
.info-block {
29-
margin-bottom: 20px;
3010
text-align: center;
3111
font-weight: 500;
3212
}
3313

34-
.choice-authoring-button {
35-
margin-left: 10px;
36-
margin-right: 10px;
37-
}
38-
39-
.mat-mdc-checkbox {
40-
margin-left: 5px;
41-
}
42-
43-
.choice-text-input-container, .choice-feedback-input-container {
44-
width: 70%;
14+
.choice-input-container {
15+
flex: 1;
16+
4517
mat-form-field {
4618
width: 100%;
4719
}
4820
}
49-
50-
.reload-preview-container {
51-
margin-bottom: 10px;
52-
}
53-
54-
.mat-icon {
55-
margin: 0px;
56-
}

src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.component.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ import { EditComponentPrompt } from '../../../../../app/authoring-tool/edit-comp
1414
import { TranslatableAssetChooserComponent } from '../../../authoringTool/components/translatable-asset-chooser/translatable-asset-chooser.component';
1515
import { TranslatableInputComponent } from '../../../authoringTool/components/translatable-input/translatable-input.component';
1616
import { Choice } from '../Choice';
17+
import { AddMCChoiceComponent } from '../add-mc-choice/add-mc-choice.component';
1718

1819
@Component({
1920
imports: [
21+
AddMCChoiceComponent,
2022
FormsModule,
2123
MatButtonModule,
2224
MatCheckboxModule,
@@ -67,8 +69,12 @@ export class MultipleChoiceAuthoring extends AbstractComponentAuthoring {
6769
return false;
6870
}
6971

70-
protected addChoice(): void {
71-
this.componentContent.choices.push(new Choice(generateRandomKey(), '', false, ''));
72+
protected addChoice(position: number): void {
73+
this.componentContent.choices.splice(
74+
position,
75+
0,
76+
new Choice(generateRandomKey(), '', false, '')
77+
);
7278
this.componentChanged();
7379
}
7480

src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.harness.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ import { MatRadioButtonHarness } from '@angular/material/radio/testing';
44

55
export class MultipleChoiceAuthoringHarness extends ComponentHarness {
66
static hostSelector = 'multiple-choice-authoring';
7-
getAddChoiceButton = this.locatorFor(MatButtonHarness.with({ selector: '.add-choice-button' }));
7+
getAddChoiceButton = this.locatorFor(
8+
MatButtonHarness.with({ selector: '[mattooltip="Add choice"]' })
9+
);
810
getChoices = this.locatorForAll('.choice-container');
911
getDeleteChoiceButtons = this.locatorForAll(
10-
MatButtonHarness.with({ selector: '[mattooltip="Delete"]' })
12+
MatButtonHarness.with({ selector: '[mattooltip="Delete choice"]' })
1113
);
1214
getMoveDownButtons = this.locatorForAll(
13-
MatButtonHarness.with({ selector: '[mattooltip="Move Down"]' })
15+
MatButtonHarness.with({ selector: '[mattooltip="Move down"]' })
1416
);
1517
getMoveUpButtons = this.locatorForAll(
16-
MatButtonHarness.with({ selector: '[mattooltip="Move Up"]' })
18+
MatButtonHarness.with({ selector: '[mattooltip="Move up"]' })
1719
);
1820
getMultipleAnswerRadioChoice = this.locatorFor(
1921
MatRadioButtonHarness.with({ label: 'Multiple Answer' })

src/assets/wise5/components/multipleChoice/multiple-choice-authoring/multiple-choice-authoring.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ function moveChoice() {
120120
});
121121
describe('move choice up is clicked on the second choice', () => {
122122
it('moves the choice up', async () => {
123-
await (await multipleChoiceAuthoringHarness.getMoveChoiceUpButton(1)).click();
123+
await (await multipleChoiceAuthoringHarness.getMoveChoiceUpButton(0)).click();
124124
expectChoiceOrder(['choice2', 'choice1']);
125125
});
126126
});

0 commit comments

Comments
 (0)