Created initial menu structure
This commit is contained in:
parent
fbd602e18a
commit
30cc326168
|
@ -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>
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
},
|
||||
];
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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() {
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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() {
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue