add show
This commit is contained in:
4592
package-lock.json
generated
4592
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
69
package.json
69
package.json
@@ -12,44 +12,45 @@
|
|||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "~9.0.2",
|
"@angular/animations": "~9.0.5",
|
||||||
"@angular/cdk": "~9.0.1",
|
"@angular/cdk": "^9.1.1",
|
||||||
"@angular/common": "~9.0.2",
|
"@angular/common": "~9.0.5",
|
||||||
"@angular/compiler": "~9.0.2",
|
"@angular/compiler": "~9.0.5",
|
||||||
"@angular/core": "~9.0.2",
|
"@angular/core": "~9.0.5",
|
||||||
"@angular/fire": "^5.2.3",
|
"@angular/fire": "^5.4.2",
|
||||||
"@angular/forms": "~9.0.2",
|
"@angular/forms": "~9.0.5",
|
||||||
"@angular/material": "^9.0.1",
|
"@angular/material": "^9.1.1",
|
||||||
"@angular/platform-browser": "~9.0.2",
|
"@angular/platform-browser": "~9.0.5",
|
||||||
"@angular/platform-browser-dynamic": "~9.0.2",
|
"@angular/platform-browser-dynamic": "~9.0.5",
|
||||||
"@angular/router": "~9.0.2",
|
"@angular/router": "~9.0.5",
|
||||||
"@angular/service-worker": "~9.0.2",
|
"@angular/service-worker": "~9.0.5",
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.25",
|
"@fortawesome/angular-fontawesome": "^0.6.0",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.11.2",
|
"@fortawesome/fontawesome-svg-core": "^1.2.27",
|
||||||
"firebase": "^7.4.0",
|
"@fortawesome/free-solid-svg-icons": "^5.12.1",
|
||||||
|
"firebase": "^7.10.0",
|
||||||
"rxjs": "~6.5.4",
|
"rxjs": "~6.5.4",
|
||||||
"tslib": "^1.10.0",
|
"tslib": "^1.11.1",
|
||||||
"zone.js": "~0.10.2"
|
"zone.js": "~0.10.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "~0.900.3",
|
"@angular-devkit/build-angular": "~0.900.5",
|
||||||
"@angular/cli": "~9.0.3",
|
"@angular/cli": "~9.0.5",
|
||||||
"@angular/compiler-cli": "~9.0.2",
|
"@angular/compiler-cli": "~9.0.5",
|
||||||
"@angular/language-service": "~9.0.2",
|
"@angular/language-service": "~9.0.5",
|
||||||
"@types/node": "^12.11.1",
|
"@types/jasmine": "~3.5.8",
|
||||||
"@types/jasmine": "~3.3.8",
|
"@types/jasminewd2": "~2.0.8",
|
||||||
"@types/jasminewd2": "~2.0.3",
|
"@types/node": "^13.9.0",
|
||||||
"codelyzer": "^5.1.2",
|
"codelyzer": "^5.2.1",
|
||||||
"jasmine-core": "~3.4.0",
|
"jasmine-core": "~3.5.0",
|
||||||
"jasmine-spec-reporter": "~4.2.1",
|
"jasmine-spec-reporter": "~4.2.1",
|
||||||
"karma": "~4.1.0",
|
"karma": "~4.4.1",
|
||||||
"karma-chrome-launcher": "~2.2.0",
|
"karma-chrome-launcher": "~3.1.0",
|
||||||
"karma-coverage-istanbul-reporter": "~2.0.1",
|
"karma-coverage-istanbul-reporter": "~2.1.1",
|
||||||
"karma-jasmine": "~2.0.1",
|
"karma-jasmine": "~3.1.1",
|
||||||
"karma-jasmine-html-reporter": "^1.4.0",
|
"karma-jasmine-html-reporter": "^1.5.2",
|
||||||
"protractor": "~5.4.0",
|
"protractor": "~5.4.3",
|
||||||
"ts-node": "~7.0.0",
|
"ts-node": "~8.6.2",
|
||||||
"tslint": "~5.15.0",
|
"tslint": "~6.0.0",
|
||||||
"typescript": "~3.7.5"
|
"typescript": "^3.7.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {animate, state, style, transition, trigger} from '@angular/animations';
|
import {animate, query, state, style, transition, trigger} from '@angular/animations';
|
||||||
|
|
||||||
export const fade = [
|
export const fade = [
|
||||||
// the fade-in/fade-out animation.
|
// the fade-in/fade-out animation.
|
||||||
@@ -18,3 +18,23 @@ export const fade = [
|
|||||||
animate(300, style({opacity: 0, display: 'block', transform: 'translateY(-20px)'})))
|
animate(300, style({opacity: 0, display: 'block', transform: 'translateY(-20px)'})))
|
||||||
])
|
])
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const fader =
|
||||||
|
trigger('fader', [
|
||||||
|
transition('* <=> *', [
|
||||||
|
// Set a default style for enter and leave
|
||||||
|
query(':enter, :leave', [
|
||||||
|
style({
|
||||||
|
position: 'absolute',
|
||||||
|
left: 0,
|
||||||
|
width: '100%',
|
||||||
|
opacity: 0,
|
||||||
|
transform: 'scale(0.96) translateY(-10px)',
|
||||||
|
}),
|
||||||
|
], {optional: true}),
|
||||||
|
// Animate the new page in
|
||||||
|
query(':enter', [
|
||||||
|
animate('200ms ease', style({opacity: 1, transform: 'scale(1) translateY(0)'})),
|
||||||
|
], {optional: true}),
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|||||||
@@ -14,6 +14,12 @@ const routes: Routes = [
|
|||||||
canActivate: [AngularFireAuthGuard],
|
canActivate: [AngularFireAuthGuard],
|
||||||
data: {authGuardPipe: () => redirectUnauthorizedTo(['user', 'login'])}
|
data: {authGuardPipe: () => redirectUnauthorizedTo(['user', 'login'])}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'show',
|
||||||
|
loadChildren: () => import('./modules/show/show.module').then(m => m.ShowModule),
|
||||||
|
canActivate: [AngularFireAuthGuard],
|
||||||
|
data: {authGuardPipe: () => redirectUnauthorizedTo(['user', 'login'])}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'user',
|
path: 'user',
|
||||||
loadChildren: () => import('./modules/user/user.module').then(m => m.UserModule)
|
loadChildren: () => import('./modules/user/user.module').then(m => m.UserModule)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<app-navigation></app-navigation>
|
<app-navigation></app-navigation>
|
||||||
<main class="content">
|
<div [@fader]="o.isActivated ? o.activatedRoute : ''" class="content">
|
||||||
<router-outlet></router-outlet>
|
<router-outlet #o="outlet"></router-outlet>
|
||||||
</main>
|
</div>
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ h1 {
|
|||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
|
||||||
margin-top: 60px;
|
.manager {
|
||||||
display: flex;
|
//display: grid;
|
||||||
justify-content: center;
|
//grid-template-columns: 1fr 1fr;
|
||||||
|
//transition: all 1s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import {Component} from '@angular/core';
|
import {Component} from '@angular/core';
|
||||||
|
import {fader} from './animations';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrls: ['./app.component.less']
|
styleUrls: ['./app.component.less'],
|
||||||
|
animations: [fader]
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
title = 'wgenerator';
|
title = 'wgenerator';
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {AngularFireStorageModule} from '@angular/fire/storage';
|
|||||||
import {AngularFireDatabaseModule} from '@angular/fire/database';
|
import {AngularFireDatabaseModule} from '@angular/fire/database';
|
||||||
import {AngularFireAuthModule} from '@angular/fire/auth';
|
import {AngularFireAuthModule} from '@angular/fire/auth';
|
||||||
import {AngularFireAuthGuardModule} from '@angular/fire/auth-guard';
|
import {AngularFireAuthGuardModule} from '@angular/fire/auth-guard';
|
||||||
|
import {MAT_DATE_LOCALE} from '@angular/material/core';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -27,7 +28,6 @@ import {AngularFireAuthGuardModule} from '@angular/fire/auth-guard';
|
|||||||
|
|
||||||
ApplicationFrameModule,
|
ApplicationFrameModule,
|
||||||
|
|
||||||
|
|
||||||
AngularFireModule.initializeApp(environment.firebase),
|
AngularFireModule.initializeApp(environment.firebase),
|
||||||
AngularFirestoreModule.enablePersistence({synchronizeTabs: true}),
|
AngularFirestoreModule.enablePersistence({synchronizeTabs: true}),
|
||||||
AngularFireStorageModule,
|
AngularFireStorageModule,
|
||||||
@@ -36,8 +36,11 @@ import {AngularFireAuthGuardModule} from '@angular/fire/auth-guard';
|
|||||||
AngularFireAuthGuardModule,
|
AngularFireAuthGuardModule,
|
||||||
|
|
||||||
],
|
],
|
||||||
providers: [],
|
providers: [
|
||||||
bootstrap: [AppComponent]
|
{provide: MAT_DATE_LOCALE, useValue: 'de-DE'},
|
||||||
|
],
|
||||||
|
bootstrap: [AppComponent],
|
||||||
|
|
||||||
})
|
})
|
||||||
export class AppModule {
|
export class AppModule {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<div class="list-item">
|
||||||
|
<div>{{show.showType|showType}}</div>
|
||||||
|
<div>{{show.date.toDate()|date:'dd.MM.yyyy HH.mm'}}</div>
|
||||||
|
</div>
|
||||||
26
src/app/modules/show/list/list-item/list-item.component.less
Normal file
26
src/app/modules/show/list/list-item/list-item.component.less
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
@import "../../../../../styles/styles";
|
||||||
|
|
||||||
|
.list-item {
|
||||||
|
padding: 5px 20px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
min-height: 34px;
|
||||||
|
|
||||||
|
& > div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @primary-color;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.number {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||||
|
|
||||||
|
import {ListItemComponent} from './list-item.component';
|
||||||
|
|
||||||
|
describe('ListItemComponent', () => {
|
||||||
|
let component: ListItemComponent;
|
||||||
|
let fixture: ComponentFixture<ListItemComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ListItemComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ListItemComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
18
src/app/modules/show/list/list-item/list-item.component.ts
Normal file
18
src/app/modules/show/list/list-item/list-item.component.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import {Component, Input, OnInit} from '@angular/core';
|
||||||
|
import {Show} from '../../services/show';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list-item',
|
||||||
|
templateUrl: './list-item.component.html',
|
||||||
|
styleUrls: ['./list-item.component.less']
|
||||||
|
})
|
||||||
|
export class ListItemComponent implements OnInit {
|
||||||
|
@Input() public show: Show;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
7
src/app/modules/show/list/list.component.html
Normal file
7
src/app/modules/show/list/list.component.html
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<div>
|
||||||
|
<app-list-header></app-list-header>
|
||||||
|
|
||||||
|
<app-card *ngIf="shows$ | async as shows" [@fade] [padding]="false">
|
||||||
|
<app-list-item *ngFor="let show of shows" [routerLink]="show.id" [show]="show"></app-list-item>
|
||||||
|
</app-card>
|
||||||
|
</div>
|
||||||
0
src/app/modules/show/list/list.component.less
Normal file
0
src/app/modules/show/list/list.component.less
Normal file
25
src/app/modules/show/list/list.component.spec.ts
Normal file
25
src/app/modules/show/list/list.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||||
|
|
||||||
|
import {ListComponent} from './list.component';
|
||||||
|
|
||||||
|
describe('ListComponent', () => {
|
||||||
|
let component: ListComponent;
|
||||||
|
let fixture: ComponentFixture<ListComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ListComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ListComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
20
src/app/modules/show/list/list.component.ts
Normal file
20
src/app/modules/show/list/list.component.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {Observable} from 'rxjs';
|
||||||
|
import {Show} from '../services/show';
|
||||||
|
import {ShowDataService} from '../services/show-data.service';
|
||||||
|
import {fade} from '../../../animations';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list',
|
||||||
|
templateUrl: './list.component.html',
|
||||||
|
styleUrls: ['./list.component.less'],
|
||||||
|
animations: [fade]
|
||||||
|
})
|
||||||
|
export class ListComponent {
|
||||||
|
public shows$: Observable<Show[]>;
|
||||||
|
|
||||||
|
constructor(showDataService: ShowDataService) {
|
||||||
|
this.shows$ = showDataService.list$();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
34
src/app/modules/show/new/new.component.html
Normal file
34
src/app/modules/show/new/new.component.html
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<div>
|
||||||
|
<app-card *ngIf="!publicChosen">
|
||||||
|
<h1>Neue Veranstaltung</h1>
|
||||||
|
<app-button-row>
|
||||||
|
<button (click)="onIsPublic(true)" mat-button>Ja</button>
|
||||||
|
<button (click)="onIsPublic(false)" mat-button>Nein</button>
|
||||||
|
<p class="inline"> Handelt es sich um eine öffentliche Veranstaltung? </p>
|
||||||
|
</app-button-row>
|
||||||
|
</app-card>
|
||||||
|
|
||||||
|
<app-card *ngIf="publicChosen">
|
||||||
|
<h1>Neue Veranstaltung</h1>
|
||||||
|
|
||||||
|
<div [formGroup]="form" class="split">
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Datum</mat-label>
|
||||||
|
<input [matDatepicker]="picker" formControlName="date" matInput>
|
||||||
|
<mat-datepicker-toggle [for]="picker" matSuffix></mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #picker touchUi></mat-datepicker>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Art der Veranstaltung</mat-label>
|
||||||
|
<mat-select formControlName="showType">
|
||||||
|
<mat-option *ngFor="let key of showType" [value]="key">{{key|showType}}</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<app-button-row>
|
||||||
|
<button (click)="onSave()" color="primary" mat-flat-button>Anlegen</button>
|
||||||
|
<button mat-button routerLink="/show">Abbrechen</button>
|
||||||
|
</app-button-row>
|
||||||
|
</app-card>
|
||||||
|
</div>
|
||||||
9
src/app/modules/show/new/new.component.less
Normal file
9
src/app/modules/show/new/new.component.less
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
.split {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
column-gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
25
src/app/modules/show/new/new.component.spec.ts
Normal file
25
src/app/modules/show/new/new.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||||
|
|
||||||
|
import {NewComponent} from './new.component';
|
||||||
|
|
||||||
|
describe('NewComponent', () => {
|
||||||
|
let component: NewComponent;
|
||||||
|
let fixture: ComponentFixture<NewComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [NewComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(NewComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
44
src/app/modules/show/new/new.component.ts
Normal file
44
src/app/modules/show/new/new.component.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {ShowDataService} from '../services/show-data.service';
|
||||||
|
import {Observable} from 'rxjs';
|
||||||
|
import {Show} from '../services/show';
|
||||||
|
import {ShowService} from '../services/show.service';
|
||||||
|
import {FormControl, FormGroup, Validators} from '@angular/forms';
|
||||||
|
import {Router} from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-new',
|
||||||
|
templateUrl: './new.component.html',
|
||||||
|
styleUrls: ['./new.component.less']
|
||||||
|
})
|
||||||
|
export class NewComponent implements OnInit {
|
||||||
|
public shows$: Observable<Show[]>;
|
||||||
|
public showType = this.showService.SHOW_TYPE;
|
||||||
|
public form: FormGroup;
|
||||||
|
public publicChosen = false;
|
||||||
|
|
||||||
|
constructor(private showService: ShowService, showDataService: ShowDataService, private router: Router) {
|
||||||
|
this.shows$ = showDataService.list$();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnInit(): void {
|
||||||
|
this.form = new FormGroup({
|
||||||
|
public: new FormControl(null),
|
||||||
|
date: new FormControl(null, Validators.required),
|
||||||
|
showType: new FormControl(null, Validators.required),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
public onIsPublic(isPublic: boolean): void {
|
||||||
|
this.form.patchValue({public: isPublic});
|
||||||
|
this.publicChosen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onSave() {
|
||||||
|
this.form.markAllAsTouched();
|
||||||
|
if (!this.form.valid) return;
|
||||||
|
|
||||||
|
const id = await this.showService.new(this.form.value);
|
||||||
|
await this.router.navigateByUrl('/show/' + id);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/app/modules/show/services/show-data.service.spec.ts
Normal file
12
src/app/modules/show/services/show-data.service.spec.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import {TestBed} from '@angular/core/testing';
|
||||||
|
|
||||||
|
import {ShowDataService} from './show-data.service';
|
||||||
|
|
||||||
|
describe('ShowDataService', () => {
|
||||||
|
beforeEach(() => TestBed.configureTestingModule({}));
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const service: ShowDataService = TestBed.get(ShowDataService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
17
src/app/modules/show/services/show-data.service.ts
Normal file
17
src/app/modules/show/services/show-data.service.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {Observable} from 'rxjs';
|
||||||
|
import {DbService} from '../../../services/db.service';
|
||||||
|
import {Show} from './show';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ShowDataService {
|
||||||
|
constructor(private dbService: DbService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public list$ = (): Observable<Show[]> => this.dbService.col$('show');
|
||||||
|
public read$ = (showId: string): Observable<Show | undefined> => this.dbService.doc$('show/' + showId);
|
||||||
|
public update = async (showId: string, data: Partial<Show>): Promise<void> => await this.dbService.doc(showId).update(data);
|
||||||
|
public add = async (data: Partial<Show>): Promise<string> => (await this.dbService.col('show').add(data)).id
|
||||||
|
}
|
||||||
12
src/app/modules/show/services/show.service.spec.ts
Normal file
12
src/app/modules/show/services/show.service.spec.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import {TestBed} from '@angular/core/testing';
|
||||||
|
|
||||||
|
import {ShowService} from './show.service';
|
||||||
|
|
||||||
|
describe('ShowService', () => {
|
||||||
|
beforeEach(() => TestBed.configureTestingModule({}));
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const service: ShowService = TestBed.get(ShowService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
18
src/app/modules/show/services/show.service.ts
Normal file
18
src/app/modules/show/services/show.service.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {ShowDataService} from './show-data.service';
|
||||||
|
import {Show} from './show';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ShowService {
|
||||||
|
|
||||||
|
public SHOW_TYPE = ['praise', 'worship', 'homegroup', 'prayergroup'];
|
||||||
|
|
||||||
|
constructor(private showDataService: ShowDataService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public async new(data: Partial<Show>): Promise<string> {
|
||||||
|
return await this.showDataService.add(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/app/modules/show/services/show.ts
Normal file
12
src/app/modules/show/services/show.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import * as firebase from 'firebase';
|
||||||
|
import Timestamp = firebase.firestore.Timestamp;
|
||||||
|
|
||||||
|
|
||||||
|
export interface Show {
|
||||||
|
id: string;
|
||||||
|
showType: string;
|
||||||
|
date: Timestamp;
|
||||||
|
owner: string;
|
||||||
|
public: boolean;
|
||||||
|
reported: boolean;
|
||||||
|
}
|
||||||
24
src/app/modules/show/show-routing.module.ts
Normal file
24
src/app/modules/show/show-routing.module.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
import {RouterModule, Routes} from '@angular/router';
|
||||||
|
import {NewComponent} from './new/new.component';
|
||||||
|
import {ListComponent} from './list/list.component';
|
||||||
|
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
pathMatch: 'full',
|
||||||
|
component: ListComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'new',
|
||||||
|
component: NewComponent
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class ShowRoutingModule {
|
||||||
|
}
|
||||||
42
src/app/modules/show/show.module.ts
Normal file
42
src/app/modules/show/show.module.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
import {CommonModule} from '@angular/common';
|
||||||
|
|
||||||
|
import {ShowRoutingModule} from './show-routing.module';
|
||||||
|
import {NewComponent} from './new/new.component';
|
||||||
|
import {CardModule} from '../../widget-modules/components/card/card.module';
|
||||||
|
import {MatFormFieldModule} from '@angular/material/form-field';
|
||||||
|
import {ReactiveFormsModule} from '@angular/forms';
|
||||||
|
import {MatInputModule} from '@angular/material/input';
|
||||||
|
import {ListComponent} from './list/list.component';
|
||||||
|
import {ListItemComponent} from './list/list-item/list-item.component';
|
||||||
|
import {ListHeaderModule} from '../../widget-modules/list-header/list-header.module';
|
||||||
|
import {MatCheckboxModule} from '@angular/material/checkbox';
|
||||||
|
import {ButtonRowModule} from '../../widget-modules/components/button-row/button-row.module';
|
||||||
|
import {MatButtonModule} from '@angular/material/button';
|
||||||
|
import {MatDatepickerModule} from '@angular/material/datepicker';
|
||||||
|
import {MatSelectModule} from '@angular/material/select';
|
||||||
|
import {ShowTypeTranslaterModule} from '../../widget-modules/pipes/show-type-translater/show-type-translater.module';
|
||||||
|
import {MatNativeDateModule} from '@angular/material/core';
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [NewComponent, ListComponent, ListItemComponent],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
ShowRoutingModule,
|
||||||
|
CardModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
MatInputModule,
|
||||||
|
ListHeaderModule,
|
||||||
|
MatCheckboxModule,
|
||||||
|
ButtonRowModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatDatepickerModule,
|
||||||
|
MatNativeDateModule,
|
||||||
|
MatSelectModule,
|
||||||
|
ShowTypeTranslaterModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class ShowModule {
|
||||||
|
}
|
||||||
@@ -1,27 +1,27 @@
|
|||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {SongDataService} from './song-data.service';
|
|
||||||
import {File} from './file';
|
import {File} from './file';
|
||||||
import {Observable} from 'rxjs';
|
import {Observable} from 'rxjs';
|
||||||
import {map} from 'rxjs/operators';
|
import {map} from 'rxjs/operators';
|
||||||
import {FileServer} from './fileServer';
|
import {FileServer} from './fileServer';
|
||||||
|
import {DbService} from '../../../services/db.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class FileDataService {
|
export class FileDataService {
|
||||||
|
|
||||||
constructor(private songDataService: SongDataService) {
|
constructor(private db: DbService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async put(songId: string, file: FileServer): Promise<string> {
|
public async set(songId: string, file: FileServer): Promise<string> {
|
||||||
const songRef = this.songDataService.getSongRef(songId);
|
const songRef = this.db.doc('songs/' + songId);
|
||||||
const fileCollection = songRef.collection('files');
|
const fileCollection = songRef.collection('files');
|
||||||
const id = await fileCollection.add(file);
|
const id = await fileCollection.add(file);
|
||||||
return id.id;
|
return id.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get$(songId: string): Observable<File[]> {
|
public read$(songId: string): Observable<File[]> {
|
||||||
const songRef = this.songDataService.getSongRef(songId);
|
const songRef = this.db.doc('songs/' + songId);
|
||||||
return songRef.collection<File>('files').snapshotChanges().pipe(map(actions => {
|
return songRef.collection<File>('files').snapshotChanges().pipe(map(actions => {
|
||||||
return actions.map(a => ({
|
return actions.map(a => ({
|
||||||
...a.payload.doc.data(),
|
...a.payload.doc.data(),
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ describe('SongDataService', () => {
|
|||||||
|
|
||||||
it('should list songs', async(() => {
|
it('should list songs', async(() => {
|
||||||
const service: SongDataService = TestBed.get(SongDataService);
|
const service: SongDataService = TestBed.get(SongDataService);
|
||||||
service.list().subscribe(s => {
|
service.list$().subscribe(s => {
|
||||||
expect(s).toEqual([
|
expect(s).toEqual([
|
||||||
{title: 'title1'}
|
{title: 'title1'}
|
||||||
] as any);
|
] as any);
|
||||||
|
|||||||
@@ -1,40 +1,17 @@
|
|||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {AngularFirestore, AngularFirestoreCollection} from '@angular/fire/firestore';
|
import {Song} from './song';
|
||||||
import {Song} from '../models/song';
|
|
||||||
import {Observable} from 'rxjs';
|
import {Observable} from 'rxjs';
|
||||||
import {map} from 'rxjs/operators';
|
import {DbService} from '../../../services/db.service';
|
||||||
import {AngularFirestoreDocument} from '@angular/fire/firestore/document/document';
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class SongDataService {
|
export class SongDataService {
|
||||||
private songCollection: AngularFirestoreCollection<Song>;
|
constructor(private dbService: DbService) {
|
||||||
private readonly songs: Observable<Song[]>;
|
|
||||||
|
|
||||||
constructor(private afs: AngularFirestore) {
|
|
||||||
this.songCollection = afs.collection<Song>('songs');
|
|
||||||
this.songs = this.songCollection.snapshotChanges().pipe(map(actions => {
|
|
||||||
return actions.map(a => ({
|
|
||||||
...a.payload.doc.data(),
|
|
||||||
id: a.payload.doc.id
|
|
||||||
}));
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public list = (): Observable<Song[]> => this.songs;
|
public list$ = (): Observable<Song[]> => this.dbService.col$('songs');
|
||||||
|
public read$ = (songId: string): Observable<Song | undefined> => this.dbService.doc$('songs/' + songId);
|
||||||
public getSongRef = (songId: string): AngularFirestoreDocument<Song> => this.afs.doc<Song>('songs/' + songId);
|
public update = async (songId: string, data: any): Promise<void> => await this.dbService.doc(songId).update(data);
|
||||||
|
|
||||||
public read(songId: string): Observable<Song | undefined> {
|
|
||||||
return this.getSongRef(songId).valueChanges().pipe(map(song => ({
|
|
||||||
...song,
|
|
||||||
id: songId
|
|
||||||
} as Song)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async update(songId: string, data: any): Promise<void> {
|
|
||||||
await this.getSongRef(songId).update(data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {Observable} from 'rxjs';
|
import {Observable} from 'rxjs';
|
||||||
import {Song} from '../models/song';
|
import {Song} from './song';
|
||||||
import {SongDataService} from './song-data.service';
|
import {SongDataService} from './song-data.service';
|
||||||
import {tap} from 'rxjs/operators';
|
import {tap} from 'rxjs/operators';
|
||||||
|
|
||||||
@@ -26,8 +26,8 @@ export class SongService {
|
|||||||
importCCLI = (songs: Song[]) => this.updateFromCLI(songs);
|
importCCLI = (songs: Song[]) => this.updateFromCLI(songs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public list$ = (): Observable<Song[]> => this.songDataService.list().pipe(tap(_ => this.list = _));
|
public list$ = (): Observable<Song[]> => this.songDataService.list$().pipe(tap(_ => this.list = _));
|
||||||
public read = (songId: string): Observable<Song | undefined> => this.songDataService.read(songId);
|
public read = (songId: string): Observable<Song | undefined> => this.songDataService.read$(songId);
|
||||||
|
|
||||||
public async update(songId: string, data: any): Promise<void> {
|
public async update(songId: string, data: any): Promise<void> {
|
||||||
await this.songDataService.update(songId, data);
|
await this.songDataService.update(songId, data);
|
||||||
|
|||||||
@@ -55,6 +55,6 @@ export class UploadService extends FileBase {
|
|||||||
path: upload.path,
|
path: upload.path,
|
||||||
createdAt: new Date()
|
createdAt: new Date()
|
||||||
};
|
};
|
||||||
await this.fileDataService.put(songId, file);
|
await this.fileDataService.set(songId, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import {Component, Input, OnInit} from '@angular/core';
|
import {Component, Input, OnInit} from '@angular/core';
|
||||||
import {Song} from '../../models/song';
|
import {Song} from '../../services/song';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-list-item',
|
selector: 'app-list-item',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {Component, OnInit} from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import {SongService} from '../services/song.service';
|
import {SongService} from '../services/song.service';
|
||||||
import {Song} from '../models/song';
|
import {Song} from '../services/song';
|
||||||
import {debounceTime, map} from 'rxjs/operators';
|
import {debounceTime, map} from 'rxjs/operators';
|
||||||
import {combineLatest, Observable} from 'rxjs';
|
import {combineLatest, Observable} from 'rxjs';
|
||||||
import {fade} from '../../../animations';
|
import {fade} from '../../../animations';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import {Component, OnInit} from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import {Song} from '../../../models/song';
|
import {Song} from '../../../services/song';
|
||||||
import {FormGroup} from '@angular/forms';
|
import {FormGroup} from '@angular/forms';
|
||||||
import {ActivatedRoute, Router} from '@angular/router';
|
import {ActivatedRoute, Router} from '@angular/router';
|
||||||
import {SongService} from '../../../services/song.service';
|
import {SongService} from '../../../services/song.service';
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
|
<div>
|
||||||
<app-edit-song></app-edit-song>
|
<app-edit-song></app-edit-song>
|
||||||
<app-edit-file></app-edit-file>
|
<app-edit-file></app-edit-file>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {Song} from '../../models/song';
|
import {Song} from '../../services/song';
|
||||||
import {FormControl, FormGroup} from '@angular/forms';
|
import {FormControl, FormGroup} from '@angular/forms';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<div class="split">
|
||||||
<app-card *ngIf="song$ | async as song" [heading]="song.number + ' - ' + song.title">
|
<app-card *ngIf="song$ | async as song" [heading]="song.number + ' - ' + song.title">
|
||||||
<div class="song">
|
<div class="song">
|
||||||
<div>
|
<div>
|
||||||
@@ -24,6 +25,11 @@
|
|||||||
|
|
||||||
<app-button-row>
|
<app-button-row>
|
||||||
<button color="primary" mat-flat-button routerLink="edit">Bearbeiten</button>
|
<button color="primary" mat-flat-button routerLink="edit">Bearbeiten</button>
|
||||||
|
<button mat-button routerLink="../">Schließen</button>
|
||||||
</app-button-row>
|
</app-button-row>
|
||||||
|
|
||||||
</app-card>
|
</app-card>
|
||||||
|
<app-card>
|
||||||
|
|
||||||
|
</app-card>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import {Component, OnInit} from '@angular/core';
|
|||||||
import {ActivatedRoute} from '@angular/router';
|
import {ActivatedRoute} from '@angular/router';
|
||||||
import {SongService} from '../services/song.service';
|
import {SongService} from '../services/song.service';
|
||||||
import {map, switchMap} from 'rxjs/operators';
|
import {map, switchMap} from 'rxjs/operators';
|
||||||
import {Song} from '../models/song';
|
import {Song} from '../services/song';
|
||||||
import {Observable} from 'rxjs';
|
import {Observable} from 'rxjs';
|
||||||
import {FileDataService} from '../services/file-data.service';
|
import {FileDataService} from '../services/file-data.service';
|
||||||
import {File} from '../services/file';
|
import {File} from '../services/file';
|
||||||
@@ -31,7 +31,7 @@ export class SongComponent implements OnInit {
|
|||||||
|
|
||||||
this.files$ = this.activatedRoute.params.pipe(
|
this.files$ = this.activatedRoute.params.pipe(
|
||||||
map(param => param.songId),
|
map(param => param.songId),
|
||||||
switchMap(songId => this.fileService.get$(songId))
|
switchMap(songId => this.fileService.read$(songId))
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/app/services/db.service.spec.ts
Normal file
12
src/app/services/db.service.spec.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import {TestBed} from '@angular/core/testing';
|
||||||
|
|
||||||
|
import {DbService} from './db.service';
|
||||||
|
|
||||||
|
describe('DbService', () => {
|
||||||
|
beforeEach(() => TestBed.configureTestingModule({}));
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const service: DbService = TestBed.get(DbService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
44
src/app/services/db.service.ts
Normal file
44
src/app/services/db.service.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument} from '@angular/fire/firestore';
|
||||||
|
import {Observable} from 'rxjs';
|
||||||
|
import {map} from 'rxjs/operators';
|
||||||
|
|
||||||
|
type CollectionPredicate<T> = string | AngularFirestoreCollection<T>;
|
||||||
|
type DocumentPredicate<T> = string | AngularFirestoreDocument<T>;
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class DbService {
|
||||||
|
|
||||||
|
constructor(private afs: AngularFirestore) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public col<T>(ref: CollectionPredicate<T>, queryFn?): AngularFirestoreCollection<T> {
|
||||||
|
return typeof ref === 'string' ? this.afs.collection<T>(ref, queryFn) : ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
public doc<T>(ref: DocumentPredicate<T>): AngularFirestoreDocument<T> {
|
||||||
|
return typeof ref === 'string' ? this.afs.doc<T>(ref) : ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
public doc$<T>(ref: DocumentPredicate<T>): Observable<T> {
|
||||||
|
return this.doc(ref).snapshotChanges().pipe(
|
||||||
|
map(doc => {
|
||||||
|
const data = doc.payload.data();
|
||||||
|
const id = doc.payload.id;
|
||||||
|
return {...data, id} as T;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public col$<T>(ref: CollectionPredicate<T>, queryFn?): Observable<T[]> {
|
||||||
|
return this.col(ref, queryFn).snapshotChanges().pipe(
|
||||||
|
map(doc => doc.map(_ => {
|
||||||
|
const data = _.payload.doc.data();
|
||||||
|
const id = _.payload.doc.id;
|
||||||
|
return {...data, id} as T;
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,19 +3,19 @@ import {AngularFireAuth} from '@angular/fire/auth';
|
|||||||
import {Observable} from 'rxjs';
|
import {Observable} from 'rxjs';
|
||||||
import {filter, switchMap} from 'rxjs/operators';
|
import {filter, switchMap} from 'rxjs/operators';
|
||||||
import {User} from './user';
|
import {User} from './user';
|
||||||
import {AngularFirestore} from '@angular/fire/firestore';
|
import {DbService} from './db.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class UserService {
|
export class UserService {
|
||||||
constructor(private afAuth: AngularFireAuth, private afs: AngularFirestore) {
|
constructor(private afAuth: AngularFireAuth, private db: DbService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public get user$(): Observable<User> {
|
public get user$(): Observable<User> {
|
||||||
return this.afAuth.authState.pipe(
|
return this.afAuth.authState.pipe(
|
||||||
filter(_ => !!_),
|
filter(_ => !!_),
|
||||||
switchMap(auth => this.afs.doc<User>('user/' + auth.uid).valueChanges())
|
switchMap(auth => this.db.doc$<User>('user/' + auth.uid))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export interface User {
|
export interface User {
|
||||||
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
role: 'admin';
|
role: 'admin';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<nav class="head">
|
<nav class="head">
|
||||||
<div class="links">
|
<div class="links">
|
||||||
<a href="#" routerLink="/songs" routerLinkActive="active">Lieder</a>
|
<a href="#" routerLink="/songs" routerLinkActive="active">Lieder</a>
|
||||||
|
<a href="#" routerLink="/show" routerLinkActive="active">Veranstaltungen</a>
|
||||||
<a href="#" routerLink="/user" routerLinkActive="active">Benutzer</a>
|
<a href="#" routerLink="/user" routerLinkActive="active">Benutzer</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ nav {
|
|||||||
right: 0;
|
right: 0;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
background: @navigation-background;
|
background: @navigation-background;
|
||||||
|
z-index: 1;
|
||||||
.card-3;
|
.card-3;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
.row {
|
.row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
flex-wrap: wrap;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,18 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #fffe;
|
background: #fffe;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 50vw;
|
width: 800px;
|
||||||
|
@media screen and (max-width: 860px) {
|
||||||
|
width: 100vw;
|
||||||
|
border-radius: 0px;
|
||||||
|
background: #fffa;
|
||||||
|
}
|
||||||
|
|
||||||
&.padding {
|
&.padding {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heading {
|
.heading {
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<div class="header">
|
||||||
|
<button mat-icon-button>
|
||||||
|
<fa-icon [icon]="faFilter"></fa-icon>
|
||||||
|
</button>
|
||||||
|
<button mat-icon-button routerLink="new">
|
||||||
|
<fa-icon [icon]="faNew"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
.header {
|
||||||
|
position: relative;
|
||||||
|
height: 34px;
|
||||||
|
margin: 20px 20px -20px 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
color: #A6C4F5;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||||
|
|
||||||
|
import {ListHeaderComponent} from './list-header.component';
|
||||||
|
|
||||||
|
describe('ListHeaderComponent', () => {
|
||||||
|
let component: ListHeaderComponent;
|
||||||
|
let fixture: ComponentFixture<ListHeaderComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ListHeaderComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ListHeaderComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
23
src/app/widget-modules/list-header/list-header.component.ts
Normal file
23
src/app/widget-modules/list-header/list-header.component.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {faFilter} from '@fortawesome/free-solid-svg-icons/faFilter';
|
||||||
|
import {faBars} from '@fortawesome/free-solid-svg-icons/faBars';
|
||||||
|
import {faPlus} from '@fortawesome/free-solid-svg-icons/faPlus';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-list-header',
|
||||||
|
templateUrl: './list-header.component.html',
|
||||||
|
styleUrls: ['./list-header.component.less']
|
||||||
|
})
|
||||||
|
export class ListHeaderComponent implements OnInit {
|
||||||
|
|
||||||
|
public faNew = faPlus;
|
||||||
|
public faFilter = faFilter;
|
||||||
|
public faMenu = faBars;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
21
src/app/widget-modules/list-header/list-header.module.ts
Normal file
21
src/app/widget-modules/list-header/list-header.module.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
import {CommonModule} from '@angular/common';
|
||||||
|
import {ListHeaderComponent} from './list-header.component';
|
||||||
|
import {FontAwesomeModule} from '@fortawesome/angular-fontawesome';
|
||||||
|
import {MatButtonModule} from '@angular/material/button';
|
||||||
|
import {RouterModule} from '@angular/router';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [ListHeaderComponent],
|
||||||
|
exports: [
|
||||||
|
ListHeaderComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
FontAwesomeModule,
|
||||||
|
MatButtonModule,
|
||||||
|
RouterModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class ListHeaderModule {
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
import {CommonModule} from '@angular/common';
|
||||||
|
import {ShowTypePipe} from './show-type.pipe';
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [ShowTypePipe],
|
||||||
|
exports: [
|
||||||
|
ShowTypePipe
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CommonModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class ShowTypeTranslaterModule {
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import {ShowTypePipe} from './show-type.pipe';
|
||||||
|
|
||||||
|
describe('ShowTypePipe', () => {
|
||||||
|
it('create an instance', () => {
|
||||||
|
const pipe = new ShowTypePipe();
|
||||||
|
expect(pipe).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import {Pipe, PipeTransform} from '@angular/core';
|
||||||
|
|
||||||
|
@Pipe({
|
||||||
|
name: 'showType'
|
||||||
|
})
|
||||||
|
export class ShowTypePipe implements PipeTransform {
|
||||||
|
|
||||||
|
transform(type: string): string {
|
||||||
|
switch (type) {
|
||||||
|
case 'worship':
|
||||||
|
return 'Gottesdienst Anbetung';
|
||||||
|
case 'praise':
|
||||||
|
return 'Gottesdienst Lobpreis';
|
||||||
|
case 'homegroup':
|
||||||
|
return 'Hauskreis';
|
||||||
|
case 'prayergroup':
|
||||||
|
return 'Gebetskreis';
|
||||||
|
}
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,3 +19,27 @@ body {
|
|||||||
background: linear-gradient(to top, #373b44, #4286f4); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
|
background: linear-gradient(to top, #373b44, #4286f4); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4 {
|
||||||
|
color: @navigation-link-color;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-form-field .mat-form-field-infix {
|
||||||
|
width: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.content > *:not(router-outlet) {
|
||||||
|
margin-top: 60px;
|
||||||
|
@media screen and (max-width: 860px) {
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user