Compare commits

...

3 Commits
master ... prod

Author SHA1 Message Date
Flo
fa2e7e4e1c prod: new devenv 2025-10-31 17:09:38 +01:00
Flo
93ab4635b3 tag sorting, tag thumbnail and tag strip in home 2024-08-07 19:42:44 +00:00
Flo
42ec2d22c8 analyze 2024-08-05 10:25:56 +00:00
21 changed files with 175 additions and 95 deletions

View File

@ -1,3 +0,0 @@
#!/bin/bash
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
$SCRIPT_DIR/exec build

View File

@ -1,3 +0,0 @@
#!/bin/bash
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
$SCRIPT_DIR/exec down

View File

@ -1,23 +0,0 @@
#!/bin/bash
COMMAND="$@"
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
#LOAD ENV VARIABLES FROM .ENV
#export $(grep -v '^#' "${SCRIPT_DIR}/../../.env" | xargs)
#MAC
if [[ "$OSTYPE" == "darwin"* ]]; then
docker compose -f "${SCRIPT_DIR}/../../docker/docker-compose-mac.yml" $COMMAND
#LINUX
elif [[ "$OSTYPE" == "linux-gnu" ]]; then
docker compose -f "${SCRIPT_DIR}/../../docker/docker-compose.yml" $COMMAND
else
echo "Dieses Skript wird auf deinem Gerät nicht unterstützt"
exit 1
fi
#UNSET ENV VARIABLES FROM .ENV
#unset $(grep -v '^#' "${SCRIPT_DIR}/../../.env" | sed -E 's/(.*)=.*/\1/' | xargs)

18
bin/script/firstRun Executable file
View File

@ -0,0 +1,18 @@
#!/bin/bash
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
PROJECT_DIR=$(realpath $SCRIPT_DIR/../../)
ENV_DIR=$(realpath $PROJECT_DIR/../../../)
source $ENV_DIR/bin/messages
source $ENV_DIR/bin/drun
# Install node Packages
infomsg "[frontend]: NPM install"
drun frontend npm install
successmsg "[frontend]: NPM install done"
# Initial build of website
infomsg "[frontend]: NPM run build"
drun frontend npm run build
successmsg "[frontend]: NPM run build done"

View File

@ -2,18 +2,13 @@
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
PROJECT_DIR=$(realpath $SCRIPT_DIR/../../) PROJECT_DIR=$(realpath $SCRIPT_DIR/../../)
ENV_DIR=$(realpath $PROJECT_DIR/../../) ENV_DIR=$(realpath $PROJECT_DIR/../../../)
# Build and start docker containers source $ENV_DIR/bin/messages
$SCRIPT_DIR/exec build
$SCRIPT_DIR/exec up -d
# Source drun # Check docker-compose.yml file
source $ENV_DIR/bin/script/drun if [ ! -f "$PROJECT_DIR/docker/docker-compose.yml" ] ; then
infomsg "[frontend] Creating docker-compose.yml"
# Install node Packages cp "$PROJECT_DIR/docker/docker-compose.yml.dist" "$PROJECT_DIR/docker/docker-compose.yml"
drun mytube-frontend npm install successmsg "[frontend] Created docker-compose.yml"
drun mytube-frontend npm install -g @angular/cli fi
# Initial build of website
drun mytube-frontend npm run build

View File

@ -1,3 +0,0 @@
#!/bin/bash
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
$SCRIPT_DIR/exec stop

View File

@ -1,3 +0,0 @@
#!/bin/bash
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
$SCRIPT_DIR/exec up -d

29
bin/script/update Executable file
View File

@ -0,0 +1,29 @@
#!/bin/bash
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
PROJECT_DIR=$(realpath $SCRIPT_DIR/../../)
ENV_DIR=$(realpath $PROJECT_DIR/../../../)
CWD=$(pwd)
source $ENV_DIR/bin/messages
source $ENV_DIR/bin/drun
# Pull branch in project directory
infomsg "[frontend]: Git pull"
cd "$PROJECT_DIR"
git pull
successmsg "[frontend]: Git pull done"
# Install node Packages
infomsg "[frontend]: NPM install"
drun frontend npm install
successmsg "[frontend]: NPM install done"
# Initial build of website
infomsg "[frontend]: NPM run build"
drun frontend npm run build
successmsg "[frontend]: NPM run build done"
# Switch back to current working directory
cd "$CWD"

View File

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

View File

