Skip to content

Commit 4a44570

Browse files
authored
Merge pull request #2841 from WISE-Community/issue-2827-convert-notebook-to-angular
Convert Notebook to Angular
2 parents bab0c16 + a38a156 commit 4a44570

58 files changed

Lines changed: 2071 additions & 1966 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

angular.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@
6565
"bundleName": "siteStyles"
6666
}
6767
],
68+
"stylePreprocessorOptions": {
69+
"includePaths": [
70+
"src/main/webapp/site/src/style"
71+
]
72+
},
6873
"scripts": []
6974
},
7075
"configurations": {
@@ -274,6 +279,11 @@
274279
"styles": [
275280
"src/main/webapp/site/src/style/styles.scss"
276281
],
282+
"stylePreprocessorOptions": {
283+
"includePaths": [
284+
"src/main/webapp/site/src/style"
285+
]
286+
},
277287
"assets": [
278288
"src/main/webapp/site/src/assets",
279289
"src/main/webapp/site/src/favicon.ico"

src/main/webapp/site/src/app/common-hybrid-angular.module.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,16 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
5454
import { MomentModule } from 'ngx-moment';
5555
import { EditorModule, TINYMCE_SCRIPT_SRC } from '@tinymce/tinymce-angular';
5656
import { WiseTinymceEditorComponent } from '../../../wise5/directives/wise-tinymce-editor/wise-tinymce-editor.component';
57+
import { NotebookParentComponent } from './notebook/notebook-parent/notebook-parent.component';
58+
import { NotebookItemComponent } from './notebook/notebook-item/notebook-item.component';
59+
import { NotebookLauncherComponent } from './notebook/notebook-launcher/notebook-launcher.component';
60+
import { NotebookNotesComponent } from './notebook/notebook-notes/notebook-notes.component';
61+
import { NotebookReportComponent } from './notebook/notebook-report/notebook-report.component';
62+
import { NotebookReportAnnotationsComponent } from './notebook/notebook-report-annotations/notebook-report-annotations.component';
63+
import { MatSidenavModule } from '@angular/material/sidenav';
64+
import { MatTabsModule } from '@angular/material/tabs';
5765
import { MatAutocompleteModule } from '@angular/material/autocomplete';
66+
import { MatToolbarModule } from '@angular/material/toolbar';
5867
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
5968
import { MatRadioModule } from '@angular/material/radio';
6069
import { MatDividerModule } from '@angular/material/divider';
@@ -70,6 +79,12 @@ export class EmptyComponent {}
7079
HelpIconComponent,
7180
NodeIconComponent,
7281
NodeStatusIcon,
82+
NotebookParentComponent,
83+
NotebookItemComponent,
84+
NotebookLauncherComponent,
85+
NotebookNotesComponent,
86+
NotebookReportComponent,
87+
NotebookReportAnnotationsComponent,
7388
WiseTinymceEditorComponent
7489
],
7590
imports: [
@@ -92,6 +107,9 @@ export class EmptyComponent {}
92107
MatProgressSpinnerModule,
93108
MatRadioModule,
94109
MatSelectModule,
110+
MatSidenavModule,
111+
MatTabsModule,
112+
MatToolbarModule,
95113
MatSlideToggleModule,
96114
MatTooltipModule,
97115
MomentModule,
@@ -151,6 +169,9 @@ export class EmptyComponent {}
151169
MatProgressSpinnerModule,
152170
MatRadioModule,
153171
MatSelectModule,
172+
MatSidenavModule,
173+
MatTabsModule,
174+
MatToolbarModule,
154175
MatSlideToggleModule,
155176
MatTooltipModule,
156177
MomentModule,
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<mat-card class="notebook-item"
2+
(click)="doSelect($event)"
3+
(keyup.enter)="doSelect($event)"
4+
role="button"
5+
tabindex="0">
6+
<mat-card-content class="content" [ngClass]="{'text-only': !item.content.attachments.length}">
7+
<div *ngIf="item.content.attachments.length > 0"
8+
class="attachment-content"
9+
style="background-image: url('{{item.content.attachments[0].iconURL}}')">
10+
</div>
11+
<div *ngIf="item.content.text"
12+
class="text-content mat-body-1"
13+
style="color: {{label.color}}">
14+
{{item.content.text}}
15+
</div>
16+
</mat-card-content>
17+
<mat-card-actions class="dark-theme">
18+
<div class="actions app-bar"
19+
fxLayoutAlign="start center"
20+
style="background-color: {{color}}">
21+
<span class="location" fxLayoutAlign="start center">
22+
<mat-icon>place</mat-icon><span class="mat-body-1">{{getItemNodePosition()}}</span>
23+
</span>
24+
<span fxFlex></span>
25+
<button mat-icon-button
26+
*ngIf="canDeleteNotebookItem()"
27+
i18n-aria-label
28+
attr.aria-label="Delete {{label.singular}}"
29+
i18n-matTooltip
30+
attr.matTooltip="Delete {{label.singular}}"
31+
matTooltipPosition="above"
32+
(click)="doDelete($event)">
33+
<mat-icon>delete</mat-icon>
34+
</button>
35+
<button mat-icon-button
36+
*ngIf="canReviveNotebookItem()"
37+
i18n-aria-label
38+
attr.aria-label="Revive {{label.singular}}"
39+
i18n-matTooltip
40+
attr.matTooltip="Revive {{label.singular}}"
41+
matTooltipPosition="above"
42+
(click)="doRevive($event)">
43+
<mat-icon>undo</mat-icon>
44+
</button>
45+
</div>
46+
</mat-card-actions>
47+
</mat-card>
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
@import '~@angular/material/theming',
2+
'~style/abstracts/variables',
3+
'~style/themes/default';
4+
5+
$light-gray: map-get($mat-grey, 300);
6+
7+
.notebook-item {
8+
transition: box-shadow 250ms;
9+
margin: 0;
10+
padding: 0;
11+
cursor: pointer;
12+
13+
&:hover, &:focus {
14+
@include mat-elevation(4);
15+
outline: none;
16+
}
17+
18+
&:active {
19+
outline: none;
20+
}
21+
}
22+
23+
.content {
24+
height: 200px;
25+
padding: 0;
26+
background-color: $light-gray;
27+
border-top-left-radius: $card-border-radius;
28+
border-top-right-radius: $card-border-radius;
29+
}
30+
31+
.attachment-content, .text-content {
32+
position: absolute;
33+
left: 0;
34+
right: 0;
35+
}
36+
37+
.attachment-content {
38+
background-repeat: no-repeat;
39+
border-top-left-radius: $card-border-radius;
40+
border-top-right-radius: $card-border-radius;
41+
background-position: center top;
42+
background-size: cover;
43+
top: 0;
44+
bottom: 0;
45+
}
46+
47+
.text-content {
48+
bottom: 0;
49+
padding: 8px;
50+
font-weight: 500;
51+
overflow: hidden;
52+
max-height: 120px;
53+
min-height: 56px;
54+
background-color: rgba(255,255,255,0.95);
55+
border-top: 1px solid $light-gray;
56+
57+
&:after {
58+
content: "";
59+
text-align: right;
60+
position: absolute;
61+
bottom: 0;
62+
right: 0;
63+
width: 100%;
64+
height: 0.8em;
65+
background: linear-gradient(180deg,hsla(0,0%,100%,0),rgba(255,255,255,0.95) 100%);
66+
}
67+
}
68+
69+
.text-only {
70+
&:after {
71+
content: "note";
72+
font-family: 'Material Icons';
73+
font-weight: normal;
74+
font-style: normal;
75+
display: inline-block;
76+
line-height: 1;
77+
text-transform: none;
78+
letter-spacing: normal;
79+
word-wrap: normal;
80+
white-space: nowrap;
81+
direction: ltr;
82+
-webkit-font-smoothing: antialiased;
83+
text-rendering: optimizeLegibility;
84+
-moz-osx-font-smoothing: grayscale;
85+
font-feature-settings: 'liga';
86+
font-size: 80px;
87+
color: map-get($default-colors, disabled-text);
88+
}
89+
}
90+
91+
.location {
92+
opacity: 0.9;
93+
padding: 8px 0;
94+
}
95+
96+
mat-card-actions {
97+
padding-top: 0;
98+
}
99+
100+
.actions {
101+
margin: 0;
102+
padding: 0 8px;
103+
border-bottom-left-radius: $card-border-radius;
104+
border-bottom-right-radius: $card-border-radius;
105+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { HttpClientTestingModule } from "@angular/common/http/testing";
2+
import { TestBed } from "@angular/core/testing";
3+
import { UpgradeModule } from "@angular/upgrade/static";
4+
import { configureTestSuite } from "ng-bullet";
5+
import { Subscription } from "rxjs";
6+
import { AnnotationService } from "../../../../../wise5/services/annotationService";
7+
import { ConfigService } from "../../../../../wise5/services/configService";
8+
import { NotebookService } from "../../../../../wise5/services/notebookService";
9+
import { ProjectService } from "../../../../../wise5/services/projectService";
10+
import { SessionService } from "../../../../../wise5/services/sessionService";
11+
import { StudentAssetService } from "../../../../../wise5/services/studentAssetService";
12+
import { StudentDataService } from "../../../../../wise5/services/studentDataService";
13+
import { TagService } from "../../../../../wise5/services/tagService";
14+
import { UtilService } from "../../../../../wise5/services/utilService";
15+
import { NotebookItemComponent } from "./notebook-item.component";
16+
17+
let component: NotebookItemComponent;
18+
19+
describe('NotebookItemComponent', () => {
20+
configureTestSuite(() => {
21+
TestBed.configureTestingModule({
22+
imports: [ HttpClientTestingModule, UpgradeModule ],
23+
declarations: [ NotebookItemComponent ],
24+
providers: [
25+
AnnotationService,
26+
ConfigService,
27+
NotebookService,
28+
ProjectService,
29+
SessionService,
30+
StudentAssetService,
31+
StudentDataService,
32+
TagService,
33+
UtilService
34+
]
35+
});
36+
});
37+
38+
beforeEach(() => {
39+
const fixture = TestBed.createComponent(NotebookItemComponent);
40+
component = fixture.componentInstance;
41+
component.notebookUpdatedSubscription = new Subscription();
42+
});
43+
44+
isItemInGroup();
45+
isNotebookItemActive();
46+
});
47+
48+
function isItemInGroup() {
49+
it('should check if an notebook item is in group when it is not in the group', () => {
50+
component.item = { groups: ['Group A'] };
51+
expect(component.isItemInGroup('Group B')).toEqual(false);
52+
});
53+
it('should check if an notebook item is in group when it is in the group', () => {
54+
component.item = { groups: ['Group A'] };
55+
expect(component.isItemInGroup('Group A')).toEqual(true);
56+
});
57+
}
58+
59+
function isNotebookItemActive() {
60+
it('should check if a notebook item is active when it is not active', () => {
61+
component.item = { serverDeleteTime: 1607704074794 };
62+
expect(component.isNotebookItemActive()).toEqual(false);
63+
});
64+
it('should check if a notebook item is active when it is active', () => {
65+
component.item = { serverDeleteTime: null };
66+
expect(component.isNotebookItemActive()).toEqual(true);
67+
});
68+
}

0 commit comments

Comments
 (0)