first commit

This commit is contained in:
Flo 2024-02-14 21:09:30 +01:00
parent 76232e4856
commit 362a24a5c3
36 changed files with 37 additions and 791 deletions

View File

@ -1,4 +1,4 @@
# Homepage
# mytube
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 15.2.6.

View File

@ -3,7 +3,7 @@
"version": 1,
"newProjectRoot": "projects",
"projects": {
"homepage": {
"mytube": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
@ -36,7 +36,7 @@
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/homepage",
"outputPath": "dist/mytube",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": [
@ -84,10 +84,10 @@
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"browserTarget": "homepage:build:production"
"browserTarget": "mytube:build:production"
},
"development": {
"browserTarget": "homepage:build:development"
"browserTarget": "mytube:build:development"
}
},
"defaultConfiguration": "development"
@ -95,7 +95,7 @@
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "homepage:build"
"browserTarget": "mytube:build"
}
},
"test": {

View File

@ -12,8 +12,8 @@ $SCRIPT_DIR/exec up -d
source $ENV_DIR/bin/script/drun
# Install node Packages
drun homepage-frontend npm install
drun homepage-frontend npm install -g @angular/cli
drun mytube-frontend npm install
drun mytube-frontend npm install -g @angular/cli
# Initial build of website
drun homepage-frontend npm run build
drun mytube-frontend npm run build

View File

@ -1,31 +1,31 @@
version: '3'
networks:
homepage:
mytube:
external: true
services:
homepage-frontend-app:
image: homepage-frontend-app
mytube-frontend-app:
image: mytube-frontend-app
networks:
- homepage
- mytube
volumes:
- /Users/flo/dev/frontend/homepage/:/var/www/
- /Users/flo/dev/frontend/mytube/:/var/www/
build:
context: ./../
dockerfile: ./docker/npm/dockerfile
tty: true
homepage-frontend-nginx:
image: homepage-frontend-nginx
mytube-frontend-nginx:
image: mytube-frontend-nginx
networks:
- homepage
- mytube
volumes:
- /Users/flo/dev/frontend/homepage/:/var/www/html:z
- /Users/flo/dev/frontend/mytube/:/var/www/html:z
build:
context: ./../
dockerfile: ./docker/nginx/dockerfile
ports:
- 80:80
depends_on:
- homepage-frontend-app
- mytube-frontend-app

View File

@ -1,14 +1,14 @@
version: '3'
networks:
homepage:
mytube:
external: true
services:
homepage-frontend-app:
image: homepage-frontend-app
mytube-frontend-app:
image: mytube-frontend-app
networks:
- homepage
- mytube
volumes:
- ./../:/var/www/
build:
@ -16,10 +16,10 @@ services:
dockerfile: ./docker/npm/dockerfile
tty: true
homepage-frontend-nginx:
image: homepage-frontend-nginx
mytube-frontend-nginx:
image: mytube-frontend-nginx
networks:
- homepage
- mytube
volumes:
- ./../:/var/www/html:z
build:
@ -28,4 +28,4 @@ services:
ports:
- 80:80
depends_on:
- homepage-frontend-app
- mytube-frontend-app

View File

@ -1,12 +1,12 @@
upstream host-backend-nginx {
server homepage-backend-nginx:80;
server mytube-backend-nginx:80;
}
server{
listen 80 default_server;
root /var/www/html/dist/homepage;
root /var/www/html/dist/mytube;
index index.html;
location / {

4
package-lock.json generated
View File

@ -1,11 +1,11 @@
{
"name": "homepage",
"name": "mytube",
"version": "0.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "homepage",
"name": "mytube",
"version": "0.0.0",
"dependencies": {
"@angular/animations": "^15.2.0",

View File

@ -1,5 +1,5 @@
{
"name": "homepage",
"name": "mytube",
"version": "0.0.0",
"scripts": {
"ng": "ng",

View File

@ -1,20 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LoginComponent } from './auth/login/login.component';
import { HomeComponent } from './home/home.component';
import { RegistrationComponent } from './auth/registration/registration.component';
import { RegistrationConfirmationComponent } from './auth/registration-confirmation/registration-confirmation.component';
const routes: Routes = [
{ path: 'auth', component: LoginComponent },
{ path: 'auth/registration', component: RegistrationComponent },
{ path: 'auth/registration/:id', component: RegistrationConfirmationComponent },
{ path: 'home', component: HomeComponent },
{ path: '', redirectTo: '/auth', pathMatch: 'full' },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

View File

@ -1 +1,3 @@
<router-outlet></router-outlet>
<video style="height: 100%; width: 100%;" controls autoplay>
<source src="http://wsl-flo/api/video/stream" type="video/mp4" id="video_player" >
</video>

View File

@ -21,35 +21,16 @@ import { MatDividerModule } from '@angular/material/divider';
import {MatDialogModule} from '@angular/material/dialog';
import {MatSnackBarModule} from '@angular/material/snack-bar';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ProductListComponent } from './product/product-list/product-list.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HomeComponent } from './home/home.component';
import { ProductDetailsComponent } from './product/product-details/product-details.component';
import { LoginComponent } from './auth/login/login.component';
import { CreateProductComponent } from './product/create-product/create-product.component';
import { RegistrationComponent } from './auth/registration/registration.component';
import { RegistrationConfirmationComponent } from './auth/registration-confirmation/registration-confirmation.component';
import { ProductComponent } from './product/product/product.component';
@NgModule({
declarations: [
AppComponent,
ProductListComponent,
ProductDetailsComponent,
LoginComponent,
HomeComponent,
CreateProductComponent,
RegistrationComponent,
RegistrationConfirmationComponent,
ProductComponent,
],
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
BrowserAnimationsModule,
MatSlideToggleModule,
MatCardModule,
MatButtonModule,

View File

@ -1,41 +0,0 @@
<mat-card>
<mat-card-header>
<mat-card-title>Login</mat-card-title>
<mat-card-subtitle>Bitte melde Dich an</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div class="container">
<div class="row">
<mat-form-field>
<mat-label>Identifier</mat-label>
<input matInput [(ngModel)]="identifier">
</mat-form-field>
</div>
<div class="row">
<mat-form-field>
<mat-label>Password</mat-label>
<input matInput type="password" [(ngModel)]="password">
</mat-form-field>
</div>
<div class="row">
<div class="col-md">
<button mat-fab
extended
color="disabled"
(click)="register()">
Registrieren
</button>
</div>
<div class="col-md">
<button mat-fab
extended
color="primary"
(click)="login()">
Login
</button>
</div>
</div>
</div>
</mat-card-content>
</mat-card>

View File

@ -1,23 +0,0 @@
mat-card {
margin-left: auto;
margin-right: auto;
}
button {
width: 100%;
}
/* For tablet: */
@media only screen and (min-width: 600px) {
mat-card {
width: 70%;
}
}
/* For desktop: */
@media only screen and (min-width: 768px) {
mat-card {
width: 40%;
}
}

View File

@ -1,60 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { RequestService } from '../../request.service';
import { Router } from "@angular/router"
import { AppService } from '../../app.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
identifier: string|null = null;
password: string|null = null;
constructor(
public appService : AppService,
public requestService : RequestService,
private router: Router
) {
}
ngOnInit(): void {
this.stateRequest();
}
login() {
this.requestService.post(
'auth/login-user',
{
identifier: this.identifier,
password: this.password
},
(response:any) => {
if(response.hasOwnProperty('sessionId')) {
this.router.navigate(['/home']);
}
}
);
}
register() {
console.log('goto registration');
this.router.navigate(['/auth/registration']);
}
private stateRequest() {
this.requestService.get(
'user/state',
{},
(response:any) => {
if (response.hasOwnProperty('sessionId')) {
this.appService.setUsername(response.username);
this.router.navigate(['/home']);
}
}
);
}
}

View File

@ -1,33 +0,0 @@
<mat-card>
<mat-card-header>
<mat-card-title>Registrierung bestätigen</mat-card-title>
<mat-card-subtitle>Bitte gib dein Passwort ein</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div class="container">
<div class="row">
<mat-form-field>
<mat-label>Passwort</mat-label>
<input matInput type="password" [(ngModel)]="password">
</mat-form-field>
</div>
<div class="row">
<mat-form-field>
<mat-label>Passwort wiederholen</mat-label>
<input matInput type="password" [(ngModel)]="passwordConfirmation">
</mat-form-field>
</div>
<div class="row">
<div class="col-md">
<button mat-fab
extended
color="primary"
(click)="confirm()">
Bestätigen
</button>
</div>
</div>
</div>
</mat-card-content>
</mat-card>

View File

@ -1,23 +0,0 @@
mat-card {
margin-left: auto;
margin-right: auto;
}
button {
width: 100%;
}
/* For tablet: */
@media only screen and (min-width: 600px) {
mat-card {
width: 70%;
}
}
/* For desktop: */
@media only screen and (min-width: 768px) {
mat-card {
width: 40%;
}
}

View File

@ -1,40 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { RequestService } from '../../request.service';
@Component({
selector: 'app-registration-confirmation',
templateUrl: './registration-confirmation.component.html',
styleUrls: ['./registration-confirmation.component.scss']
})
export class RegistrationConfirmationComponent implements OnInit {
public id: string;
public password: string|null = null;
public passwordConfirmation: string|null = null;
constructor(
private route: ActivatedRoute,
public requestService : RequestService,
private router: Router
) {
this.id = '';
}
ngOnInit() {
this.id = this.route.snapshot.paramMap.get('id') ?? '';
}
confirm() {
this.requestService.post(
'auth/confirm-registration',
{
id: this.id,
password: this.password,
passwordConfirmation: this.passwordConfirmation,
},
(response:any) => {
this.router.navigate(['/auth']);
}
)
}
}

View File

@ -1,33 +0,0 @@
<mat-card>
<mat-card-header>
<mat-card-title>Registrieren</mat-card-title>
<mat-card-subtitle>Bitte gib deine Benutzerdaten an:</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div class="container">
<div class="row">
<mat-form-field>
<mat-label>Benutzername</mat-label>
<input matInput [(ngModel)]="username">
</mat-form-field>
</div>
<div class="row">
<mat-form-field>
<mat-label>E-Mail</mat-label>
<input matInput [(ngModel)]="mail">
</mat-form-field>
</div>
<div class="row">
<div class="col-md">
<button mat-fab
extended
color="primary"
(click)="register()">
Registrieren
</button>
</div>
</div>
</div>
</mat-card-content>
</mat-card>

View File

@ -1,23 +0,0 @@
mat-card {
margin-left: auto;
margin-right: auto;
}
button {
width: 100%;
}
/* For tablet: */
@media only screen and (min-width: 600px) {
mat-card {
width: 70%;
}
}
/* For desktop: */
@media only screen and (min-width: 768px) {
mat-card {
width: 40%;
}
}

View File

@ -1,39 +0,0 @@
import { Component } from '@angular/core';
import { AppService } from '../../app.service';
import { RequestService } from '../../request.service';
import { Router } from '@angular/router';
@Component({
selector: 'app-registration',
templateUrl: './registration.component.html',
styleUrls: ['./registration.component.scss']
})
export class RegistrationComponent {
username: string|null = null;
mail: string|null = null;
constructor(
public appService : AppService,
public requestService : RequestService,
private router: Router
) {
}
ngOnInit(): void {
this.username = "";
this.mail = "";
}
register(): void {
this.requestService.post(
'auth/register-user',
{
username: this.username,
mail: this.mail
},
(response:any) => {
this.router.navigate(['/auth']);
}
);
}
}

View File

@ -1,26 +0,0 @@
<mat-toolbar color="primary">
<button mat-icon-button (click)="drawer.toggle(); list.onGetProductList()">
<mat-icon>menu</mat-icon>
</button>
<span>
{{title}}
</span>
<button mat-button [matMenuTriggerFor]="menu">{{username}}</button>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="logout()">Logout</button>
</mat-menu>
</mat-toolbar>
<mat-drawer-container class="content">
<mat-drawer #drawer class="example-sidenav" mode="over">
<app-product-list #list (productSelected)="selectProduct($event); drawer.toggle(); list.onGetProductList()">
</app-product-list>
</mat-drawer>
<div class="example-sidenav-content">
<app-product-details [product]="selectedProduct"></app-product-details>
</div>
</mat-drawer-container>

View File

@ -1,13 +0,0 @@
span {
margin-left: auto;
margin-right: auto;
}
.content {
height: 100%;
}
.example-sidenav-content {
margin: 1em;
height: 100%;
}

View File

@ -1,52 +0,0 @@
import { Component } from '@angular/core';
import { Product } from '../product/product-list/product-list.component';
import { RequestService } from '../request.service';
import { Router } from "@angular/router"
import { AppService } from '../app.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent {
title = 'Homepage';
username: string = "(null)";
selectedProduct: Product|null = null;
constructor(
public appService : AppService,
public requestService : RequestService,
private router: Router
) {
}
ngOnInit(): void {
this.requestService.get(
'user/state',
{},
(response:any) => {
if (response.status == 401) {
this.router.navigate(['/auth']);
} else {
this.username = response.username;
}
}
);
}
logout() {
this.requestService.post(
'auth/logout-user',
{},
(response:any) => {
this.router.navigate(['/auth']);
}
);
}
selectProduct(product: any) {
this.selectedProduct = product;
}
}

View File

@ -1,28 +0,0 @@
<mat-card>
<mat-card-header>
<mat-card-title>Neues Produkt</mat-card-title>
<mat-card-subtitle>Bitte gebe die Daten des neuen Produkts an</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div class="container">
<div class="row">
<mat-form-field>
<mat-label>Identifier</mat-label>
<input matInput [(ngModel)]="identifier">
</mat-form-field>
</div>
<div class="row">
<mat-form-field>
<mat-label>Name</mat-label>
<input matInput [(ngModel)]="name">
</mat-form-field>
</div>
</div>
</mat-card-content>
<mat-card-actions>
<button mat-button (click)="cancel()">Abbrechen</button>
<button mat-button [mat-dialog-close]="{identifier: identifier, name: name}" cdkFocusInitial>Ok</button>
</mat-card-actions>
</mat-card>

View File

@ -1,24 +0,0 @@
import { Component } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
@Component({
selector: 'app-create-product',
templateUrl: './create-product.component.html',
styleUrls: ['./create-product.component.scss']
})
export class CreateProductComponent {
name: string
identifier: string
constructor(
private dialogRef: MatDialogRef<CreateProductComponent>
) {
this.name = '';
this.identifier = '';
}
cancel(){
this.dialogRef.close();
}
}

View File

@ -1,56 +0,0 @@
<iframe *ngIf="url != null" [src]="url">
</iframe>
<mat-card *ngIf="product != null">
<mat-card-header>
<mat-card-title>{{product.name}}</mat-card-title>
<mat-card-subtitle>{{product.identifier}} - {{product.id}}</mat-card-subtitle>
</mat-card-header>
<mat-divider/>
<mat-card-content>
<div class="container">
<div class="row">
<mat-form-field>
<mat-label>Identifier</mat-label>
<input matInput [(ngModel)]="product.identifier">
</mat-form-field>
</div>
<div class="row">
<mat-form-field>
<mat-label>Name</mat-label>
<input matInput [(ngModel)]="product.name">
</mat-form-field>
</div>
<div class="row">
<mat-form-field>
<mat-label>Url</mat-label>
<input matInput [(ngModel)]="product.url">
</mat-form-field>
</div>
<div class="row">
<div class="col-md">
<mat-form-field appearance="outline">
<mat-label>Erstellt am</mat-label>
<input matInput [(ngModel)]="product.created" readonly>
</mat-form-field>
</div>
<div class="col-md">
<mat-form-field appearance="outline">
<mat-label>Zuletzt geändert am</mat-label>
<input matInput [(ngModel)]="product.updated" readonly>
</mat-form-field>
</div>
</div>
</div>
</mat-card-content>
<mat-card-actions align="end">
<button mat-fab color="primary"
(click)="updateProduct(product)">
<mat-icon>save</mat-icon>
</button>
</mat-card-actions>
</mat-card>

View File

@ -1,36 +0,0 @@
app-login {
margin: auto;
}
mat-form-field {
width: 100%;
}
mat-divider {
margin-top: 0.5em;
margin-bottom: 1em;
}
mat-card {
margin-right: auto;
margin-left: auto;
}
iframe {
width: 100%;
height: 100%;
}
/* For tablet: */
@media only screen and (min-width: 600px) {
mat-card {
max-width: 85%;
}
}
/* For desktop: */
@media only screen and (min-width: 768px) {
mat-card {
max-width: 85%;
}
}

View File

@ -1,40 +0,0 @@
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
import { RequestService } from '../../request.service';
import { Product } from '../product-list/product-list.component';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
@Component({
selector: 'app-product-details',
templateUrl: './product-details.component.html',
styleUrls: ['./product-details.component.scss']
})
export class ProductDetailsComponent implements OnChanges {
@Input() product: Product|null = null
url: SafeResourceUrl|null = null;
constructor(
public requestService : RequestService,
private domSanitizer: DomSanitizer
) {
}
ngOnChanges(changes: SimpleChanges) {
if (this.product != null && this.product.url != null) {
this.url = this.domSanitizer.bypassSecurityTrustResourceUrl(this.product.url);
}
else {
this.url = null;
}
}
updateProduct(product: Product) {
this.requestService.post(
'product/update-product',
product,
(response:any) => {
this.product = response
}
);
}
}

View File

@ -1,17 +0,0 @@
<mat-list>
<mat-list-item class="listItem" *ngFor="let product of products" (click)="selectProduct(product)">
<mat-icon matListItemIcon (click)="removeProduct(product)"> delete</mat-icon>
<span matListItemTitle>{{product.name}}</span>
<span matListItemLine>{{product.identifier}}</span>
</mat-list-item>
</mat-list>
<mat-divider></mat-divider>
<button mat-fab
extended
color="primary"
(click)="createProduct()">
<mat-icon>add</mat-icon>
Add
</button>

View File

@ -1,18 +0,0 @@
mat-divider {
margin-top: 0.5em;
margin-bottom: 1em;
}
.listItem {
margin-right: 1em;
}
.listItem:hover {
background-color: lightgray;
}
button {
margin-left: 1em;
margin-right: 1em;
width: 90%;
}

View File

@ -1,82 +0,0 @@
import { Component, EventEmitter, Output } from '@angular/core';
import { RequestService } from '../../request.service';
import {MatDialog, MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
import { CreateProductComponent } from '../create-product/create-product.component';
export interface Product {
id: string,
identifier: string,
name: string|null,
url: string|null,
created: string,
updated: string
}
@Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.scss']
})
export class ProductListComponent {
@Output() productSelected = new EventEmitter<Product|null>();
products: Product[] = []
constructor(
public requestService : RequestService,
public dialog: MatDialog
) {
}
onGetProductList(): void {
this.requestService.get(
'product/product-list',
{},
(answer:any) => this.products = answer
);
}
selectProduct(product: Product|null) {
this.productSelected.emit(product);
}
createProduct() {
const createProductDialogRef = this.dialog.open(
CreateProductComponent
)
createProductDialogRef.afterClosed().subscribe(
result => {
if(result != undefined) {
this.requestService.post(
'product/create-product',
{
identifier: result.identifier,
name: result.name
},
(answer:any) => {
this.onGetProductList();
this.selectProduct(answer);
}
);
}
}
)
return;
}
removeProduct(product: Product) {
this.selectProduct(null);
this.requestService.post(
'product/delete-product',
{
id: product.id
},
(answer:any) => {
this.selectProduct(null);
this.onGetProductList();
}
);
}
}

View File

@ -1,10 +0,0 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.scss']
})
export class ProductComponent {
}

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>Homepage</title>
<title>mytube</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">