Skip to content

Commit

Permalink
Admin initial setup: add filtering + some icons (#1156)
Browse files Browse the repository at this point in the history
* add icons + initial work for org switching #1127

* add stubs for more parts #1127

* add filter for lazy load expired events #1127
  • Loading branch information
syjer committed Dec 13, 2022
1 parent 43f1069 commit e8f4fbf
Show file tree
Hide file tree
Showing 24 changed files with 196 additions and 69 deletions.
2 changes: 1 addition & 1 deletion frontend-admin/src/app/app-routing.module.ts
Expand Up @@ -4,7 +4,7 @@ import { MissingOrgComponent } from './missing-org/missing-org.component';

const routes: Routes = [
{
path: 'organization/:id',
path: 'organization/:organizationId',
loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule)
},
{
Expand Down
3 changes: 2 additions & 1 deletion frontend-admin/src/app/app.component.html
@@ -1,8 +1,9 @@
<!--based on https://getbootstrap.com/docs/5.2/examples/dashboard/ -->
<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
<span class="navbar-brand col-md-3 col-lg-2 me-0 px-3 fs-6">
<img src="assets/alfio-logo.svg" height="48">
</span>
<span style="color: white;">org id {{organizationId$ | async}}</span>
<!-- <input class="form-control form-control-dark w-100 rounded-0 border-0" type="text" placeholder="Search"
aria-label="Search">
<div class="navbar-nav">
Expand Down
35 changes: 0 additions & 35 deletions frontend-admin/src/app/app.component.spec.ts

This file was deleted.

18 changes: 17 additions & 1 deletion frontend-admin/src/app/app.component.ts
@@ -1,5 +1,9 @@
import { Component, OnInit } from '@angular/core';
import { ActivationEnd, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { filter, map, Observable, tap } from 'rxjs';
import { Organization } from './model/organization';
import { OrganizationService } from './shared/organization.service';

@Component({
selector: 'app-root',
Expand All @@ -8,11 +12,23 @@ import { TranslateService } from '@ngx-translate/core';
})
export class AppComponent implements OnInit {

constructor(private readonly translateService: TranslateService) {
public organizations$?: Observable<Organization[]>;
public organizationId$?: Observable<string | null>;

constructor(
private readonly translateService: TranslateService,
private readonly organizationService: OrganizationService,
private readonly router: Router,
) {
}

ngOnInit(): void {
this.translateService.setDefaultLang('en');
this.translateService.use('en');
this.organizations$ = this.organizationService.getOrganizations();
this.organizationId$ = this.router.events.pipe(filter(a => a instanceof ActivationEnd), map(a => {
const ae = a as ActivationEnd;
return ae.snapshot.paramMap.get('organizationId');
}));
}
}
8 changes: 4 additions & 4 deletions frontend-admin/src/app/app.module.ts
@@ -1,6 +1,6 @@
import {APP_INITIALIZER, NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {provideSvgIcons} from '@ngneat/svg-icon';
import {provideSvgIconsConfig} from '@ngneat/svg-icon';
import {AppRoutingModule} from './app-routing.module';
import {AppComponent} from './app.component';
import {AuthenticationModule} from "./authentication/authentication.module";
Expand All @@ -12,7 +12,7 @@ import {firstValueFrom} from "rxjs";
import { SvgIconComponent } from '@ngneat/svg-icon';
import {OrganizationService} from './shared/organization.service';
import {MissingOrgComponent} from './missing-org/missing-org.component';
import { ICONS } from './shared/icons';
import { ICON_CONFIG } from './shared/icons';
import {TranslateLoader, TranslateModule} from '@ngx-translate/core';
import {CustomLoader} from './shared/i18n.service';

Expand All @@ -34,7 +34,7 @@ export function HttpLoaderFactory(http: HttpClient) {
@NgModule({
declarations: [
AppComponent,
MissingOrgComponent
MissingOrgComponent,
],
imports: [
BrowserModule,
Expand All @@ -58,7 +58,7 @@ export function HttpLoaderFactory(http: HttpClient) {
{ provide: APP_INITIALIZER, useFactory: RedirectToLoginIfNeeded, deps: [UserService, Router], multi: true},
{ provide: HTTP_INTERCEPTORS, useClass: AuthTokenInterceptor, multi: true },
{ provide: HttpXsrfTokenExtractor, useClass: DOMXsrfTokenExtractor },
provideSvgIcons(ICONS),
provideSvgIconsConfig(ICON_CONFIG),
DOMGidExtractor,
DOMXsrfTokenExtractor,
UserService,
Expand Down
@@ -1,12 +1,12 @@
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" [routerLink]="['./']">My events</a>
<a class="nav-link" [routerLink]="['./']"><svg-icon key="home"></svg-icon> My events</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['./subscriptions']">Subscriptions</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['./organization-info']">My organization</a>
<a class="nav-link" [routerLink]="['./organization-info']"><svg-icon key="organization"></svg-icon> My organization</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['./access-control']">Access Control</a>
Expand All @@ -15,6 +15,6 @@
<a class="nav-link" [routerLink]="['./groups']">Groups</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['./configuration']">Configuration</a>
<a class="nav-link" [routerLink]="['./configuration']"><svg-icon key="settings"></svg-icon> Configuration</a>
</li>
</ul>
32 changes: 18 additions & 14 deletions frontend-admin/src/app/dashboard/dashboard.component.html
@@ -1,15 +1,19 @@
<h1 translate="admin.dashboard.my-events"></h1>
<svg-icon key="check"></svg-icon>
<h2>Active</h2>
<ul>
<li *ngFor="let ev of activeEvents$ | async">
{{ev.displayName}} {{ev.formattedBegin}} {{ev.formattedEnd}}
</li>
</ul>

<h2>Expired</h2>
<ul>
<li *ngFor="let ev of expiredEvents$ | async">
{{ev.displayName}} {{ev.formattedBegin}} {{ev.formattedEnd}}
</li>
</ul>
<app-filter-button text="Active" [checked]="activeFilter" (toggleFilter)="toggleActiveFilter($event)"></app-filter-button>
<app-filter-button text="Inactive" [checked]="inactiveFilter" (toggleFilter)="toggleInactiveFilter($event)"></app-filter-button>
<ng-container *ngIf="activeFilter">
<h2>Active</h2>
<ul>
<li *ngFor="let ev of activeEvents$ | async">
{{ev.displayName}} {{ev.formattedBegin}} {{ev.formattedEnd}}
</li>
</ul>
</ng-container>
<ng-container *ngIf="inactiveFilter">
<h2>Expired</h2>
<ul>
<li *ngFor="let ev of expiredEvents$ | async">
{{ev.displayName}} {{ev.formattedBegin}} {{ev.formattedEnd}}
</li>
</ul>
</ng-container>
27 changes: 23 additions & 4 deletions frontend-admin/src/app/dashboard/dashboard.component.ts
Expand Up @@ -12,13 +12,32 @@ export class DashboardComponent implements OnInit {
public readonly organizationId: string;
public activeEvents$: Observable<EventInfo[]> = of();
public expiredEvents$: Observable<EventInfo[]> = of();
public activeFilter: boolean = true;
public inactiveFilter: boolean = false;

constructor(route: ActivatedRoute, private readonly eventService: EventService) {
this.organizationId = route.snapshot.paramMap.get('id') as string;
this.organizationId = route.snapshot.paramMap.get('organizationId') as string;
}

ngOnInit(): void {
this.activeEvents$ = this.eventService.getActiveEvents(this.organizationId);
this.expiredEvents$ = this.eventService.getExpiredEvents(this.organizationId);
public ngOnInit(): void {
this.activeEvents$ = this.eventService.getActiveEvents(this.organizationId); // default
}

public toggleActiveFilter(toggle: boolean): void {
this.activeFilter = toggle;
if (toggle) {
this.activeEvents$ = this.eventService.getActiveEvents(this.organizationId);
} else {
this.activeEvents$ = of();
}
}

public toggleInactiveFilter(toggle: boolean): void {
this.inactiveFilter = toggle;
if (toggle) {
this.expiredEvents$ = this.eventService.getExpiredEvents(this.organizationId);
} else {
this.expiredEvents$ = of();
}
}
}
21 changes: 16 additions & 5 deletions frontend-admin/src/app/dashboard/dashboard.module.ts
Expand Up @@ -7,9 +7,13 @@ import {OrganizationService} from "../shared/organization.service";
import {CommonModule} from "@angular/common";
import {EventService} from "../shared/event.service";
import {OrganizationConfigurationComponent} from './organization-configuration/organization-configuration.component';
import {provideSvgIcons, SvgIconComponent} from '@ngneat/svg-icon';
import { TranslateModule } from '@ngx-translate/core'
import { ICONS } from "../shared/icons";
import {provideSvgIconsConfig, SvgIconComponent} from '@ngneat/svg-icon';
import {TranslateModule} from '@ngx-translate/core'
import {ICON_CONFIG} from "../shared/icons";
import {SubscriptionsComponent} from './subscriptions/subscriptions.component';
import {OrganizationInfoComponent} from './organization-info/organization-info.component';
import {GroupsComponent} from './groups/groups.component';
import {FilterButtonComponent} from "../shared/filter-button/filter-button.component";

@NgModule({
imports: [
Expand All @@ -19,19 +23,26 @@ import { ICONS } from "../shared/icons";
RouterModule.forChild([
{ path: '', component: DashboardComponent},
{ path: '', component: DashboardMenuComponent, outlet: 'sidebar-content'},
{ path: 'configuration', component: OrganizationConfigurationComponent }
{ path: 'configuration', component: OrganizationConfigurationComponent },
{ path: 'subscriptions', component: SubscriptionsComponent },
{ path: 'organization-info', component: OrganizationInfoComponent },
{ path: 'groups', component: GroupsComponent },
]),
SvgIconComponent,
FilterButtonComponent,
],
declarations: [
DashboardComponent,
DashboardMenuComponent,
OrganizationConfigurationComponent,
SubscriptionsComponent,
OrganizationInfoComponent,
GroupsComponent,
],
providers: [
OrganizationService,
EventService,
provideSvgIcons(ICONS),
provideSvgIconsConfig(ICON_CONFIG)
]
})
export class DashboardModule {}
@@ -0,0 +1 @@
<p>groups works!</p>
Empty file.
15 changes: 15 additions & 0 deletions frontend-admin/src/app/dashboard/groups/groups.component.ts
@@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';

@Component({
selector: 'app-groups',
templateUrl: './groups.component.html',
styleUrls: ['./groups.component.scss']
})
export class GroupsComponent implements OnInit {

constructor() { }

ngOnInit(): void {
}

}
@@ -0,0 +1 @@
<p>organization-info works!</p>
Empty file.
@@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';

@Component({
selector: 'app-organization-info',
templateUrl: './organization-info.component.html',
styleUrls: ['./organization-info.component.scss']
})
export class OrganizationInfoComponent implements OnInit {

constructor() { }

ngOnInit(): void {
}

}
@@ -0,0 +1 @@
<p>subscriptions works!</p>
Empty file.
@@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';

@Component({
selector: 'app-subscriptions',
templateUrl: './subscriptions.component.html',
styleUrls: ['./subscriptions.component.scss']
})
export class SubscriptionsComponent implements OnInit {

constructor() { }

ngOnInit(): void {
}

}
@@ -0,0 +1,36 @@
import { NgClass, NgIf } from '@angular/common';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { SvgIconComponent } from '@ngneat/svg-icon';

@Component({
standalone: true,
imports: [SvgIconComponent, NgClass, NgIf],
selector: 'app-filter-button',
template: `
<button
type="button"
class="btn"
style="border-radius: 20px"
[ngClass]="{'btn-outline-primary': !checked, 'btn-primary': checked}"
(click)="onClick()"
>
<svg-icon key="check" size="md" *ngIf="checked"></svg-icon> {{text}}
</button>`,
})
export class FilterButtonComponent {

@Input()
public text?: string;

@Input()
public checked: boolean = false;

@Output()
public toggleFilter = new EventEmitter<boolean>();

constructor() { }

public onClick(): void {
this.toggleFilter.emit(!this.checked);
}
}
25 changes: 24 additions & 1 deletion frontend-admin/src/app/shared/icons.ts
@@ -1,3 +1,26 @@
import { addIcon } from '../svg/add';
import {checkIcon} from '../svg/check';
import {homeIcon} from '../svg/home';
import { organizationIcon } from '../svg/organization';
import { settingsIcon } from '../svg/settings';

export const ICONS = [checkIcon];
const ICONS = [
checkIcon,
homeIcon,
checkIcon,
addIcon,
organizationIcon,
settingsIcon,
];
export const ICON_CONFIG = {
sizes: {
xs: '10px',
sm: '12px',
md: '16px',
lg: '20px',
xl: '25px',
xxl: '30px',
},
defaultSize: 'xl',
icons: ICONS
};
1 change: 1 addition & 0 deletions frontend-admin/src/assets/svg/add.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions frontend-admin/src/assets/svg/home.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions frontend-admin/src/assets/svg/organization.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions frontend-admin/src/assets/svg/settings.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit e8f4fbf

Please sign in to comment.