Skip to content
Snippets Groups Projects
Commit 8d67c625 authored by Tom Käsler's avatar Tom Käsler
Browse files

Merge branch '175-content-creation-refactoring' into 'master'

Resolve "Content creation refactoring"

Closes #175

See merge request arsnova/arsnova-lite!117
parents 8f4fdd02 954d16d7
Branches
Tags
No related merge requests found
Showing
with 210 additions and 140 deletions
<form (ngSubmit)="submitContent(subject.value, body.value, group.value)" fxLayout="column" fxLayoutGap="20px">
<mat-form-field class="input-block">
<input matInput #subject [(ngModel)]="content.subject" placeholder="{{ 'content.subject' | translate }}" name="subject">
</mat-form-field>
<app-markdown-toolbar textareaId="content-choice-body"></app-markdown-toolbar>
<mat-form-field class="input-block">
<textarea matInput #body id="content-choice-body" [(ngModel)]="content.body" placeholder="{{ 'content.body' | translate }}" name="body"
matTextareaAutosize matAutosizeMinRows="3" matAutosizeMaxRows="8"></textarea>
</mat-form-field>
<form (ngSubmit)="submitContent()" fxLayout="column" fxLayoutGap="20px">
<markdown [data]="content.body"></markdown>
<mat-divider></mat-divider>
......@@ -58,15 +50,6 @@
{{ 'content.add-answer' | translate }}
</button>
</div>
<mat-form-field>
<input matInput #group matInput [formControl]="myControl" [matAutocomplete]="auto"
value={{lastCollection}} placeholder="{{'content.collection' | translate}}"/>
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let collection of filteredOptions | async" [value]="collection">
{{collection}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<div *ngIf="!editDialogMode" fxLayout="row" fxLayoutAlign="center" fxLayoutGap="50px">
<button mat-raised-button type="submit" color="accent">{{ 'content.create' | translate }}</button>
<button mat-raised-button (click)="reset($event)" color="primary">{{ 'content.reset' | translate }}</button>
......
import { Component, Inject, OnInit } from '@angular/core';
import { Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core';
import { AnswerOption } from '../../../models/answer-option';
import { ContentChoice } from '../../../models/content-choice';
import { ContentService } from '../../../services/http/content.service';
......@@ -29,6 +29,12 @@ export class DisplayAnswer {
styleUrls: ['./content-choice-creator.component.scss']
})
export class ContentChoiceCreatorComponent implements OnInit {
@Input() contentSub;
@Input() contentBod;
@Input() contentCol;
@Output() resetP = new EventEmitter<boolean>();
singleChoice = true;
content: ContentChoice = new ContentChoice(
'0',
......@@ -249,8 +255,7 @@ export class ContentChoiceCreatorComponent implements OnInit {
}
resetAfterSubmit() {
this.content.subject = '';
this.content.body = '';
this.resetP.emit(true);
this.content.options = [];
this.content.correctOptionIndexes = [];
this.fillCorrectAnswers();
......@@ -259,8 +264,8 @@ export class ContentChoiceCreatorComponent implements OnInit {
});
}
submitContent(subject: string, body: string, group: string) {
if (this.content.body.valueOf() === '' || this.content.body.valueOf() === '') {
submitContent() {
if (this.contentBod === '' || this.contentSub === '') {
this.translationService.get('content.no-empty').subscribe(message => {
this.notificationService.show(message);
});
......@@ -299,10 +304,10 @@ export class ContentChoiceCreatorComponent implements OnInit {
'',
'',
this.roomId,
subject,
body,
this.contentSub,
this.contentBod,
1,
[group],
[this.contentCol],
this.content.options,
this.content.correctOptionIndexes,
this.content.multiple,
......@@ -314,7 +319,7 @@ export class ContentChoiceCreatorComponent implements OnInit {
editDialogClose($event, action: string) {
$event.preventDefault();
if (action.valueOf() === 'edit') {
this.submitContent(this.content.subject, this.content.body, this.content.groups[1]);
this.submitContent();
}
if (action.valueOf() === 'abort') {
this.dialogRef.close(action);
......
......@@ -3,22 +3,22 @@
<mat-tab-group>
<mat-tab label="Text">
<div class="tab-container">
<app-content-text-creator></app-content-text-creator>
<app-content-creator [format]="'text'" [contentGroups]="contentGroups"></app-content-creator>
</div>
</mat-tab>
<mat-tab label="Single / Multiple Choice">
<div class="tab-container">
<app-content-choice-creator></app-content-choice-creator>
<app-content-creator [format]="'choice'" [contentGroups]="contentGroups"></app-content-creator>
</div>
</mat-tab>
<mat-tab label="Likert">
<div class="tab-container">
<app-content-likert-creator></app-content-likert-creator>
<app-content-creator [format]="'likert'" [contentGroups]="contentGroups"></app-content-creator>
</div>
</mat-tab>
<mat-tab label="{{ 'content.yes' | translate }} / {{ 'content.no' | translate }}">
<div class="tab-container">
<app-content-yes-no-creator></app-content-yes-no-creator>
<app-content-creator [format]="'yesno'" [contentGroups]="contentGroups"></app-content-creator>
</div>
</mat-tab>
</mat-tab-group>
......
import { Component, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { LanguageService } from '../../../services/util/language.service';
import { RoomService } from '../../../services/http/room.service';
import { ActivatedRoute } from '@angular/router';
import { ContentGroup } from '../../../models/content-group';
@Component({
selector: 'app-content-create-page',
......@@ -9,12 +12,27 @@ import { LanguageService } from '../../../services/util/language.service';
})
export class ContentCreatePageComponent implements OnInit {
contentGroups: ContentGroup[];
lastCollection: string;
constructor(private translateService: TranslateService,
protected langService: LanguageService) {
protected langService: LanguageService,
protected roomService: RoomService,
protected route: ActivatedRoute) {
langService.langEmitter.subscribe(lang => translateService.use(lang));
}
ngOnInit() {
this.translateService.use(sessionStorage.getItem('currentLang'));
this.route.params.subscribe(params => {
this.getGroups(params['roomId']);
});
this.lastCollection = sessionStorage.getItem('collection');
}
getGroups(id: string): void {
this.roomService.getRoomByShortId(id).subscribe(room => {
this.contentGroups = room.contentGroups;
});
}
}
<form>
<mat-form-field class="input-block">
<input matInput #subject [(ngModel)]="content.subject" placeholder="{{'content.subject' | translate}}" name="subject">
</mat-form-field>
<app-markdown-toolbar textareaId="content-text-body"></app-markdown-toolbar>
<mat-form-field class="input-block">
<textarea matInput #body [(ngModel)]="content.body" placeholder="{{'content.body' | translate}}" name="body"
matTextareaAutosize matAutosizeMinRows="3" matAutosizeMaxRows="8"></textarea>
</mat-form-field>
<markdown [data]="content.body"></markdown>
<mat-form-field>
<input matInput #group matInput [formControl]="myControl" [matAutocomplete]="auto"
value={{lastCollection}} placeholder="{{'content.collection' | translate}}"/>
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let collection of contentGroups" [value]="collection.name">
{{collection.name}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<app-content-text-creator *ngIf="format === 'text'" (reset)="resetInputs()"
[contentSub] = "subject.value" [contentBod]="body.value" [contentCol]="group.value">
</app-content-text-creator>
<app-content-choice-creator *ngIf="format === 'choice'" (resetP)="resetInputs()"
[contentSub] = "subject.value" [contentBod]="body.value" [contentCol]="group.value">
</app-content-choice-creator>
<app-content-likert-creator *ngIf="format === 'likert'" (reset)="resetInputs()"
[contentSub] = "subject.value" [contentBod]="body.value" [contentCol]="group.value">
</app-content-likert-creator>
<app-content-yes-no-creator *ngIf="format === 'yesno'" (reset)="resetInputs()"
[contentSub] = "subject.value" [contentBod]="body.value" [contentCol]="group.value">
</app-content-yes-no-creator>
</form>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ContentCreatorComponent } from './content-creator.component';
describe('ContentCreatorComponent', () => {
let component: ContentCreatorComponent;
let fixture: ComponentFixture<ContentCreatorComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ContentCreatorComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ContentCreatorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Inject, Input, OnInit } from '@angular/core';
import { ContentText } from '../../../models/content-text';
import { FormControl } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material';
import { ContentListComponent } from '../../shared/content-list/content-list.component';
import { Room } from '../../../models/room';
@Component({
selector: 'app-content-creator',
templateUrl: './content-creator.component.html',
styleUrls: ['./content-creator.component.scss']
})
export class ContentCreatorComponent implements OnInit {
@Input() format;
@Input() contentGroups;
room: Room;
content: ContentText = new ContentText(
'1',
'1',
'0',
'',
'',
1,
[],
);
lastCollection: string;
myControl = new FormControl();
editDialogMode = false;
constructor(public dialog: MatDialog,
public dialogRef: MatDialogRef<ContentListComponent>,
@Inject(MAT_DIALOG_DATA) public data: any) {
}
ngOnInit() {
}
resetInputs() {
this.content.subject = '';
this.content.body = '';
}
}
<form (ngSubmit)="submitContent(subject.value, body.value, group.value)">
<mat-form-field class="input-block">
<input matInput #subject [(ngModel)]="content.subject" placeholder="{{ 'content.subject' | translate }}" name="subject">
</mat-form-field>
<mat-form-field class="input-block">
<textarea matInput #body [(ngModel)]="content.body" placeholder="{{ 'content.body' | translate }}" name="body"></textarea>
</mat-form-field>
<form (ngSubmit)="submitContent()">
<mat-divider></mat-divider>
<mat-table #table [dataSource]="displayAnswers">
<ng-container matColumnDef="label">
......@@ -17,15 +11,6 @@
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
<mat-form-field>
<input matInput #group matInput [formControl]="myControl" [matAutocomplete]="auto"
value={{lastCollection}} placeholder="{{'content.collection' | translate}}"/>
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let collection of filteredOptions | async" [value]="collection">
{{collection}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<div *ngIf="!editDialogMode">
<button mat-raised-button type="submit" color="accent">{{ 'content.create' | translate }}</button>
</div>
......
import { Component, Inject, OnInit } from '@angular/core';
import { Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core';
import { DisplayAnswer } from '../content-choice-creator/content-choice-creator.component';
import { ContentChoice } from '../../../models/content-choice';
import { AnswerOption } from '../../../models/answer-option';
......@@ -19,6 +19,11 @@ import { TranslateService } from '@ngx-translate/core';
styleUrls: ['./content-likert-creator.component.scss']
})
export class ContentLikertCreatorComponent implements OnInit {
@Input() contentSub;
@Input() contentBod;
@Input() contentCol;
@Output() reset = new EventEmitter<boolean>();
likertScale = [
'Strongly agree',
'Agree',
......@@ -89,8 +94,7 @@ export class ContentLikertCreatorComponent implements OnInit {
}
resetAfterSubmit() {
this.content.subject = '';
this.content.body = '';
this.reset.emit(true);
this.content.correctOptionIndexes = [];
this.fillCorrectAnswers();
this.translationService.get('content.submitted').subscribe(message => {
......@@ -98,8 +102,8 @@ export class ContentLikertCreatorComponent implements OnInit {
});
}
submitContent(subject: string, body: string, group: string): void {
if (subject.valueOf() === '' || body.valueOf() === '') {
submitContent(): void {
if (this.contentSub === '' || this.contentBod === '') {
this.translationService.get('content.no-empty').subscribe(message => {
this.notificationService.show(message);
});
......@@ -109,10 +113,10 @@ export class ContentLikertCreatorComponent implements OnInit {
'',
'',
this.roomId,
subject,
body,
this.contentSub,
this.contentBod,
1,
[group],
[this.contentCol],
this.content.options,
this.content.correctOptionIndexes,
this.content.multiple,
......
<form (ngSubmit)="submitContent(subject.value, body.value, group.value)">
<mat-form-field class="input-block">
<input matInput #subject [(ngModel)]="content.subject" placeholder="{{'content.subject' | translate}}" name="subject">
</mat-form-field>
<app-markdown-toolbar textareaId="content-text-body"></app-markdown-toolbar>
<mat-form-field class="input-block">
<textarea matInput #body id="content-text-body" [(ngModel)]="content.body" placeholder="{{'content.body' | translate}}" name="body"
matTextareaAutosize matAutosizeMinRows="3" matAutosizeMaxRows="8"></textarea>
</mat-form-field>
<markdown [data]="content.body"></markdown>
<mat-form-field>
<input matInput #group matInput [formControl]="myControl" [matAutocomplete]="auto"
value={{lastCollection}} placeholder="{{'content.collection' | translate}}"/>
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let collection of filteredOptions | async" [value]="collection">
{{collection}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<form (ngSubmit)="submitContent()">
<div fxLayout="row" fxLayoutAlign="center" fxLayoutGap="5px" *ngIf="!editDialogMode">
<button mat-raised-button type="submit" color="accent">{{'content.create' | translate}}</button>
</div>
......
import { Component, Inject, OnInit } from '@angular/core';
import { Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core';
import { ContentText } from '../../../models/content-text';
import { ContentService } from '../../../services/http/content.service';
import { NotificationService } from '../../../services/util/notification.service';
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material';
import { ContentListComponent } from '../../shared/content-list/content-list.component';
import { ContentDeleteComponent } from '../_dialogs/content-delete/content-delete.component';
import { map, startWith } from 'rxjs/operators';
import { FormControl } from '@angular/forms';
import { Observable } from 'rxjs/Observable';
import { TranslateService } from '@ngx-translate/core';
@Component({
......@@ -16,6 +13,10 @@ import { TranslateService } from '@ngx-translate/core';
styleUrls: ['./content-text-creator.component.scss']
})
export class ContentTextCreatorComponent implements OnInit {
@Input() contentSub;
@Input() contentBod;
@Input() contentCol;
@Output() reset = new EventEmitter<boolean>();
roomId: string;
content: ContentText = new ContentText(
......@@ -27,10 +28,6 @@ export class ContentTextCreatorComponent implements OnInit {
1,
[],
);
collections: string[] = ['ARSnova', 'Angular', 'HTML', 'TypeScript' ];
myControl = new FormControl();
filteredOptions: Observable<string[]>;
lastCollection: string;
editDialogMode = false;
......@@ -44,44 +41,32 @@ export class ContentTextCreatorComponent implements OnInit {
ngOnInit() {
this.roomId = localStorage.getItem(`roomId`);
this.lastCollection = sessionStorage.getItem('collection');
this.filteredOptions = this.myControl.valueChanges
.pipe(
startWith(''),
map(value => this._filter(value))
);
}
private _filter(value: string): string[] {
const filterValue = value.toLowerCase();
return this.collections.filter(collection => collection.toLowerCase().includes(filterValue));
}
resetAfterSubmit() {
this.content.subject = '';
this.content.body = '';
this.reset.emit(true);
this.translationService.get('content.submitted').subscribe(message => {
this.notificationService.show(message);
});
}
submitContent(subject: string, body: string, group: string) {
submitContent() {
this.contentService.addContent(new ContentText(
'1',
'1',
this.roomId,
subject,
body,
this.contentSub,
this.contentBod,
1,
[group],
[this.contentCol],
)).subscribe();
if (this.content.body.valueOf() === '' || this.content.body.valueOf() === '') {
if (this.contentSub === '' || this.contentBod === '') {
this.translationService.get('content.no-empty').subscribe(message => {
this.notificationService.show(message);
});
return;
}
sessionStorage.setItem('collection', group);
sessionStorage.setItem('collection', this.contentCol);
this.resetAfterSubmit();
}
......
<form (ngSubmit)="submitContent(subject.value, body.value, group.value)">
<mat-form-field class="input-block">
<input matInput #subject [(ngModel)]="content.subject" placeholder="{{ 'content.subject' | translate }}" name="subject">
</mat-form-field>
<mat-form-field class="input-block">
<textarea matInput #body [(ngModel)]="content.body" placeholder="{{ 'content.body' | translate }}" name="body"></textarea>
</mat-form-field>
<mat-radio-group [(ngModel)]="yesno" [ngModelOptions]="{standalone: true}" fxLayout="row" fxLayoutAlign="center" fxLayoutGap="20px">
<mat-radio-button [value]=true [checked]=true>
{{ 'content.yes' | translate }}
</mat-radio-button>
<mat-radio-button [value]=false [checked]=false>
{{ 'content.no' | translate }}
</mat-radio-button>
</mat-radio-group>
<mat-form-field>
<input matInput #group matInput [formControl]="myControl" [matAutocomplete]="auto"
value={{lastCollection}} placeholder="{{'content.collection' | translate}}"/>
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let collection of filteredOptions | async" [value]="collection">
{{collection}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<form (ngSubmit)="submitContent()">
<mat-radio-group [(ngModel)]="yesno" [ngModelOptions]="{standalone: true}" fxLayout="row" fxLayoutAlign="center" fxLayoutGap="20px">
<mat-radio-button [value]=true [checked]=true>
{{ 'content.yes' | translate }}
</mat-radio-button>
<mat-radio-button [value]=false [checked]=false>
{{ 'content.no' | translate }}
</mat-radio-button>
</mat-radio-group>
<div *ngIf="!editDialogMode">
<button mat-raised-button type="submit" color="accent">{{ 'content.create' | translate }}</button>
</div>
......
import { Component, Inject, OnInit } from '@angular/core';
import { Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core';
import { ContentChoice } from '../../../models/content-choice';
import { DisplayAnswer } from '../content-choice-creator/content-choice-creator.component';
import { AnswerOption } from '../../../models/answer-option';
......@@ -19,6 +19,11 @@ import { TranslateService } from '@ngx-translate/core';
styleUrls: ['./content-yes-no-creator.component.scss']
})
export class ContentYesNoCreatorComponent implements OnInit {
@Input() contentSub;
@Input() contentBod;
@Input() contentCol;
@Output() reset = new EventEmitter<boolean>();
yesno = true;
answerLabels = [
'yes',
......@@ -84,8 +89,7 @@ export class ContentYesNoCreatorComponent implements OnInit {
}
resetAfterSubmit() {
this.content.subject = '';
this.content.body = '';
this.reset.emit(true);
this.content.correctOptionIndexes = [];
this.fillCorrectAnswers();
this.translationService.get('content.submitted').subscribe(message => {
......@@ -93,8 +97,8 @@ export class ContentYesNoCreatorComponent implements OnInit {
});
}
submitContent(subject: string, body: string, group: string): void {
if (subject.valueOf() === '' || body.valueOf() === '') {
submitContent(): void {
if (this.contentSub === '' || this.contentBod === '') {
this.translationService.get('content.no-empty').subscribe(message => {
this.notificationService.show(message);
});
......@@ -109,10 +113,10 @@ export class ContentYesNoCreatorComponent implements OnInit {
'',
'',
this.roomId,
subject,
body,
this.contentSub,
this.contentBod,
1,
[group],
[this.contentCol],
this.content.options,
this.content.correctOptionIndexes,
this.content.multiple,
......
......@@ -21,6 +21,7 @@ import { SharedModule } from '../shared/shared.module';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { HttpClient } from '@angular/common/http';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { ContentCreatorComponent } from './content-creator/content-creator.component';
@NgModule({
imports: [
......@@ -50,7 +51,8 @@ import { TranslateHttpLoader } from '@ngx-translate/http-loader';
RoomCreateComponent,
RoomDeleteComponent,
RoomEditComponent,
CreatorContentCarouselPageComponent
CreatorContentCarouselPageComponent,
ContentCreatorComponent
],
entryComponents: [
RoomCreateComponent,
......
<mat-card *ngFor="let contentGroup of displayedContentGroups" (click)="viewContents(contentGroup)">
<mat-card *ngFor="let contentGroup of contentGroups" (click)="viewContents(contentGroup)">
<mat-divider></mat-divider>
<mat-card-header>
<mat-card-title>
......
import { Component, Input, OnInit } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { ContentService } from '../../../services/http/content.service';
import { Content } from '../../../models/content';
import { ActivatedRoute } from '@angular/router';
......@@ -13,8 +13,8 @@ import { ContentTextCreatorComponent } from '../../creator/content-text-creator/
import { NotificationService } from '../../../services/util/notification.service';
import { Room } from '../../../models/room';
import { RoomService } from '../../../services/http/room.service';
import {TranslateService} from "@ngx-translate/core";
import {LanguageService} from "../../../services/util/language.service";
import { TranslateService } from '@ngx-translate/core';
import { LanguageService } from '../../../services/util/language.service';
class ContentGroup {
name: string;
......
export class ContentGroup {
name: string;
contentIds: string[];
autoSort: boolean;
constructor(name: string, contentIds: string[], autoSort: boolean) {
this.name = name;
this.contentIds = contentIds;
this.autoSort = autoSort;
}
}
import { ContentGroup } from './content-group';
export class Room {
id: string;
revision: string;
......@@ -6,5 +8,5 @@ export class Room {
name: string;
description: string;
closed: boolean;
contentGroups: {[key: string]: [string]};
contentGroups: ContentGroup[];
}
......@@ -5,6 +5,7 @@ import { Observable } from 'rxjs/Observable';
import { catchError, tap } from 'rxjs/operators';
import { BaseHttpService } from './base-http.service';
import { ContentChoice } from '../../models/content-choice';
import { ContentGroup } from '../../models/content-group';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment