...
 
Commits (522)
......@@ -49,33 +49,33 @@ ngbuild:
paths:
- "$BUILD_DIR"
#review:
# stage: review
# script:
# - rsync -av --delete "$BUILD_DIR" /srv/nginx/pages/$CI_BUILD_REF_SLUG
# environment:
# name: review/$CI_BUILD_REF_NAME
# url: http://$CI_BUILD_REF_SLUG.$SERVER_URL
# on_stop: stop_review
# only:
# - branches
# except:
# - master
# tags:
# - nginx
review:
stage: review
script:
- rsync -av --delete "$BUILD_DIR" /srv/nginx/pages/$CI_BUILD_REF_SLUG
environment:
name: review/$CI_BUILD_REF_NAME
url: http://$CI_BUILD_REF_SLUG.$REVIEW_SERVER_URL
on_stop: stop_review
only:
- branches
except:
- master
tags:
- nginx
#stop_review:
# stage: review
# script:
# - rm -rf "$BUILD_DIR" /srv/nginx/pages/$CI_BUILD_REF_SLUG
# variables:
# GIT_STRATEGY: none
# when: manual
# environment:
# name: review/$CI_BUILD_REF_NAME
# action: stop
# tags:
# - nginx
stop_review:
stage: review
script:
- rm -rf "$BUILD_DIR" /srv/nginx/pages/$CI_BUILD_REF_SLUG
variables:
GIT_STRATEGY: none
when: manual
environment:
name: review/$CI_BUILD_REF_NAME
action: stop
tags:
- nginx
deploy:
......
# Changelog
## 1.3
Changes to the role system:
* Removes the distinction between participant and lecturer on login
* Adds a user home where all related sessions are listed
* Adds a moderator role
Moderated comment board:
* Creators of sessions can add moderators (via room settings)
* Creators and moderators have access to the moderator board
* Two modes of moderating:
* Default: new comments are auto-acknowledged and are visible on the normal comment board
* Whitelist: new comments are only visible in the moderator board and need acknowledgement
Other Changes:
* Comments can now be marked as wrong
* Comments can get banned (to the moderator board, see above)
* User can delete his account
* Improve wording
**This version is brought to you by:**
Project management: Klaus Quibeldey-Cirkel
Lead programming: Tom "tekay" Käsler, Lukas Mauß
## 1.2.1
Bug Fixes:
* Fix icons in room view for both roles
......
[TOC]
# Making HTML elements a11y
### Example (meeting_room) for Buttons
```html
<button mat-button *ngIf="user && deviceType === 'desktop'" [matMenuTriggerFor]="userMenu" aria-labelledby="meeting_room"></button>
<!--Hidden Div's for a11y-Descriptions-->
<div class="visually-hidden">
<div id="meeting_room">{{'header.a11y-meeting_room' | translate}}</div>
</div>
```
### style.sccs
```scss
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
left: -10000px;
}
```
### Dynamic ARIA labels
Dynamic Aria labels like used in generic components are also possible!
For usage only the `attr.` tag prefix must be added like in following code example:
```html
<button
mat-button
attr.aria-labelledby="{{ ariaPrefix + 'cancel' }}"
...
...
<div id="{{ ariaPrefix + 'cancel'}}">{{ buttonsLabelSection + '.cancel-description' | translate }}</div>
```
@see: [Accessible components: #2 dynamic ARIA labels](https://blog.prototypr.io/accessible-components-2-dynamic-aria-labels-6bf281f26d17)
### Live Announcer
#### To Add Live Announcer you need to import:
``import { LiveAnnouncer } from '@angular/cdk/a11y';``
##### And add to the constructor:
```typescript
constructor(
...
private liveAnnouncer: LiveAnnouncer) {
...
}
```
#### You also need to add to the `ngOnInit()` - Function:
```typescript
ngOnInit() {
...
this.announce();
}
```
#### And this is the function to start the announcement:
```typescript
public announce() {
this.liveAnnouncer.announce('Willkommenstext', 'assertive');
}
```
#### Problems with JAWS and Microsoft Speech
JAWS and Microsoft Speech cannot play the "title" attributes. Only NVDA plays the "title" attribute.
Attribute "aria-label" does not work with multi-language titles, voice output reads registered string directly 1 to 1.
`aria-labelledby` works finde with Microsoft Speech, JAWS and NVDA. If "title" attribute is additionally set, NVDA plays the text twice.
### Keyboard Shortcut
To enter Keyboard Shortcuts you first need to import `Renderer2`, `InDestroy` and the `EventService` form `angular/core`:
```typescript
import { Component, OnInit, OnDestroy, Renderer2 } from '@angular/core';
import { EventService } from '../../../services/util/event.service';
```
After that you also need to add it to the constructor
```typescript
constructor(
...
private eventService: EventService,
private _r: Renderer2){
...
}
}
```
When this is done you need to add a listener to the ``ngOnInit()`` function.
Example:
```typescript
ngOnInit() {
...
// But first you need to add a variable:
listenerFn: () => void;
// listenerFn is for closing the listener in the ngOnDestroy() function when leaving the page
// Example of start-page
this.listenerFn = this._r.listen(document, 'keyup', (event) => {
if (event.keyCode === 49 && this.eventService.focusOnInput === false) {
document.getElementById('session_id-input').focus();
} else if (event.keyCode === 51 && this.eventService.focusOnInput === false) {
document.getElementById('new_session-button').focus();
} else if (event.keyCode === 52 && this.eventService.focusOnInput === false) {
document.getElementById('language-menu').focus();
} else if ((event.keyCode === 57 || event.keyCode === 27) && this.eventService.focusOnInput === false) {
this.announce();
} else if (event.keyCode === 27 && this.eventService.focusOnInput === true) {
document.getElementById('session_enter-button').focus();
}
});
}
// HTML Code:
<button id="session_enter-button" ...>
...
</button>
// 'focusOnInput' is a boolean variable which should be triggered when an input element is focused and unfocused
// Example of room-join.component.html
<input id="session_id-input" matInput #roomId (focus)="eventService.makeFocusOnInputTrue()"
(blur)="eventService.makeFocusOnInputFalse()"
.../>
// ngOnDestroy function for closing the listener when leaving the page
ngOnDestroy() {
this.listenerFn();
}
```
## HTML5 Accessibility: aria-hidden and role=”presentation”
A page about `aria-hidden` and `role="presentation"` attribute usage tests:
Source: [HTML5 Accessibility: aria-hidden and role=”presentation”](http://john.foliot.ca/aria-hidden/)
This diff is collapsed.
This diff is collapsed.
......@@ -28,9 +28,6 @@ hide circle
package "frag.jetzt | domain diagram" <<Frame>> {
class Role {
}
class GuestUser {
}
......@@ -39,17 +36,17 @@ class RegisteredUser {
password
}
GuestUser -left-|> Role
RegisteredUser -up-|> Role
GuestUser -left-|> User
RegisteredUser -up-|> User
class SessionParticipant {
}
class TemporalSessionOwner {
class TemporalSessionHolder {
}
SessionParticipant -left-|> GuestUser
TemporalSessionOwner -up-|> GuestUser
TemporalSessionHolder -up-|> GuestUser
class Moderator <<USP>> {
}
......@@ -57,10 +54,10 @@ class Moderator <<USP>> {
class BonusParticipant <<USP>> {
}
class PermanentSessionOwner {
class PermanentSessionHolder{
}
PermanentSessionOwner -left-|> RegisteredUser
PermanentSessionHolder -left-|> RegisteredUser
Moderator -up-|> RegisteredUser
Moderator -down- Session :assigned to >
BonusParticipant -right-|> RegisteredUser
......@@ -69,7 +66,8 @@ class Session {
id
name
description
owner
holder
moderators
}
class Question {
......@@ -86,7 +84,7 @@ class Status {
Status -up- Question
class Board {
help
helpPage
}
class QuestionBoard {
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<diagram program="umlet" version="14.2">
<zoom_level>13</zoom_level>
<element>
<id>UMLActor</id>
<coordinates>
<x>0</x>
<y>208</y>
<w>104</w>
<h>156</h>
</coordinates>
<panel_attributes>Participant
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>65</x>
<y>221</y>
<w>442</w>
<h>104</h>
</coordinates>
<panel_attributes/>
<additional_attributes>10.0;10.0;320.0;60.0</additional_attributes>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>884</x>
<y>208</y>
<w>182</w>
<h>52</h>
</coordinates>
<panel_attributes>join created
room</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>676</x>
<y>481</y>
<w>156</w>
<h>65</h>
</coordinates>
<panel_attributes>create content
for room</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>520</x>
<y>65</y>
<w>156</w>
<h>52</h>
</coordinates>
<panel_attributes>give a
comment</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>481</x>
<y>169</y>
<w>156</w>
<h>65</h>
</coordinates>
<panel_attributes>show content
in room</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>377</x>
<y>715</y>
<w>156</w>
<h>52</h>
</coordinates>
<panel_attributes>see feedback</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>975</x>
<y>611</y>
<w>208</w>
<h>65</h>
</coordinates>
<panel_attributes>see answer statistics</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>806</x>
<y>507</y>
<w>195</w>
<h>156</h>
</coordinates>
<panel_attributes>lt=.&gt;
&lt;&lt;extends&gt;&gt;</panel_attributes>
<additional_attributes>130.0;100.0;10.0;17.0</additional_attributes>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>1001</x>
<y>468</y>
<w>169</w>
<h>78</h>
</coordinates>
<panel_attributes>start new
voting round</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>819</x>
<y>481</y>
<w>208</w>
<h>52</h>
</coordinates>
<panel_attributes>lt=.&gt;
&lt;&lt;extends&gt;&gt;</panel_attributes>
<additional_attributes>140.0;20.0;10.0;20.0</additional_attributes>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>156</x>
<y>13</y>
<w>156</w>
<h>39</h>
</coordinates>
<panel_attributes>ARSnova</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLActor</id>
<coordinates>
<x>0</x>
<y>546</y>
<w>78</w>
<h>156</h>
</coordinates>
<panel_attributes>Creator
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>156</x>
<y>13</y>
<w>1144</w>
<h>949</h>
</coordinates>
<panel_attributes>
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>481</x>
<y>273</y>
<w>156</w>
<h>52</h>
</coordinates>
<panel_attributes>give feedback
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>416</x>
<y>598</y>
<w>156</w>
<h>52</h>
</coordinates>
<panel_attributes>create room
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>26</x>
<y>559</y>
<w>416</w>
<h>91</h>
</coordinates>
<panel_attributes/>
<additional_attributes>300.0;50.0;10.0;10.0</additional_attributes>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>663</x>
<y>637</y>
<w>156</w>
<h>52</h>
</coordinates>
<panel_attributes>login</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>546</x>
<y>624</y>
<w>143</w>
<h>65</h>
</coordinates>
<panel_attributes>lt=&lt;.
&lt;&lt;include&gt;&gt;</panel_attributes>
<additional_attributes>90.0;30.0;10.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>663</x>
<y>78</y>
<w>247</w>
<h>169</h>
</coordinates>
<panel_attributes>lt=&lt;.
&lt;&lt;include&gt;&gt;</panel_attributes>
<additional_attributes>10.0;10.0;170.0;110.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>624</x>
<y>195</y>
<w>286</w>
<h>65</h>
</coordinates>
<panel_attributes>lt=&lt;.
&lt;&lt;include&gt;&gt;</panel_attributes>
<additional_attributes>10.0;10.0;200.0;30.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>624</x>
<y>234</y>
<w>286</w>
<h>91</h>
</coordinates>
<panel_attributes>lt=&lt;.
&lt;&lt;include&gt;&gt;</panel_attributes>
<additional_attributes>10.0;50.0;200.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>52</x>
<y>507</y>
<w>650</w>
<h>78</h>
</coordinates>
<panel_attributes/>
<additional_attributes>10.0;40.0;480.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>520</x>
<y>533</y>
<w>260</w>
<h>91</h>
</coordinates>
<panel_attributes>lt=&lt;.
&lt;&lt;include&gt;&gt;</panel_attributes>
<additional_attributes>10.0;50.0;180.0;10.0</additional_attributes>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>429</x>
<y>832</y>
<w>156</w>
<h>78</h>
</coordinates>
<panel_attributes>see participant's
comments</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>39</x>
<y>598</y>
<w>416</w>
<h>286</h>
</coordinates>
<panel_attributes/>
<additional_attributes>10.0;10.0;300.0;200.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>39</x>
<y>585</y>
<w>364</w>
<h>182</h>
</coordinates>
<panel_attributes/>
<additional_attributes>10.0;10.0;260.0;120.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>520</x>
<y>637</y>
<w>117</w>
<h>130</h>
</coordinates>
<panel_attributes>lt=&lt;.
&lt;&lt;include&gt;&gt;</panel_attributes>
<additional_attributes>10.0;10.0;10.0;80.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>65</x>
<y>195</y>
<w>455</w>
<h>52</h>
</coordinates>
<panel_attributes/>
<additional_attributes>10.0;20.0;330.0;20.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>65</x>
<y>78</y>
<w>481</w>
<h>156</h>
</coordinates>
<panel_attributes/>
<additional_attributes>10.0;100.0;350.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>533</x>
<y>624</y>
<w>130</w>
<h>273</h>
</coordinates>
<panel_attributes>lt=&lt;.
&lt;&lt;include&gt;&gt;</panel_attributes>
<additional_attributes>10.0;10.0;40.0;190.0</additional_attributes>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>338</x>
<y>26</y>
<w>182</w>
<h>52</h>
</coordinates>
<panel_attributes>give answer
to a content</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>403</x>
<y>65</y>
<w>156</w>
<h>156</h>
</coordinates>
<panel_attributes>lt=.&gt;
&lt;&lt;extends&gt;&gt;</panel_attributes>
<additional_attributes>60.0;100.0;10.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>65</x>
<y>65</y>
<w>351</w>
<h>156</h>
</coordinates>
<panel_attributes/>
<additional_attributes>250.0;10.0;10.0;100.0</additional_attributes>
</element>
</diagram>
......@@ -48,8 +48,8 @@ rectangle "frag.jetzt | use-case diagram \n" << Business >> {
(Moderate questions) <.. (Ban question) : << extend >>
(Evaluate questions) <.. (Ban question) : << extend >>
(Join session) <.. (Ask question) : << extend >>
(Ask question) <.. (Vote down question) : << extend >>
(Ask question) <.. (Vote up question) : << extend >>
(Join session) <.. (Vote up question) : << extend >>
(Join session) <.. (Vote down question) : << extend >>
}
......
# 1.3
## Improved role system
### Break up role concept by not needing to log into specific roles
### Moderators
- implement moderators that have the same access rights (without being able to delete the room) as the owner of a room
- add dialog to room to manage moderators
- add blacklist/whitelist mode for comments
- implement moderator view to monitor/manage incoming comments
# 1.4
## Performance improvements
- Production server performance analysis
- production server performance analysis
- improve on handling STOMP subscribtions
## Web Accessibility Initiative
## Barrier-free
- adhere to WCAG 2.1 for accessibility
# No version planned
# 1.5
## Configuration
- load some configs from the backend
## Bonus
- mark room as "bonus" on creation
- bonus rooms save the users id on comment and answer creation
## Tests
- add automated testing for use cases
## New feedback view
## Feedback
- implement a circle for the feedback
- add a freeze option to stop the feedback
## Message flow
- add message channels for domain objects
- channels provide information on new content, feedback, etc
## Content
- improve on the UX
- add a markup language for the text
- improve on the theme/style
{
"name": "arsnova-lite",
"version": "1.3.0-SNAPSHOT",
"version": "1.4.0-SNAPSHOT",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......
{
"name": "arsnova-lite",
"version": "1.3.0-SNAPSHOT",
"version": "1.4.0-SNAPSHOT",
"license": "MIT",
"scripts": {
"ng": "ng",
......
......@@ -3,6 +3,9 @@ import { RouterModule, Routes } from '@angular/router';
import { PageNotFoundComponent } from './components/shared/page-not-found/page-not-found.component';
import { HomePageComponent } from './components/home/home-page/home-page.component';
import { UserHomeComponent } from './components/home/user-home/user-home.component';
import { ImprintComponent } from './components/home/_dialogs/imprint/imprint.component';
import { DataProtectionComponent } from './components/home/_dialogs/data-protection/data-protection.component';
import { HelpPageComponent } from './components/shared/_dialogs/help-page/help-page.component';
const routes: Routes = [
{
......@@ -18,6 +21,18 @@ const routes: Routes = [
path: 'user',
component: UserHomeComponent
},
{
path: 'imprint',
component: ImprintComponent
},
{
path: 'data-protection',
component: DataProtectionComponent
},
{
path: 'help-page',
component: HelpPageComponent
},
{
path: 'creator',
loadChildren: './components/creator/creator.module#CreatorModule'
......
<div fxLayout="column" fxFill appTheme>
<script src="models/rescale.ts"></script>
<div fxLayout="column" fxFill appTheme>
<header class="header" id="header_rescale">
<app-header #header></app-header>
<div fxFlex class="app-component">
<router-outlet></router-outlet>
</header>
<div id="rescale_screen">
<div class="main_container">
<div class="inner_main_container">
<main fxFlex class="app-component">
<router-outlet></router-outlet>
</main>
</div>
</div>
</div>
<footer role="contentinfo" class="footer" id="footer_rescale">
<app-footer></app-footer>
</footer>
<div class="rescale_overlay" id="overlay_rescale" aria-hidden="true">
<button mat-icon-button (click)="getRescale().toggleState()" title="toggle">
<mat-icon>{{getRescale().getState()==1?'fullscreen':'fullscreen_exit'}}</mat-icon>
</button>
<button mat-icon-button (click)="getRescale().scaleUp()" title="Zoom +">
<mat-icon>zoom_in</mat-icon>
</button>
<button mat-icon-button (click)="getRescale().scaleDown()" title="Zoom -">
<mat-icon>zoom_out</mat-icon>
</button>
<button mat-icon-button (click)="getRescale().scaleUndo()" title="Reset Zoom">
<mat-icon>refresh</mat-icon>
</button>
</div>
</div>
.app-component {
padding: 4%;
z-index:1;
}
main {
height: 100%;
}
#rescale_screen{
width:100%;
height:100%;
float:left;
overflow:hidden;
}
.main_container{
width:100%;
height:100%;
overflow-y:auto;
background-color:var(--background);
}
.inner_main_container{
width:100%;
margin-top:64px;
margin-bottom:64px;
float:left;
}
.header{
width:100%;
position:fixed;
left:0;
top:0;
z-index:2;
transition:all 0.2s ease-in-out;
}
.footer{
width:100%;
position:fixed;
left:0;
bottom:0;
z-index:2;
transition:all 0.2s ease-in-out;
}
.rescale_overlay{
width:190px;
height:50px;
border-radius:0px 25px 25px 0px;
background-color:var(--surface);
position:fixed;
left:-100px;
top:15px;
z-index:2;
display:none;
box-shadow:0px 2px 4px rgba(0,0,0,0.5);
transition:all 0.2s ease-in-out;
}
.rescale_overlay>button{
margin-top:5px;
}
.rescale_overlay mat-icon{
color:var(--on-surface);
}
.rescale_overlay>button:first-child{
margin-left:15px;
}
......@@ -2,6 +2,9 @@ import { Component, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { SwUpdate } from '@angular/service-worker';
import { NotificationService } from './services/util/notification.service';
import { MatIconRegistry } from '@angular/material';
import { DomSanitizer } from '@angular/platform-browser';
import { Rescale } from './models/rescale';
@Component({
selector: 'app-root',
......@@ -10,11 +13,26 @@ import { NotificationService } from './services/util/notification.service';
})
export class AppComponent implements OnInit {
public static rescale: Rescale = new Rescale();
icons = [
'beamer',
'meeting_room'
];
constructor(private translationService: TranslateService,
private update: SwUpdate,
public notification: NotificationService) {
public notification: NotificationService,
private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer) {
translationService.setDefaultLang(this.translationService.getBrowserLang());
sessionStorage.setItem('currentLang', this.translationService.getBrowserLang());
for (const icon of this.icons) {
this.matIconRegistry.addSvgIcon(
icon,
this.domSanitizer.bypassSecurityTrustResourceUrl('../assets/icons/' + icon + '.svg')
);
}
}
title = 'frag.jetzt';
......@@ -37,4 +55,8 @@ export class AppComponent implements OnInit {
});
});
}
public getRescale(): Rescale {
return AppComponent.rescale;
}
}
......@@ -42,6 +42,21 @@ import { HomeCreatorPageComponent } from './components/home/home-creator-page/ho
import { HomeParticipantPageComponent } from './components/home/home-participant-page/home-participant-page.component';
import { CommentSettingsService } from './services/http/comment-settings.service';
import { ModeratorModule } from './components/moderator/moderator.module';
import { ImprintComponent } from './components/home/_dialogs/imprint/imprint.component';
import { DataProtectionComponent } from './components/home/_dialogs/data-protection/data-protection.component';
import { HelpPageComponent } from './components/shared/_dialogs/help-page/help-page.component';
import { CookiesComponent } from './components/home/_dialogs/cookies/cookies.component';
import { DataProtectionEnComponent } from '../assets/i18n/data-protection/data-protection-en';
import { DataProtectionDeComponent } from 'assets/i18n/data-protection/data-protection-de';
import { CookiesEnComponent } from '../assets/i18n/cookies/cookies-en';
import { CookiesDeComponent } from '../assets/i18n/cookies/cookies-de';
import { ImprintEnComponent } from '../assets/i18n/imprint/imprint-en';
import { ImprintDeComponent } from '../assets/i18n/imprint/imprint-de';
import { HelpDeComponent } from '../assets/i18n/help/help-de';
import { HelpEnComponent } from '../assets/i18n/help/help-en';
import { OverlayComponent } from './components/home/_dialogs/overlay/overlay.component';
import { DemoDeComponent } from '../assets/i18n/demo/demo-de';
import { DemoEnComponent } from '../assets/i18n/demo/demo-en';
export function dialogClose(dialogResult: any) {
}
......@@ -50,6 +65,7 @@ export function initializeApp(appConfig: AppConfig) {
return () => appConfig.load();
}
// @ts-ignore
@NgModule({
declarations: [
AppComponent,
......@@ -61,13 +77,31 @@ export function initializeApp(appConfig: AppConfig) {
DemoVideoComponent,
UserHomeComponent,
HomeCreatorPageComponent,
HomeParticipantPageComponent
HomeParticipantPageComponent,
ImprintComponent,
DataProtectionComponent,
HelpPageComponent,
CookiesComponent,
DataProtectionEnComponent,
DataProtectionDeComponent,
CookiesEnComponent,
CookiesDeComponent,
ImprintEnComponent,
ImprintDeComponent,
HelpDeComponent,
HelpEnComponent,
DemoDeComponent,
DemoEnComponent,
HelpEnComponent,
OverlayComponent
],
entryComponents: [
RegisterComponent,
PasswordResetComponent,
UserActivationComponent,
DemoVideoComponent
DemoVideoComponent,
CookiesComponent,
OverlayComponent
],
imports: [
AppRoutingModule,
......
<div *ngIf="answer">
<mat-form-field class="input-block">
<input [(ngModel)]="answer.answerOption.label" matInput
<input (focus)="eventService.makeFocusOnInputTrue()" (blur)="eventService.makeFocusOnInputFalse()"
[(ngModel)]="answer.answerOption.label" matInput
placeholder="{{ 'content.answer' | translate }}" name="answer-label"/>
</mat-form-field>
<mat-form-field class="input-block">
<input [(ngModel)]="answer.answerOption.points" matInput
<input (focus)="eventService.makeFocusOnInputTrue()" (blur)="eventService.makeFocusOnInputFalse()"
[(ngModel)]="answer.answerOption.points" matInput
placeholder="{{ 'content.points' | translate }}" name="points">
</mat-form-field>
<div fxLayout="row" fxLayoutAlign="center" fxLayoutGap="10px">
......
import { Component, Inject, OnInit } from '@angular/core';
import { ContentChoiceCreatorComponent, DisplayAnswer } from '../../content-choice-creator/content-choice-creator.component';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { EventService } from '../../../../services/util/event.service';
@Component({
selector: 'app-answer-edit',
......@@ -11,7 +14,8 @@ export class AnswerEditComponent implements OnInit {
answer: DisplayAnswer;
constructor(public dialogRef: MatDialogRef<ContentChoiceCreatorComponent>,
@Inject(MAT_DIALOG_DATA) public data: any) {
@Inject(MAT_DIALOG_DATA) public data: any,
public eventService: EventService) {
}
ngOnInit() {
......
<div fxLayout="column" fxLayoutAlign="center center" fxLayoutGap="35px">
<h3>{{'comment-page.delimiter' | translate}}</h3>
<mat-radio-group [(ngModel)]="exportType">
<div fxLayout="column">
<mat-radio-button value="comma" checked><h4>{{'comment-page.comma' | translate}}</h4></mat-radio-button>
<mat-radio-button value="semicolon"><h4>{{'comment-page.semicolon' | translate}}</h4></mat-radio-button>
</div>
</mat-radio-group>
<div fxLayout="row" fxLayoutAlign="center center" fxLayoutGap="20px">
<button mat-raised-button class="abort" (click)="onNoClick()">{{'comment-page.abort' | translate}}</button>
<button mat-raised-button class="export"
(click)="dialogRef.close(exportType)">{{'comment-page.export' | translate}}</button>
</div>
<h1>{{'comment-page.delimiter' | translate}}</h1>
<mat-radio-group [(ngModel)]="exportType">
<div fxLayout="column">
<mat-radio-button value="comma" checked><p>{{'comment-page.comma' | translate}}</p></mat-radio-button>
<mat-radio-button value="semicolon"><p>{{'comment-page.semicolon' | translate}}</p></mat-radio-button>
</div>
</mat-radio-group>
</div>
<app-dialog-action-buttons
buttonsLabelSection="comment-page"
confirmButtonLabel="export"
[cancelButtonClickAction]="buildCloseDialogActionCallback()"
[confirmButtonClickAction]="buildExportActionCallback()"
></app-dialog-action-buttons>
......@@ -2,13 +2,12 @@ button {
min-width: 100px;
}
h3 {
h1 {
font-size: large;
color: var(--on-surface);
}
h4 {
margin: 15px 0 15px 0;
p {
color: var(--on-surface);
}
......
......@@ -16,8 +16,27 @@ export class CommentExportComponent implements OnInit {
ngOnInit() {
}
onNoClick(): void {
/**
* Closes the dialog on call.
*/
closeDialog(): void {
this.dialogRef.close();
}
}
/**
* Returns a lambda which closes the dialog on call.
*/
buildCloseDialogActionCallback(): () => void {
return () => this.closeDialog();
}
/**
* Returns a lambda which executes the dialog dedicated action on call.
*/
buildExportActionCallback(): () => void {
return () => this.dialogRef.close(this.exportType);
}
}
<div mat-dialog-content>
<h2>{{'room-page.comments' | translate }}</h2>
<h1>{{'room-page.comments' | translate }}</h1>
<mat-divider></mat-divider>
<div fxLayout="column">
<div fxLayout="row">
<h3>{{ 'room-page.threshold' | translate}}&nbsp;</h3>
<h3><mat-slide-toggle [(ngModel)]="settingThreshold"></mat-slide-toggle></h3>
<h2>{{ 'room-page.threshold' | translate}}&nbsp;
<mat-slide-toggle [(ngModel)]="settingThreshold" aria-labelledby="threshold" ></mat-slide-toggle></h2>
</div>
<div fxLayout="row" *ngIf="settingThreshold">
<mat-slider id="commentSlider" min="-100" max="0" step="10" value="0"
<mat-slider id="commentSlider" min="-100" max="0" step="5"
[(ngModel)]="commentThreshold" (input)="onSliderChange($event)"></mat-slider>
<h3>&nbsp;{{commentThreshold | number}}</h3>
<h2>&nbsp;{{commentThreshold | number}}</h2>
</div>
</div>
<div fxLayout="column">
<div fxLayout="row">
<h3>{{ 'room-page.settings-comment-moderation' | translate}}&nbsp;</h3>
<h3><mat-slide-toggle [(ngModel)]="enableCommentModeration"></mat-slide-toggle></h3>
<h2>{{ 'room-page.settings-comment-moderation' | translate}}&nbsp;
<mat-slide-toggle [(ngModel)]="enableCommentModeration" aria-labelledby="settings-comment-moderation"></mat-slide-toggle></h2>
</div>
<div fxLayout="row" *ngIf="enableCommentModeration">
<h3>{{ 'room-page.settings-direct-send' | translate}}&nbsp;</h3>
<h3><mat-slide-toggle [(ngModel)]="directSend"></mat-slide-toggle></h3>
<h2>{{ 'room-page.settings-direct-send' | translate}}&nbsp;
<mat-slide-toggle [(ngModel)]="directSend" aria-labelledby="settings-direct-send"></mat-slide-toggle></h2>
</div>
</div>
<div fxLayoutAlign="center center">
<button mat-raised-button class="export" (click)="openExportDialog()">
<mat-icon>cloud_download</mat-icon>
<button mat-raised-button class="export" (click)="openExportDialog()" aria-labelledby="export-comments">
<mat-icon>save</mat-icon>
{{ 'room-page.export-comments' | translate }}</button>
</div>
<div fxLayoutAlign="center center">
<button mat-raised-button class="delete" (click)="openDeleteCommentDialog()">
<button mat-raised-button class="delete" (click)="openDeleteCommentDialog()" aria-labelledby="delete-all-comments">
<mat-icon>delete</mat-icon>
{{ 'room-page.delete-all-comments' | translate }}</button>
</div>
<mat-divider></mat-divider>
<div fxLayout="row" fxLayoutAlign="center" fxLayoutGap="10px" class="submit">
<button mat-raised-button class="abort" (click)="dialogRef.close('abort')">
{{ 'room-page.abort' | translate }}
</button>
<button mat-raised-button class="update" (click)="closeDialog()">
{{ 'room-page.update' | translate }}
</button>
</div>
<app-dialog-action-buttons
buttonsLabelSection="room-page"
confirmButtonLabel="update"
[cancelButtonClickAction]="buildCloseDialogActionCallback()"
[confirmButtonClickAction]="buildSaveActionCallback()"
></app-dialog-action-buttons>
</div>
<div class="visually-hidden">
<div id = "threshold">{{'room-page.a11y-threshold' | translate}} </div>
<div id = "settings-comment-moderation">{{'room-page.a11y-settings-comment-moderation' | translate}} </div>
<div id = "settings-direct-send">{{'room-page.a11y-settings-direct-send' | translate}} </div>
<div id = "export-comments">{{'room-page.a11y-export-comments' | translate}} </div>
<div id = "delete-all-comments">{{'room-page.a11y-delete-all-comments' | translate}} </div>
</div>
......@@ -24,14 +24,15 @@ mat-icon {
margin-right: 10px;
}
h2 {
h1 {
margin: 10px 0 10px 0;
color: var(--on-surface);
}
h3 {
h2 {
color: var(--on-surface);
font-weight: normal;
font-size: medium;
}
mat-divider {
......
......@@ -45,7 +45,11 @@ export class CommentSettingsComponent implements OnInit {
ngOnInit() {
if (this.editRoom.extensions && this.editRoom.extensions['comments']) {
if (this.editRoom.extensions['comments'].enableThreshold !== null) {
this.commentThreshold = this.editRoom.extensions['comments'].commentThreshold;
if (this.editRoom.extensions['comments'].commentThreshold) {
this.commentThreshold = this.editRoom.extensions['comments'].commentThreshold;
} else {
this.commentThreshold = -100;
}
this.settingThreshold = this.editRoom.extensions['comments'].enableThreshold;
}
......@@ -131,6 +135,7 @@ export class CommentSettingsComponent implements OnInit {
}
closeDialog(): void {
console.log(this.commentThreshold);
const commentSettings = new CommentSettings();
commentSettings.roomId = this.roomId;
commentSettings.directSend = this.directSend;
......@@ -143,4 +148,20 @@ export class CommentSettingsComponent implements OnInit {
this.dialogRef.close(settingsReturn);
});