Created initial menu structure

This commit is contained in:
Jim Martens 2023-11-12 15:40:46 +01:00
parent fbd602e18a
commit 30cc326168
14 changed files with 261 additions and 67 deletions

6
.run/Debug.run.xml Normal file
View File

@ -0,0 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Debug" type="JavascriptDebugType" uri="http://localhost:4200"
useFirstLineBreakpoints="true">
<method v="2"/>
</configuration>
</component>

View File

@ -1,8 +1,9 @@
{
"name": "tsw-timetable-frontend",
"version": "0.0.1",
"author": "Ionic Framework",
"homepage": "https://ionicframework.com/",
"author": "Jim Martens",
"homepage": "https://2martens.de/",
"description": "Frontend for timetable application",
"scripts": {
"ng": "ng",
"start": "ng serve",
@ -76,6 +77,5 @@
"ts-node": "^8.3.0",
"typescript": "~5.0.2",
"webpack-bundle-analyzer": "^4.9.0"
},
"description": "An Ionic project"
}
}

View File

@ -1,26 +1,36 @@
<ion-app>
<ion-split-pane contentId="main-content">
<ion-split-pane when="md" contentId="main-content">
<ion-menu contentId="main-content" type="overlay">
<ion-content>
<ion-list id="inbox-list">
<ion-list-header>Inbox</ion-list-header>
<ion-note>hi@ionicframework.com</ion-note>
<ion-list id="menu-list">
<ion-list-header i18n>Timetable</ion-list-header>
<ion-note *ngIf="isLoggedIn$ | async">{{ username$ | async }}</ion-note>
<ion-menu-toggle auto-hide="false" *ngFor="let p of appPages; let i = index">
<ion-item routerDirection="root" [routerLink]="[p.url]" lines="none" detail="false"
routerLinkActive="selected">
<ng-container *ngIf="isLoggedIn$ | async; else loggedOut">
<ion-item *ngFor="let p of accountPages; let i = index"
[routerDirection]="'root'" [routerLink]="[p.url]" [routerLinkActiveOptions]="{exact: true}"
lines="none" [detail]="false"
[routerLinkActive]="'selected'" [ariaCurrentWhenActive]="'page'" [button]="true">
<ion-icon aria-hidden="true" [slot]="'start'" [ios]="p.icon + '-outline'"
[md]="p.icon + '-sharp'"></ion-icon>
<ion-label>{{ p.title }}</ion-label>
</ion-item>
</ng-container>
<ion-item-divider></ion-item-divider>
<ng-template #loggedOut>
<ion-item *ngFor="let p of loggedOutPages; let i = index"
routerDirection="root" [routerLink]="[p.url]" lines="none" detail="false"
routerLinkActive="selected" [routerLinkActiveOptions]="{exact: true}" [button]="true">
<ion-icon aria-hidden="true" slot="start" [ios]="p.icon + '-outline'" [md]="p.icon + '-sharp'"></ion-icon>
<ion-label>{{ p.title }}</ion-label>
</ion-item>
</ion-menu-toggle>
</ion-list>
</ng-template>
<ion-list id="labels-list" *ngIf="labels.length > 0">
<ion-list-header>Labels</ion-list-header>
<ion-item *ngFor="let label of labels" lines="none">
<ion-icon aria-hidden="true" slot="start" ios="bookmark-outline" md="bookmark-sharp"></ion-icon>
<ion-label>{{ label }}</ion-label>
<ion-item *ngFor="let p of appPages; let i = index"
routerDirection="root" [routerLink]="[p.url]" lines="none" detail="false"
routerLinkActive="selected" [routerLinkActiveOptions]="{exact: true}" [button]="true">
<ion-icon aria-hidden="true" slot="start" [ios]="p.icon + '-outline'" [md]="p.icon + '-sharp'"></ion-icon>
<ion-label>{{ p.title }}</ion-label>
</ion-item>
</ion-list>
</ion-content>

View File

@ -1,11 +1,13 @@
import {CommonModule} from '@angular/common';
import {AsyncPipe, NgFor, NgIf} from '@angular/common';
import {Component} from '@angular/core';
import {RouterLink, RouterLinkActive} from '@angular/router';
import {
IonApp,
IonContent,
IonHeader,
IonIcon,
IonItem,
IonItemDivider,
IonLabel,
IonList,
IonListHeader,
@ -13,61 +15,74 @@ import {
IonMenuToggle,
IonNote,
IonRouterOutlet,
IonSplitPane
IonSplitPane,
IonTitle,
IonToolbar
} from '@ionic/angular/standalone';
import {addIcons} from 'ionicons';
import {
archiveOutline,
archiveSharp,
bookmarkOutline,
bookmarkSharp,
heartOutline,
heartSharp,
mailOutline,
mailSharp,
paperPlaneOutline,
paperPlaneSharp,
trashOutline,
trashSharp,
warningOutline,
warningSharp
homeOutline,
homeSharp,
logInOutline,
logInSharp,
logOutOutline,
logOutSharp,
readerOutline,
readerSharp,
shieldOutline,
shieldSharp
} from 'ionicons/icons';
import {KeycloakService} from "keycloak-angular";
import {from, Observable, of, switchMap} from "rxjs";
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.scss'],
standalone: true,
imports: [RouterLink, RouterLinkActive, CommonModule, IonApp, IonSplitPane, IonMenu, IonContent, IonList,
IonListHeader, IonNote, IonMenuToggle, IonItem, IonIcon, IonLabel, IonRouterOutlet],
imports: [RouterLink, RouterLinkActive, IonApp, IonSplitPane, IonMenu, IonContent, IonList,
IonListHeader, IonNote, IonMenuToggle, IonItem, IonIcon, IonLabel, IonRouterOutlet, NgIf, NgFor, AsyncPipe, IonItemDivider, IonHeader, IonToolbar, IonTitle],
})
export class AppComponent {
public appPages = [
{title: 'Inbox', url: '/folder/inbox', icon: 'mail'},
{title: 'Outbox', url: '/folder/outbox', icon: 'paper-plane'},
{title: 'Favorites', url: '/folder/favorites', icon: 'heart'},
{title: 'Archived', url: '/folder/archived', icon: 'archive'},
{title: 'Trash', url: '/folder/trash', icon: 'trash'},
{title: 'Spam', url: '/folder/spam', icon: 'warning'},
{title: $localize`Dashboard`, url: '', icon: 'home'},
{title: $localize`Privacy Policy`, url: '/privacy-policy', icon: 'shield'},
{title: $localize`Legal Notice`, url: '/legal-notice', icon: 'reader'},
];
public labels = [];
public accountPages = [
{title: $localize`Logout`, url: '/logout', icon: 'log-out'},
];
public loggedOutPages = [
{title: $localize`Logout`, url: '/login', icon: 'log-in'},
]
public isLoggedIn$: Observable<boolean>;
public username$: Observable<string>;
constructor() {
constructor(
private keycloakService: KeycloakService
) {
this.isLoggedIn$ = from(this.keycloakService.isLoggedIn());
this.username$ = this.isLoggedIn$.pipe(
switchMap(loggedIn => {
if (loggedIn) {
return of(this.keycloakService.getUsername());
} else {
return of('');
}
})
)
addIcons({
mailOutline,
mailSharp,
paperPlaneOutline,
paperPlaneSharp,
heartOutline,
heartSharp,
archiveOutline,
archiveSharp,
trashOutline,
trashSharp,
warningOutline,
warningSharp,
bookmarkOutline,
bookmarkSharp
homeOutline,
homeSharp,
logInOutline,
logInSharp,
logOutOutline,
logOutSharp,
shieldOutline,
shieldSharp,
readerOutline,
readerSharp,
});
}
}

View File

@ -1,15 +1,11 @@
import {Routes} from '@angular/router';
import {AppAuthGuard} from "./auth/auth.guard";
export const ROOT_ROUTES: Routes = [
{
path: '',
loadComponent: () => import("./dashboard/dashboard.component").then(mod => mod.DashboardComponent),
pathMatch: 'full',
},
{
path: 'permission-denied',
loadComponent: () => import("./permission-denied/permission-denied.component")
.then(mod => mod.PermissionDeniedComponent)
.then(mod => mod.PermissionDeniedComponent),
},
{
path: 'legal-notice',
@ -19,4 +15,18 @@ export const ROOT_ROUTES: Routes = [
path: 'privacy-policy',
loadComponent: () => import("./privacy-policy/privacy-policy.component").then(mod => mod.PrivacyPolicyComponent)
},
{
path: 'login',
loadComponent: () => import("./login/login.component").then(mod => mod.LoginComponent)
},
{
path: 'logout',
loadComponent: () => import("./logout/logout.component").then(mod => mod.LogoutComponent),
canActivate: [AppAuthGuard]
},
{
path: '',
loadComponent: () => import("./dashboard/dashboard.component").then(mod => mod.DashboardComponent),
pathMatch: 'full',
},
];

View File

@ -1,5 +1,13 @@
import {Component} from '@angular/core';
import {IonButtons, IonContent, IonHeader, IonMenuButton, IonTitle, IonToolbar} from "@ionic/angular/standalone";
import {
IonButtons,
IonContent,
IonHeader,
IonMenuButton,
IonMenuToggle,
IonTitle,
IonToolbar
} from "@ionic/angular/standalone";
@Component({
selector: 'app-dashboard',
@ -12,7 +20,8 @@ import {IonButtons, IonContent, IonHeader, IonMenuButton, IonTitle, IonToolbar}
IonMenuButton,
IonTitle,
IonToolbar,
IonContent
IonContent,
IonMenuToggle
]
})
export class DashboardComponent {

View File

@ -0,0 +1,22 @@
<ion-header [translucent]="true">
<ion-toolbar>
<ion-buttons slot="start">
<ion-menu-button></ion-menu-button>
</ion-buttons>
<ion-title i18n="page title">Timetable</ion-title>
</ion-toolbar>
</ion-header>
<ion-content [fullscreen]="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large" i18n="page title">Timetable</ion-title>
</ion-toolbar>
</ion-header>
<div id="container">
<p i18n="welcome text|A welcome to users">
TODO
</p>
</div>
</ion-content>

View File

View File

@ -0,0 +1,24 @@
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {IonicModule} from '@ionic/angular';
import {LoginComponent} from './login.component';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [LoginComponent],
imports: [IonicModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,26 @@
import {Component, OnInit} from '@angular/core';
import {IonButtons, IonContent, IonHeader, IonMenuButton, IonTitle, IonToolbar} from "@ionic/angular/standalone";
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss'],
imports: [
IonButtons,
IonContent,
IonHeader,
IonMenuButton,
IonTitle,
IonToolbar
],
standalone: true
})
export class LoginComponent implements OnInit {
constructor() {
}
ngOnInit() {
}
}

View File

@ -0,0 +1,22 @@
<ion-header [translucent]="true">
<ion-toolbar>
<ion-buttons slot="start">
<ion-menu-button></ion-menu-button>
</ion-buttons>
<ion-title i18n="page title">Timetable</ion-title>
</ion-toolbar>
</ion-header>
<ion-content [fullscreen]="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large" i18n="page title">Timetable</ion-title>
</ion-toolbar>
</ion-header>
<div id="container">
<p i18n="welcome text|A welcome to users">
TODO
</p>
</div>
</ion-content>

View File

View File

@ -0,0 +1,24 @@
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {IonicModule} from '@ionic/angular';
import {LogoutComponent} from './logout.component';
describe('LogoutComponent', () => {
let component: LogoutComponent;
let fixture: ComponentFixture<LogoutComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [LogoutComponent],
imports: [IonicModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(LogoutComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,26 @@
import {Component, OnInit} from '@angular/core';
import {IonButtons, IonContent, IonHeader, IonMenuButton, IonTitle, IonToolbar} from "@ionic/angular/standalone";
@Component({
selector: 'app-logout',
templateUrl: './logout.component.html',
styleUrls: ['./logout.component.scss'],
imports: [
IonButtons,
IonContent,
IonHeader,
IonMenuButton,
IonTitle,
IonToolbar
],
standalone: true
})
export class LogoutComponent implements OnInit {
constructor() {
}
ngOnInit() {
}
}