Skip to content
Snippets Groups Projects
Commit 4fb414ec authored by Kameel Zaghbour's avatar Kameel Zaghbour
Browse files

Merge branch 'staging' into tag-cloud-configuration

parents 0b9e0720 61c39a81
Branches
Tags
No related merge requests found
Showing
with 841 additions and 222 deletions
......@@ -40,7 +40,7 @@
"rxjs": "^6.5.4",
"tslib": "^2.0.0",
"typescript-map": "0.0.7",
"zone.js": "~0.10.2"
"zone.js": "~0.10.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.1102.11",
......@@ -3777,7 +3777,7 @@
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true,
"engines": {
"node": ">=0.10.0"
"node": ">=8"
}
},
"node_modules/ansi-styles": {
......@@ -3786,7 +3786,7 @@
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
"dev": true,
"engines": {
"node": ">=0.10.0"
"node": ">=8"
}
},
"node_modules/anymatch": {
......@@ -8579,20 +8579,6 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
......@@ -17288,7 +17274,7 @@
"ansi-regex": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
"node": ">=8"
}
},
"node_modules/strip-bom": {
......@@ -20750,9 +20736,9 @@
}
},
"node_modules/zone.js": {
"version": "0.10.2",
"resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.2.tgz",
"integrity": "sha512-UAYfiuvxLN4oyuqhJwd21Uxb4CNawrq6fPS/05Su5L4G+1TN+HVDJMUHNMobVQDFJRir2cLAODXwluaOKB7HFg=="
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz",
"integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg=="
}
},
"dependencies": {
......@@ -27529,13 +27515,6 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
......@@ -37089,9 +37068,9 @@
"dev": true
},
"zone.js": {
"version": "0.10.2",
"resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.2.tgz",
"integrity": "sha512-UAYfiuvxLN4oyuqhJwd21Uxb4CNawrq6fPS/05Su5L4G+1TN+HVDJMUHNMobVQDFJRir2cLAODXwluaOKB7HFg=="
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz",
"integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg=="
}
}
}
\ No newline at end of file
}
......@@ -44,7 +44,7 @@
"rxjs": "^6.5.4",
"tslib": "^2.0.0",
"typescript-map": "0.0.7",
"zone.js": "~0.10.2"
"zone.js": "~0.10.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.1102.11",
......
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { AppComponent } from './app.component';
import { RegisterComponent } from './components/home/_dialogs/register/register.component';
import { PasswordResetComponent } from './components/home/_dialogs/password-reset/password-reset.component';
import { AppRoutingModule } from './app-routing.module';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { HTTP_INTERCEPTORS, HttpClient, HttpClientModule } from '@angular/common/http';
import { UserService } from './services/http/user.service';
import { NotificationService } from './services/util/notification.service';
import { AuthenticationService } from './services/http/authentication.service';
import { AuthenticationGuard } from './guards/authentication.guard';
import { RoomService } from './services/http/room.service';
import { CommentService } from './services/http/comment.service';
import { DataStoreService } from './services/util/data-store.service';
import { EventService } from './services/util/event.service';
import { VoteService } from './services/http/vote.service';
import { WsConnectorService } from './services/websockets/ws-connector.service';
import { UserActivationComponent } from './components/home/_dialogs/user-activation/user-activation.component';
import { AuthenticationInterceptor } from './interceptors/authentication.interceptor';
import { EssentialsModule } from './components/essentials/essentials.module';
import { SharedModule } from './components/shared/shared.module';
import { CreatorModule } from './components/creator/creator.module';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { LanguageService } from './services/util/language.service';
import { MarkdownModule, MarkdownService, MarkedOptions } from 'ngx-markdown';
import { NewLandingComponent } from './components/home/new-landing/new-landing.component';
import { HomePageComponent } from './components/home/home-page/home-page.component';
import { UserHomeComponent } from './components/home/user-home/user-home.component';
import { AppConfig } from './app.config';
import { ThemeModule } from '../theme/theme.module';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
import { ModeratorService } from './services/http/moderator.service';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { DemoVideoComponent } from './components/home/_dialogs/demo-video/demo-video.component';
import { HomeCreatorPageComponent } from './components/home/home-creator-page/home-creator-page.component';
import { HomeParticipantPageComponent } from './components/home/home-participant-page/home-participant-page.component';
import { BonusTokenService } from './services/http/bonus-token.service';
import { CustomIconService } from './services/util/custom-icon.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 { 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';
import { ArsModule } from '../../projects/ars/src/lib/ars.module';
import { QrCodeDialogComponent } from './components/shared/_dialogs/qr-code-dialog/qr-code-dialog.component';
import { MatIconModule } from '@angular/material/icon';
import { RemoveFromHistoryComponent } from './components/shared/_dialogs/remove-from-history/remove-from-history.component';
import { MatomoModule } from 'ngx-matomo-v9';
import { TagCloudComponent } from './components/shared/tag-cloud/tag-cloud.component';
import {TagCloudModule} from 'angular-tag-cloud-module';
import {SpacyService} from './services/http/spacy.service';
export function dialogClose(dialogResult: any) {
}
export function initializeApp(appConfig: AppConfig) {
return () => appConfig.load();
}
// @ts-ignore
@NgModule({
declarations: [
AppComponent,
PasswordResetComponent,
RegisterComponent,
UserActivationComponent,
NewLandingComponent,
HomePageComponent,
DemoVideoComponent,
UserHomeComponent,
HomeCreatorPageComponent,
HomeParticipantPageComponent,
ImprintComponent,
DataProtectionComponent,
CookiesComponent,
DataProtectionEnComponent,
DataProtectionDeComponent,
CookiesEnComponent,
CookiesDeComponent,
ImprintEnComponent,
ImprintDeComponent,
HelpDeComponent,
HelpEnComponent,
DemoDeComponent,
DemoEnComponent,
HelpEnComponent,
OverlayComponent,
TagCloudComponent
],
imports: [
MatomoModule,
AppRoutingModule,
BrowserModule,
BrowserAnimationsModule,
EssentialsModule,
SharedModule,
ThemeModule,
MatIconModule,
HttpClientModule,
CreatorModule,
ModeratorModule,
MarkdownModule.forRoot({
loader: HttpClient,
markedOptions: {
provide: MarkedOptions,
useValue: {
sanitize: true
}
}
}),
ServiceWorkerModule.register('ngsw-worker.js', {enabled: environment.production}),
TranslateModule.forChild({
loader: {
provide: TranslateLoader,
useFactory: (HttpLoaderFactory),
deps: [HttpClient]
},
isolate: true
}),
ArsModule,
TagCloudModule
],
providers: [
/*AppConfig,
{ provide: APP_INITIALIZER,
useFactory: initializeApp,
deps: [AppConfig], multi: true
},*/
{
provide: HTTP_INTERCEPTORS,
useClass: AuthenticationInterceptor,
multi: true
},
WsConnectorService,
NotificationService,
AuthenticationService,
AuthenticationGuard,
DataStoreService,
EventService,
RoomService,
CommentService,
LanguageService,
MarkdownService,
MarkedOptions,
UserService,
VoteService,
ModeratorService,
BonusTokenService,
CustomIconService,
WsConnectorService,
SpacyService,
{
provide: MatDialogRef,
useValue: {
dialogClose
}
},
{
provide: MAT_DIALOG_DATA,
useValue: []
}
],
bootstrap: [AppComponent]
})
export class AppModule {
}
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, '../../assets/i18n/home/', '.json');
}
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { AppComponent } from './app.component';
import { RegisterComponent } from './components/home/_dialogs/register/register.component';
import { PasswordResetComponent } from './components/home/_dialogs/password-reset/password-reset.component';
import { AppRoutingModule } from './app-routing.module';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { HTTP_INTERCEPTORS, HttpClient, HttpClientModule } from '@angular/common/http';
import { UserService } from './services/http/user.service';
import { NotificationService } from './services/util/notification.service';
import { AuthenticationService } from './services/http/authentication.service';
import { AuthenticationGuard } from './guards/authentication.guard';
import { RoomService } from './services/http/room.service';
import { CommentService } from './services/http/comment.service';
import { DataStoreService } from './services/util/data-store.service';
import { EventService } from './services/util/event.service';
import { VoteService } from './services/http/vote.service';
import { WsConnectorService } from './services/websockets/ws-connector.service';
import { UserActivationComponent } from './components/home/_dialogs/user-activation/user-activation.component';
import { AuthenticationInterceptor } from './interceptors/authentication.interceptor';
import { EssentialsModule } from './components/essentials/essentials.module';
import { SharedModule } from './components/shared/shared.module';
import { CreatorModule } from './components/creator/creator.module';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { LanguageService } from './services/util/language.service';
import { MarkdownModule, MarkdownService, MarkedOptions } from 'ngx-markdown';
import { NewLandingComponent } from './components/home/new-landing/new-landing.component';
import { HomePageComponent } from './components/home/home-page/home-page.component';
import { UserHomeComponent } from './components/home/user-home/user-home.component';
import { AppConfig } from './app.config';
import { ThemeModule } from '../theme/theme.module';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
import { ModeratorService } from './services/http/moderator.service';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { DemoVideoComponent } from './components/home/_dialogs/demo-video/demo-video.component';
import { HomeCreatorPageComponent } from './components/home/home-creator-page/home-creator-page.component';
import { HomeParticipantPageComponent } from './components/home/home-participant-page/home-participant-page.component';
import { BonusTokenService } from './services/http/bonus-token.service';
import { CustomIconService } from './services/util/custom-icon.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 { 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';
import { ArsModule } from '../../projects/ars/src/lib/ars.module';
import { QrCodeDialogComponent } from './components/shared/_dialogs/qr-code-dialog/qr-code-dialog.component';
import { MatIconModule } from '@angular/material/icon';
import { RemoveFromHistoryComponent } from './components/shared/_dialogs/remove-from-history/remove-from-history.component';
import { MatomoModule } from 'ngx-matomo-v9';
import { TagCloudComponent } from './components/shared/tag-cloud/tag-cloud.component';
import { MatDialogModule } from '@angular/material/dialog';
import {TagCloudModule} from 'angular-tag-cloud-module';
import {SpacyService} from './services/http/spacy.service';
export function dialogClose(dialogResult: any) {
}
export function initializeApp(appConfig: AppConfig) {
return () => appConfig.load();
}
// @ts-ignore
@NgModule({
declarations: [
AppComponent,
PasswordResetComponent,
RegisterComponent,
UserActivationComponent,
NewLandingComponent,
HomePageComponent,
DemoVideoComponent,
UserHomeComponent,
HomeCreatorPageComponent,
HomeParticipantPageComponent,
ImprintComponent,
DataProtectionComponent,
CookiesComponent,
DataProtectionEnComponent,
DataProtectionDeComponent,
CookiesEnComponent,
CookiesDeComponent,
ImprintEnComponent,
ImprintDeComponent,
HelpDeComponent,
HelpEnComponent,
DemoDeComponent,
DemoEnComponent,
HelpEnComponent,
OverlayComponent,
TagCloudComponent
],
imports: [
MatomoModule,
AppRoutingModule,
BrowserModule,
BrowserAnimationsModule,
EssentialsModule,
SharedModule,
ThemeModule,
MatIconModule,
MatDialogModule,
HttpClientModule,
CreatorModule,
ModeratorModule,
MarkdownModule.forRoot({
loader: HttpClient,
markedOptions: {
provide: MarkedOptions,
useValue: {
sanitize: true
}
}
}),
ServiceWorkerModule.register('ngsw-worker.js', {enabled: environment.production}),
TranslateModule.forChild({
loader: {
provide: TranslateLoader,
useFactory: (HttpLoaderFactory),
deps: [HttpClient]
},
isolate: true
}),
ArsModule,
TagCloudModule
],
providers: [
/*AppConfig,
{ provide: APP_INITIALIZER,
useFactory: initializeApp,
deps: [AppConfig], multi: true
},*/
{
provide: HTTP_INTERCEPTORS,
useClass: AuthenticationInterceptor,
multi: true
},
WsConnectorService,
NotificationService,
AuthenticationService,
AuthenticationGuard,
DataStoreService,
EventService,
RoomService,
CommentService,
LanguageService,
MarkdownService,
MarkedOptions,
UserService,
VoteService,
ModeratorService,
BonusTokenService,
CustomIconService,
WsConnectorService,
SpacyService,
{
provide: MatDialogRef,
useValue: {
dialogClose
}
},
{
provide: MAT_DIALOG_DATA,
useValue: []
}
],
bootstrap: [AppComponent]
})
export class AppModule {
}
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, '../../assets/i18n/home/', '.json');
}
<mat-dialog-content>
<mat-card>
<mat-slide-toggle [(ngModel)]="considerVotes">{{'topic-cloud-dialog.consider-votes' | translate}}</mat-slide-toggle>
<mat-slide-toggle [(ngModel)]="tagsLowerCase">{{'topic-cloud-dialog.tags-lowercase' | translate}}</mat-slide-toggle>
</mat-card>
<div fxLayout="row" style="margin-top: 10px;">
<mat-label fxLayoutAlign="center center">
<mat-icon>search</mat-icon>
</mat-label>
<div style="margin-left: 10px;">
<mat-form-field class="example-form-field">
<input #searchBox id="searchBox" (input)="searchKeyword()"
[(ngModel)]="searchedKeyword" matInput type="text"
placeholder="{{'topic-cloud-dialog.keyword-search' | translate}}">
<button *ngIf="searchedKeyword"
(click)="searchedKeyword = ''; searchMode = false;"
mat-button matSuffix mat-icon-button aria-label="topic-cloud-dialog.keyword-search">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
</div>
<div fxLayoutAlign="end" style="margin-left: 52%;">
<button mat-button [matMenuTriggerFor]="sortMenu" mat-ripple>
<mat-icon>sort</mat-icon>
</button>
</div>
</div>
<mat-menu #sortMenu>
<button mat-menu-item (click)="sortQuestions('alphabetic')">
<mat-icon>sort_by_alpha</mat-icon>
{{'topic-cloud-dialog.sort-alpha' | translate}} </button>
<button mat-menu-item (click)="sortQuestions('questionsCount')">
<mat-icon>swap_vert</mat-icon>
{{'topic-cloud-dialog.sort-count' | translate}} </button>
<button mat-menu-item (click)="sortQuestions('voteCount')">
<mat-icon>swap_vert</mat-icon>
{{'topic-cloud-dialog.sort-vote' | translate}} </button>
</mat-menu>
<mat-accordion>
<mat-expansion-panel hideToggle *ngIf="searchMode && filteredKeywords.length === 0">
<mat-expansion-panel-header>
<mat-panel-title fxLayoutAlign="center">
{{'topic-cloud-dialog.no-keywords-note' | translate}}
</mat-panel-title>
</mat-expansion-panel-header>
</mat-expansion-panel>
<mat-expansion-panel (opened)="panelOpenState = true"
(closed)="panelOpenState = edit = false"
*ngFor="let keyword of (searchMode ? filteredKeywords : keywords); let i = index" [attr.data-index]="i">
<mat-expansion-panel-header class="color">
<mat-panel-title [ngClass]="{'edit-keyword': editedKeyword}">
{{keyword.keyword}}
</mat-panel-title>
<mat-panel-description>
{{keyword.questions.length}}
{{'topic-cloud-dialog.question-count-'+(keyword.questions.length > 1 ? 'plural' : 'singular') | translate}}
</mat-panel-description>
</mat-expansion-panel-header>
<div *ngFor="let question of keyword.questions">
<mat-divider></mat-divider>
<app-topic-dialog-comment
[question]="question"
[keyword]="keyword.keyword"
[maxShowedCharachters]="140"
[isCollapsed]="!panelOpenState"
></app-topic-dialog-comment>
</div>
<!-- Only visible when not editing -->
<div *ngIf="!edit" align="end">
<mat-divider></mat-divider>
<button class="margin-right" mat-icon-button style="align-self:flex-end;" (click)="editKeyword(i)">
<mat-icon class="primary">edit</mat-icon>
</button>
<button class="margin-right" mat-icon-button style="align-self:flex-end;"
(click)="openConfirmDialog(keyword)">
<mat-icon class="red">delete</mat-icon>
</button>
</div>
<!-- Only visible when editing -->
<div *ngIf="edit">
<mat-divider></mat-divider>
<mat-form-field>
<mat-label>{{'topic-cloud-dialog.edit-keyword-tip' | translate}}</mat-label>
<input matInput id="{{'edit-input'+i}}" [(ngModel)]="newKeyword">
</mat-form-field>
<!-- TODO: textinput and buttons in one row -->
<div align="end">
<button mat-raised-button class="redBackground margin-right" (click)="cancelEdit()">{{'topic-cloud-dialog.cancel' | translate}}</button>
<button mat-raised-button class="primaryBackground" (click)="confirmEdit(keyword.keywordID)">{{'topic-cloud-dialog.save' | translate}}</button>
</div>
</div>
</mat-expansion-panel>
</mat-accordion>
</mat-dialog-content>
// hide scrollbar
::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
//TODO: hide scrollbar for IE and Firefox
.margin-right {
margin-right: 16px;
}
.primary {
color: var(--primary);
}
.red {
color: var(--red);
}
.primaryBackground {
background-color: var(--primary);
}
.redBackground {
background-color: var(--red);
}
mat-panel-description, mat-panel-title, p, input {
color: var(--on-background);
}
mat-icon {
fill: currentColor;
}
mat-expansion-panel-header, mat-expansion-panel, mat-card {
background-color: var(--surface);
}
label {
color: var(--on-surface)
}
mat-slide-toggle {
margin-bottom: 16px;
display: block;
color: var(--on-surface);
}
mat-panel-title, mat-panel-description {
flex-basis: 0
}
@keyframes animation_blink_5s {
50% {
opacity: 0;
}
}
.edit-keyword .mat-panel-title {
color: var(--red) !important;
animation-name: animation_blink_5s;
animation-timing-function: ease-in;
animation-duration: 2s;
animation-iteration-count: 2;
opacity: 1.0 !important;
}
\ No newline at end of file
/*
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TopicCloudAdministrationComponent } from './topic-cloud-administration.component';
describe('TopicCloudAdministrationComponent', () => {
let component: TopicCloudAdministrationComponent;
let fixture: ComponentFixture<TopicCloudAdministrationComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ TopicCloudAdministrationComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(TopicCloudAdministrationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
*/
import { Component, OnInit } from '@angular/core';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { TagCloudComponent } from '../../tag-cloud/tag-cloud.component';
import { NotificationService } from '../../../../services/util/notification.service';
import { TopicCloudConfirmDialogComponent } from '../topic-cloud-confirm-dialog/topic-cloud-confirm-dialog.component';
import { AuthenticationService } from '../../../../services/http/authentication.service';
import { UserRole } from '../../../../models/user-roles.enum';
import { TranslateService } from '@ngx-translate/core';
import { LanguageService } from '../../../../services/util/language.service';
@Component({
selector: 'app-topic-cloud-administration',
templateUrl: './topic-cloud-administration.component.html',
styleUrls: ['./topic-cloud-administration.component.scss']
})
export class TopicCloudAdministrationComponent implements OnInit {
public panelOpenState = false;
public considerVotes: boolean; // should be sent back to tagCloud component
public tagsLowerCase: boolean; // should be sent back to tagCloud component
newKeyword = undefined;
edit = false;
isCreatorOrMod: boolean;
sortMode = 'alphabetic';
editedKeyword = false;
searchedKeyword = undefined;
searchMode = false;
filteredKeywords: Keyword[] = [];
keywords: Keyword[] = [
{
keywordID: 1,
keyword: 'Cloud',
questions: [
'Wieviel speicherplatz steht mir in der Cloud zur verfuegung? Ich habe eine Frage, sind Fragen zum thema \'Frage\' auch erlaubt?',
'Sollen wir die Tag Cloud implementieren?',
// eslint-disable-next-line max-len
'Wie genau ist die Cloud aufgebaut? Wieviel speicherplatz steht mir in der Cloud zur verfuegungWie genau ist die Cloud aufgebaut? Wieviel speicherplatz steht mir in der Cloud zur verfuegungWie genau ist die Cloud aufgebaut? Wieviel speicherplatz steht mir in der Cloud zur verfuegungWie genau ist die Cloud aufgebaut? Wieviel speicherplatz steht mir in der Cloud zur verfuegungWie genau ist die Cloud aufgebaut? Wieviel speicherplatz steht mir in der Cloud zur verfuegungWie genau ist die Cloud aufgebaut? Wieviel speicherplatz steht mir in der Cloud zur verfuegung',
]
},
{
keywordID: 2,
keyword: 'SWT',
questions: [
'Muss man fuer das Modul SWT bestanden haben?'
]
},
{
keywordID: 3,
keyword: 'Frage',
questions: [
'Das ist eine Lange Frage mit dem Thema \'frage\'',
'Ich habe eine Frage, sind Fragen zum thema \'Frage\' auch erlaubt?',
'Ich wollte Fragen ob sie gerne Sachen gefragt werden',
'Langsam geht mir die Fragerei mit den ganzen Fragen auf den Geist Frage'
]
},
{
keywordID: 4,
keyword: 'Klausur',
questions: [
'Darf man in der Klausur hilfmittel verwenden?',
'An welchem Termin findet die Klausur statt?'
]
},
{
keywordID: 5,
keyword: 'Diskrete Math',
questions: [
'wann wird die nächste veranstaltung stattfinden?',
'gibt es heute übung?'
]
},
];
constructor(public cloudDialogRef: MatDialogRef<TagCloudComponent>,
public confirmDialog: MatDialog,
private notificationService: NotificationService,
private authenticationService: AuthenticationService,
private translateService: TranslateService,
private langService: LanguageService) {
this.langService.langEmitter.subscribe(lang => {
this.translateService.use(lang);
});
}
ngOnInit(): void {
this.translateService.use(localStorage.getItem('currentLang'));
this.checkIfUserIsModOrCreator();
this.checkIfThereAreQuestions();
this.sortQuestions();
}
sortQuestions(sortMode?: string) {
if (sortMode !== undefined) {
this.sortMode = sortMode;
}
switch (this.sortMode) {
case 'alphabetic':
this.keywords.sort((a, b) => a.keyword.localeCompare(b.keyword));
break;
case 'questionsCount':
this.keywords.sort((a, b) => b.questions.length - a.questions.length);
break;
case 'voteCount':
console.log('not implemented!, sorting with question count');
this.keywords.sort((a, b) => b.questions.length - a.questions.length);
break;
}
}
checkIfUserIsModOrCreator() {
this.isCreatorOrMod = this.authenticationService.getRole() === UserRole.CREATOR ||
this.authenticationService.getRole() === UserRole.EDITING_MODERATOR ||
this.authenticationService.getRole() === UserRole.EXECUTIVE_MODERATOR;
}
checkIfThereAreQuestions() {
if (this.keywords.length === 0){
this.translateService.get('topic-cloud-dialog.nokeyword-note').subscribe(msg => {
this.notificationService.show(msg);
});
this.cloudDialogRef.close();
}
}
editKeyword(index: number): void {
this.edit = true;
setTimeout(() => {
document.getElementById('edit-input'+ index).focus();
}, 0);
}
deleteKeyword(id: number): void{
this.keywords.map(keyword => {
if (keyword.keywordID === id) {
this.keywords.splice(this.keywords.indexOf(keyword, 0), 1);
}
});
if (this.keywords.length === 0) {
this.cloudDialogRef.close();
}
if (this.searchMode === true){
/* update filtered array if it is searchmode */
this.searchKeyword();
}
}
cancelEdit(): void {
this.edit = false;
this.newKeyword = undefined;
}
confirmEdit(id: number): void {
this.keywords.map(keyword => {
if (keyword.keywordID === id) {
keyword.keyword = this.newKeyword.trim();
}
});
this.edit = false;
this.editedKeyword = true;
this.newKeyword = undefined;
this.sortQuestions();
if (this.searchMode){
this.searchKeyword();
}
}
openConfirmDialog(keyword: Keyword): void {
const confirmDialogRef = this.confirmDialog.open(TopicCloudConfirmDialogComponent, {
data: {topic: keyword.keyword}
});
confirmDialogRef.afterClosed().subscribe(result => {
if (result === 'delete') {
this.deleteKeyword(keyword.keywordID);
}
});
}
searchKeyword(): void {
if (!this.searchedKeyword){
this.searchMode = false;
} else {
this.filteredKeywords = this.keywords.filter(keyword =>
keyword.keyword.toLowerCase().includes(this.searchedKeyword.toLowerCase())
);
this.searchMode = true;
}
}
}
interface Keyword {
keywordID: number;
keyword: string;
questions: string[];
}
<h2 mat-dialog-title>{{'topic-cloud-confirm-dialog.confirm' | translate}}</h2>
<mat-divider></mat-divider>
<p>{{'topic-cloud-confirm-dialog.will-be-deleted' | translate }} '{{data.topic}}'.</p>
<!-- <div mat-dialog-actions align="end">
<button class="primary" mat-raised-button [mat-dialog-close]="false">
{{'topic-cloud-confirm-dialog.cancel' | translate}}</button>
<button class="warn" mat-raised-button [mat-dialog-close]="true">
{{'topic-cloud-confirm-dialog.delete' | translate}}
</button>
</div> -->
<app-dialog-action-buttons
buttonsLabelSection="topic-cloud-confirm-dialog"
confirmButtonLabel="delete"
[confirmButtonType]=confirmButtonType
[cancelButtonClickAction]="buildCloseDialogActionCallback()"
[confirmButtonClickAction]="buildDeleteAccountActionCallback()"
></app-dialog-action-buttons>
.primary {
background-color: var(--primary);
}
.warn {
background-color: var(--red);
}
/*
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TopicCloudConfirmDialogComponent } from './topic-cloud-confirm-dialog.component';
describe('TopicCloudConfirmDialogComponent', () => {
let component: TopicCloudConfirmDialogComponent;
let fixture: ComponentFixture<TopicCloudConfirmDialogComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ TopicCloudConfirmDialogComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(TopicCloudConfirmDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
*/
import { Component, Inject, OnInit } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { DialogConfirmActionButtonType } from '../../dialog/dialog-action-buttons/dialog-action-buttons.component';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'app-topic-cloud-confirm-dialog',
templateUrl: './topic-cloud-confirm-dialog.component.html',
styleUrls: ['./topic-cloud-confirm-dialog.component.scss']
})
export class TopicCloudConfirmDialogComponent implements OnInit {
confirmButtonType: DialogConfirmActionButtonType = DialogConfirmActionButtonType.Alert;
constructor(
public confirmDialogRef: MatDialogRef<TopicCloudConfirmDialogComponent>,
private translationService: TranslateService,
@Inject(MAT_DIALOG_DATA) public data: DialogData) { }
ngOnInit(): void {
}
onNoClick(): void {
this.confirmDialogRef.close();
}
close(type: string): void {
this.confirmDialogRef.close(type);
}
/**
* Returns a lambda which closes the dialog on call.
*/
buildCloseDialogActionCallback(): () => void {
return () => this.close('abort');
}
/**
* Returns a lambda which executes the dialog dedicated action on call.
*/
buildDeleteAccountActionCallback(): () => void {
return () => this.close('delete');
}
}
export interface DialogData {
topic: string;
}
<div>
<p>
<!--{{(isCollapsed) ? question : question | slice:0:maxShowedCharachters}}{{question.length > maxShowedCharachters && !isCollapsed? "..." : ""}} -->
<span *ngFor="let part Of partsOfQuestion; let i = index">{{part}}<mark *ngIf="i < partsOfQuestion.length -1">{{keyword}}</mark></span>
<button
*ngIf = "question.length > maxShowedCharachters"
(click)="isCollapsed = !isCollapsed">
{{"dialog-comment.read-" + (!isCollapsed ? 'more': 'less') | translate}}
</button>
</p>
</div>
mat-panel-description, mat-panel-title, p, input {
color: var(--on-background);
}
mat-icon {
fill: currentColor;
}
label {
color: var(--on-surface)
}
button{
color: var(--primary);
background: none;
font-weight: bold;
border: 0px solid;
}
button:focus{
outline: none;
}
button:hover{
text-decoration: underline;
}
span {
margin-left: 0px;
padding-left: 0px;
}
mark {
background: none;
color: var(--primary);
}
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-topic-dialog-comment',
templateUrl: './topic-dialog-comment.component.html',
styleUrls: ['./topic-dialog-comment.component.scss']
})
export class TopicDialogCommentComponent implements OnInit {
@Input() question: string;
@Input() keyword: string ;
@Input() maxShowedCharachters: number;
@Input() isCollapsed = false;
constructor() { }
get partsOfQuestion(){
return this.question.slice(0,this.isCollapsed? this.question.length: this.maxShowedCharachters).split(new RegExp(this.keyword,'i')) ;
}
ngOnInit(): void {
}
}
......@@ -29,8 +29,11 @@ import { QRCodeModule } from 'angularx-qrcode';
import { MotdDialogComponent } from './_dialogs/motd-dialog/motd-dialog.component';
import { MotdMessageComponent } from './_dialogs/motd-dialog/motd-message/motd-message.component';
import { TagCloudModule } from 'angular-tag-cloud-module';
import {CloudConfigurationComponent} from "./_dialogs/cloud-configuration/cloud-configuration.component";
import { CloudConfigurationComponent } from "./_dialogs/cloud-configuration/cloud-configuration.component";
import { ColorPickerModule } from 'ngx-color-picker';
import { TopicCloudConfirmDialogComponent } from './_dialogs/topic-cloud-confirm-dialog/topic-cloud-confirm-dialog.component';
import { TopicCloudAdministrationComponent } from './_dialogs/topic-cloud-administration/topic-cloud-administration.component';
import { TopicDialogCommentComponent } from './dialog/topic-dialog-comment/topic-dialog-comment.component';
import { TopicCloudFilterComponent } from './_dialogs/topic-cloud-filter/topic-cloud-filter.component';
import { SpacyDialogComponent } from './_dialogs/spacy-dialog/spacy-dialog.component';
......@@ -70,6 +73,9 @@ import { SpacyDialogComponent } from './_dialogs/spacy-dialog/spacy-dialog.compo
CommentAnswerComponent,
MotdDialogComponent,
MotdMessageComponent,
TopicCloudConfirmDialogComponent,
TopicCloudAdministrationComponent,
TopicDialogCommentComponent,
TopicCloudFilterComponent,
SpacyDialogComponent
],
......
......@@ -24,6 +24,7 @@ import {UserRole} from '../../../models/user-roles.enum';
import {RoomService} from '../../../services/http/room.service';
import {ThemeService} from '../../../../theme/theme.service';
import {CloudParameters} from './tag-cloud.interface';
import { TopicCloudAdministrationComponent } from '../_dialogs/topic-cloud-administration/topic-cloud-administration.component';
class CustomPosition implements Position {
left: number;
......@@ -199,8 +200,10 @@ export class TagCloudComponent implements OnInit {
} else if (e === 'topicCloudConfig') {
this.configurationOpen = !this.configurationOpen;
} else if (e === 'topicCloudAdministration') {
// TODO Group 5: OPEN Topic Cloud Administration
}
this.dialog.open(TopicCloudAdministrationComponent, {
minWidth: '50%'
});
}
});
this.authenticationService.watchUser.subscribe(newUser => {
if (newUser) {
......
......@@ -219,6 +219,36 @@
"overview-question-tooltip": "Anzahl gestellter Fragen",
"overview-questioners-tooltip": "Anzahl Fragensteller*innen"
},
"tag-cloud": {
"config": "Wolkenansicht ändern",
"administration": "Wolkenthemen editieren"
},
"topic-cloud-dialog": {
"cancel": "Abbrechen",
"save": "Speichern",
"edit": "Bearbeiten",
"delete": "Löschen",
"question-count-singular": "Frage",
"question-count-plural": "Fragen",
"edit-keyword-tip": "Neues Thema",
"no-keywords-note": "Es gibt keine Themen",
"consider-votes": "Votes berücksichtigen",
"tags-lowercase": "Themen klein schreiben",
"sort-alpha": "Alphabetisch",
"sort-count": "Fragenanzahl",
"sort-vote": "Votes",
"keyword-search": "Stichwort suchen"
},
"topic-cloud-confirm-dialog": {
"cancel": "Abbrechen",
"delete": "Löschen",
"confirm": "Sind Sie sicher?",
"will-be-deleted": "Thema wird gelöscht"
},
"dialog-comment": {
"read-more": "Mehr lesen",
"read-less": "Weniger lesen"
},
"tag-cloud-config":{
"title":"Tag-Cloud Einstellungen",
"general":"Allgemeine Einstellungen",
......@@ -238,7 +268,6 @@
"font-size-min":"Schriftgröße min",
"font-size-max":"Schriftgröße max",
"select-color": "Farbauswahl",
"random-angle-tooltip": "Anordnung der Winkel zufällig generieren",
"background-tooltip": "Auswahl der Hintergrundfarbe",
"word-delay-tooltip": "Animationsverzögerung der Wörter",
......
......@@ -121,7 +121,6 @@
"cancel": "Cancel",
"cancel-description": "Cancel",
"comment": "Question {{ comment }} was asked at {{ time }} and has currently {{ votes }}. {{correct}} {{wrong}} {{bonus}} {{beamer}}",
"delete": "Delete your question",
"enter-comment": "Enter your question …",
"Markdown-hint": "Format with Markdown",
"enter-title": "Title",
......@@ -225,6 +224,36 @@
"overview-question-tooltip": "Number of questions",
"overview-questioners-tooltip": "Number of questioners"
},
"tag-cloud": {
"config": "Modify cloud view",
"administration": "Edit cloud topics"
},
"topic-cloud-dialog":{
"edit": "Edit",
"delete": "Delete",
"cancel": "Cancel",
"save": "Save",
"question-count-singular": "Question",
"question-count-plural": "Questions",
"edit-keyword-tip": "New topic",
"no-keywords-note": "There are no topics!",
"consider-votes": "Consider Votes",
"tags-lowercase": "Topics in lowercase",
"sort-alpha": "Alphabetically",
"sort-count": "Questions count",
"sort-vote": "Votes",
"keyword-search": "Search keyword"
},
"topic-cloud-confirm-dialog":{
"cancel": "Cancel",
"delete": "Delete",
"confirm": "Are you sure?",
"will-be-deleted": "Topic will be deleted"
},
"dialog-comment":{
"read-more": "Read more",
"read-less": "Read less"
},
"tag-cloud-config":{
"title":"Tag-Cloud Options",
"general":"General Options",
......@@ -244,7 +273,6 @@
"font-size-min":"Font size min",
"font-size-max":"Font size max",
"select-color": "Selected color",
"random-angle-tooltip": "Generate angle randomly",
"background-tooltip": "Select background-color",
"word-delay-tooltip": "Select word-delay",
......
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