@ -1,5 +1,3 @@
version: '3'
networks: networks:
mytube: mytube:
external: true external: true
@ -25,7 +23,9 @@ services:
build: build:
context: ./../ context: ./../
dockerfile: ./docker/nginx/dockerfile dockerfile: ./docker/nginx/dockerfile
ports: labels:
- 80:80 - "traefik.http.routers.frontend.rule=Host(`mytube.srv`) || Host(`192.168.152.60`)"
- "traefik.http.routers.frontend.entrypoints=websecure"
- "traefik.http.routers.frontend.tls.certresolver=le"
depends_on: depends_on:
- mytube-frontend-app - mytube-frontend-app

View File

@ -1,3 +1,7 @@
<div class="m-5 flex flex-nowrap overflow-x-auto gap-2">
<shared-tag-card *ngFor="let tag of tags" [tag]="tag" />
</div>
<shared-video-list <shared-video-list
(onReadList)="readList($event)" (onReadList)="readList($event)"
[total]="total" [total]="total"

View File

@ -1,4 +1,5 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { TagListEntry } from 'src/app/model/TagListEntry';
import { VideoListEntry } from 'src/app/model/VideoListEntry'; import { VideoListEntry } from 'src/app/model/VideoListEntry';
import { RequestService } from 'src/app/request.service'; import { RequestService } from 'src/app/request.service';
import { OnReadListModel } from 'src/app/shared/components/video-list/video-list.component'; import { OnReadListModel } from 'src/app/shared/components/video-list/video-list.component';
@ -11,8 +12,11 @@ import { OnReadListModel } from 'src/app/shared/components/video-list/video-list
export class HomeComponent { export class HomeComponent {
total: number = 0; total: number = 0;
videos: VideoListEntry[] = []; videos: VideoListEntry[] = [];
tags: TagListEntry[] = [];
constructor(public requestService: RequestService) {} constructor(public requestService: RequestService) {
this.readTagList();
}
readList(model: OnReadListModel): void { readList(model: OnReadListModel): void {
this.requestService.post( this.requestService.post(
@ -28,4 +32,10 @@ export class HomeComponent {
} }
); );
} }
readTagList(): void {
this.requestService.post('tag-list/read-list', {}, (response: any) => {
this.tags = response.items;
});
}
} }

View File

@ -28,6 +28,15 @@
/> />
</div> </div>
</div> </div>
<div id="thumbnail" class="basis-full">
<img
[src]="'/api/tag/thumbnail/' + tagId"
alt="Thumbnail"
class="m-auto h-80 w-full"
/>
</div>
<div id="tags" class="flex flex-row gap-2"> <div id="tags" class="flex flex-row gap-2">
<div class="basis-auto w-24">Alias:</div> <div class="basis-auto w-24">Alias:</div>
<div class="basis-full" *ngIf="tagDetails !== null"> <div class="basis-full" *ngIf="tagDetails !== null">

View File

@ -11,6 +11,15 @@
(change)="readList()" (change)="readList()"
[(ngModel)]="onlyTagless" [(ngModel)]="onlyTagless"
/> />
<div class="basis-auto">
<button (click)="analyze()">
<div
class="block px-3 py-1.5 rounded rounded-lg bg-zinc-700 hover:bg-zinc-900 font-bold text-black dark:text-white"
>
Analyze
</div>
</button>
</div>
</div> </div>
<shared-table [items]="videos" [columns]="videoListColumns" /> <shared-table [items]="videos" [columns]="videoListColumns" />

View File

@ -12,7 +12,7 @@ import { ColumnDefinition } from 'src/app/shared/components/table/table.componen
export class ListComponent { export class ListComponent {
query$ = new Subject<string>(); query$ = new Subject<string>();
query: string = ''; query: string = '';
onlyTagless: boolean = false; onlyTagless: boolean = true;
videos: VideoListEntry[] = []; videos: VideoListEntry[] = [];
total: number = 0; total: number = 0;
page: number = 1; page: number = 1;
@ -57,9 +57,18 @@ export class ListComponent {
this.readList(); this.readList();
} }
analyze(): void {
this.requestService.post('analyze/analyze-videos', {}, (response: any) => {
if (response.length > 0) {
alert(response.length + ' videos were updated');
this.readList();
}
});
}
readList(): void { readList(): void {
this.requestService.post( this.requestService.post(
'video-list/read-list', 'analyze/read-video-list',
{ {
query: this.query, query: this.query,
page: this.page, page: this.page,

View File

@ -0,0 +1,40 @@
<div
*ngIf="tag !== null"
id="card"
class="grow py-2 px-3 rounded-xl shadow-lg border border-gray-100 dark:bg-zinc-800 dark:border-zinc-900 text-black dark:text-white"
[routerLink]="['/tag', tag.id]"
>
<div id="header" class="mb-2">
<div class="flex flex-row">
<div class="my-auto text-xl font-medium truncate">
{{ tag.description }}
</div>
</div>
</div>
<div id="content" class="mb-2">
<img
[src]="'/api/tag/thumbnail/' + tag.id"
alt="Thumbnail"
class="max-w-none h-40 w-80 m-auto"
(click)="onClick()"
/>
</div>
<div id="footer">
<div class="flex flex-row">
<!--
<div class="basis-full h-8">
<span
*ngFor="let alias of tag.aliases"
class="text-sm font-medium me-2 px-2.5 py-0.5 rounded bg-zinc-700 hover:bg-zinc-900"
>{{ tag.description }}</span
>
</div>
-->
<div class="basis-auto text-slate-500 dark:text-slate-400">
{{ tag.videoCount }}
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,19 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { TagListEntry } from 'src/app/model/TagListEntry';
import { VideoListEntry } from 'src/app/model/VideoListEntry';
@Component({
selector: 'shared-tag-card',
templateUrl: './tag-card.component.html',
styleUrls: ['./tag-card.component.scss'],
})
export class TagCardComponent {
@Input() tag: TagListEntry | null = null;
@Output() clicked = new EventEmitter<TagListEntry>();
onClick(): void {
if (this.tag === null) return;
this.clicked.emit(this.tag);
}
}

View File

@ -1,7 +1,7 @@
<div <div
*ngIf="video !== null" *ngIf="video !== null"
id="card" id="card"
class="grow py-2 px-3 my-2 rounded-xl shadow-lg border border-gray-100 dark:bg-zinc-800 dark:border-zinc-900 text-black dark:text-white" class="grow py-2 px-3 rounded-xl shadow-lg border border-gray-100 dark:bg-zinc-800 dark:border-zinc-900 text-black dark:text-white"
> >
<div id="header" class="mb-2"> <div id="header" class="mb-2">
<div class="flex flex-row"> <div class="flex flex-row">

View File

@ -8,7 +8,7 @@
<div <div
id="card-container" id="card-container"
class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4 px-5" class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-3 px-5"
> >
<shared-video-card <shared-video-card
*ngFor="let video of videos; index as currentIndex" *ngFor="let video of videos; index as currentIndex"
@ -17,10 +17,11 @@
(clicked)="selectVideo(video)" (clicked)="selectVideo(video)"
/> />
</div> </div>
<shared-paginator <div class="px-5 py-2">
<shared-paginator
(pageChange)="onPageChanged($event)" (pageChange)="onPageChanged($event)"
[page]="page" [page]="page"
[perPage]="perPage" [perPage]="perPage"
[total]="total" [total]="total"
> />
</shared-paginator> </div>

View File

@ -32,6 +32,7 @@ import { MatTableModule } from '@angular/material/table';
import { MatChipsModule } from '@angular/material/chips'; import { MatChipsModule } from '@angular/material/chips';
import { VideoListComponent } from './components/video-list/video-list.component'; import { VideoListComponent } from './components/video-list/video-list.component';
import { VideoCardComponent } from './components/video-card/video-card.component'; import { VideoCardComponent } from './components/video-card/video-card.component';
import { TagCardComponent } from './components/tag-card/tag-card.component';
import { TagSelectorComponent } from './components/tag-selector/tag-selector.component'; import { TagSelectorComponent } from './components/tag-selector/tag-selector.component';
@NgModule({ @NgModule({
@ -45,6 +46,7 @@ import { TagSelectorComponent } from './components/tag-selector/tag-selector.com
TableComponent, TableComponent,
VideoListComponent, VideoListComponent,
VideoCardComponent, VideoCardComponent,
TagCardComponent,
TagSelectorComponent, TagSelectorComponent,
], ],
exports: [ exports: [
@ -58,6 +60,7 @@ import { TagSelectorComponent } from './components/tag-selector/tag-selector.com
VideoListComponent, VideoListComponent,
VideoCardComponent, VideoCardComponent,
TagSelectorComponent, TagSelectorComponent,
TagCardComponent,
MatSlideToggleModule, MatSlideToggleModule,
MatCardModule, MatCardModule,