Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui/frontend): add menu-bar #12

Merged
merged 5 commits into from
Jan 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions apps/frontend/src/app/app.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
:host {
display: flex;
flex-flow: column;
height: 100%;
}

main {
flex-grow: 1;
// https://stackoverflow.com/a/38383437
min-height: 0;
}
14 changes: 13 additions & 1 deletion apps/frontend/src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ import { RouterTestingModule } from '@angular/router/testing';
import { SceneViewerTestModule, SidenavShellModule } from '@talus/ui';
import { AppComponent } from './app.component';

@Component({
selector: 'fe-menu-bar-container',
template: '',
changeDetection: ChangeDetectionStrategy.OnPush,
})
class MenuBarContainerStubComponent {}

@Component({
selector: 'fe-scene-viewer-container',
template: '',
Expand All @@ -22,7 +29,12 @@ class ToolsPanelStubComponent {}
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AppComponent, SceneViewerContainerStubComponent, ToolsPanelStubComponent],
declarations: [
AppComponent,
MenuBarContainerStubComponent,
SceneViewerContainerStubComponent,
ToolsPanelStubComponent,
],
imports: [
BrowserAnimationsModule,
RouterTestingModule,
Expand Down
31 changes: 20 additions & 11 deletions apps/frontend/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,30 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
@Component({
selector: 'fe-root',
template: `
<ui-sidenav-shell>
<ui-sidenav-shell-left>
<fe-tools-panel></fe-tools-panel>
</ui-sidenav-shell-left>
<header>
<fe-menu-bar-container></fe-menu-bar-container>
</header>

<ui-sidenav-shell-right>
Right
</ui-sidenav-shell-right>
<main>
<ui-sidenav-shell>
<ui-sidenav-shell-left>
<fe-tools-panel></fe-tools-panel>
</ui-sidenav-shell-left>

<ui-sidenav-shell-content>
<fe-scene-viewer-container></fe-scene-viewer-container>
</ui-sidenav-shell-content>
</ui-sidenav-shell>
<ui-sidenav-shell-right>
Right
</ui-sidenav-shell-right>

<ui-sidenav-shell-content>
<fe-scene-viewer-container></fe-scene-viewer-container>
</ui-sidenav-shell-content>
</ui-sidenav-shell>
</main>

<!--<ui-status-bar></ui-status-bar>-->
`,
changeDetection: ChangeDetectionStrategy.OnPush,
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
title = 'frontend';
Expand Down
2 changes: 2 additions & 0 deletions apps/frontend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { SidenavShellModule } from '@talus/ui';
import { AppComponent } from './app.component';
import { AppEffects } from './app.effects';
import { metaReducers, ROOT_REDUCERS } from './app.reducer';
import { MenuBarContainerModule } from './menu-bar-container/menu-bar-container.module';
import { SceneViewerContainerModule } from './scene-viewer-container';
import { ToolsPanelModule } from './tools-panel/tools-panel.module';
import { UndoRedoModule } from './undo-redo/undo-redo.module';
Expand Down Expand Up @@ -36,6 +37,7 @@ import { UndoRedoModule } from './undo-redo/undo-redo.module';
},
}),

MenuBarContainerModule,
SceneViewerContainerModule,
SidenavShellModule,
ToolsPanelModule,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { createAction } from '@ngrx/store';

const actionTypePrefix = `[menuBarContainer]`;

export const undo = createAction(`${actionTypePrefix} Undo`);
export const redo = createAction(`${actionTypePrefix} Redo`);
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Store, StoreModule } from '@ngrx/store';
import { MockStore } from '@ngrx/store/testing';
import { ROOT_REDUCERS, State } from '../app.reducer';
import { MenuBarContainerComponent } from './menu-bar-container.component';
import { MenuBarContainerModule } from './menu-bar-container.module';

describe('MenuBarComponent', () => {
let component: MenuBarContainerComponent;
let fixture: ComponentFixture<MenuBarContainerComponent>;

let store: MockStore<State>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [],
imports: [
MenuBarContainerModule,
StoreModule.forRoot(ROOT_REDUCERS, {
runtimeChecks: {
strictStateImmutability: true,
strictActionImmutability: true,
strictStateSerializability: true,
strictActionSerializability: true,
},
}),
],
}).compileComponents();

store = TestBed.get<Store<State>>(Store);
}));

beforeEach(() => {
fixture = TestBed.createComponent(MenuBarContainerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Action, Store } from '@ngrx/store';
import { UiMenuBarConfig } from '@talus/ui';
import * as fromApp from '../app.reducer';
import { redo, undo } from './menu-bar-container.actions';

@Component({
selector: 'fe-menu-bar-container',
template: `
<ui-menu-bar (menuItemClick)="onMenuItemClick($event)" [menuConfig]="menuConfig"></ui-menu-bar>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MenuBarContainerComponent {
menuConfig: UiMenuBarConfig<Action> = {
menus: [
{
label: 'Edit',
menuItems: [
{
icon: 'undo',
label: 'Undo',
value: undo(),
},
{
icon: 'redo',
label: 'Redo',
value: redo(),
},
],
},
],
};

constructor(private store: Store<fromApp.State>) {}

onMenuItemClick(action: Action): void {
this.store.dispatch(action);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { NgModule } from '@angular/core';
import { MenuBarModule } from '@talus/ui';
import { MenuBarContainerComponent } from './menu-bar-container.component';

@NgModule({
declarations: [MenuBarContainerComponent],
imports: [MenuBarModule],
exports: [MenuBarContainerComponent],
})
export class MenuBarContainerModule {}
2 changes: 1 addition & 1 deletion apps/frontend/src/app/tools-panel/tools-panel.actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createAction, props } from '@ngrx/store';
import { Tool } from './tool.model';

export const selectTool = createAction('[ToolsPanel] Select tool', props<{ id: Tool }>());
export const selectTool = createAction('[toolsPanel] Select tool', props<{ id: Tool }>());
5 changes: 3 additions & 2 deletions apps/frontend/src/app/undo-redo/undo-redo.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Actions, createEffect, ofType } from '@ngrx/effects';
import { Action, select, Store } from '@ngrx/store';
import { filter, map, switchMap, withLatestFrom } from 'rxjs/operators';
import * as fromApp from '../app.reducer';
import * as menuBarContainerActions from '../menu-bar-container/menu-bar-container.actions';
import { addVoxel, removeVoxel } from '../scene-viewer-container/scene-viewer-container.actions';
import { addUndo, redo, redone, undo, undone } from './undo-redo.actions';

Expand All @@ -12,7 +13,7 @@ export class UndoRedoEffects {

undo$ = createEffect(() =>
this.actions$.pipe(
ofType(undo),
ofType(undo, menuBarContainerActions.undo),
withLatestFrom(this.store.pipe(select(fromApp.selectCurrentUndoAction))),
switchMap(([action, currentUndoAction]) =>
currentUndoAction ? [currentUndoAction, undone()] : [undone()],
Expand All @@ -22,7 +23,7 @@ export class UndoRedoEffects {

redo$ = createEffect(() =>
this.actions$.pipe(
ofType(redo),
ofType(redo, menuBarContainerActions.redo),
withLatestFrom(this.store.pipe(select(fromApp.selectCurrentRedoAction))),
switchMap(([action, currentRedoAction]) =>
currentRedoAction ? [currentRedoAction, redone()] : [redone()],
Expand Down
3 changes: 2 additions & 1 deletion apps/frontend/src/app/undo-redo/undo-redo.reducer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Action, createReducer, on } from '@ngrx/store';
import * as menuBarContainerActions from '../menu-bar-container/menu-bar-container.actions';
import { addUndo, redo, redone, undo, undone } from './undo-redo.actions';

/**
Expand Down Expand Up @@ -43,7 +44,7 @@ export const reducer = createReducer(
};
}),

on(undo, redo, state => {
on(undo, menuBarContainerActions.undo, redo, menuBarContainerActions.redo, state => {
return {
...state,
isUndoRedoing: true,
Expand Down
5 changes: 3 additions & 2 deletions libs/ui/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './lib/ui.module';
export * from './lib/sidenav-shell';
export * from './lib/menu-bar';
export * from './lib/scene-viewer';
export * from './lib/sidenav-shell';
export * from './lib/toolbar';
export * from './lib/ui.module';
2 changes: 2 additions & 0 deletions libs/ui/src/lib/menu-bar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './menu-bar.component';
export * from './menu-bar.module';
5 changes: 5 additions & 0 deletions libs/ui/src/lib/menu-bar/menu-bar.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
$angular-button-height: 36px;

mat-toolbar {
height: $angular-button-height;
}
24 changes: 24 additions & 0 deletions libs/ui/src/lib/menu-bar/menu-bar.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MenuBarComponent } from './menu-bar.component';
import { MenuBarModule } from './menu-bar.module';

describe('MenuBarComponent', () => {
let component: MenuBarComponent;
let fixture: ComponentFixture<MenuBarComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MenuBarModule],
}).compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(MenuBarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
48 changes: 48 additions & 0 deletions libs/ui/src/lib/menu-bar/menu-bar.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';

export interface UiMenuBarConfig<T> {
menus: UiMenuBarMenu<T>[];
}

interface UiMenuBarMenu<T> {
label: string;
menuItems: UiMenuBarMenuItem<T>[];
}

interface UiMenuBarMenuItem<T> {
icon?: string;
label: string;
value: T;
}

@Component({
selector: 'ui-menu-bar',
template: `
<mat-toolbar>
<ng-container *ngFor="let menu of menuConfig.menus">
<button mat-button [matMenuTriggerFor]="mainMenu">{{ menu.label }}</button>
<mat-menu #mainMenu="matMenu">
<button
mat-menu-item
*ngFor="let menuItem of menu.menuItems"
(click)="onMenuItemClick(menuItem.value)"
>
<mat-icon *ngIf="menuItem.icon">{{ menuItem.icon }}</mat-icon>
<span>{{ menuItem.label }}</span>
</button>
</mat-menu>
</ng-container>
</mat-toolbar>
`,
styleUrls: ['./menu-bar.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MenuBarComponent {
@Input() menuConfig: UiMenuBarConfig<any> = { menus: [] };

@Output() menuItemClick = new EventEmitter();

onMenuItemClick(value: any): void {
this.menuItemClick.emit(value);
}
}
11 changes: 11 additions & 0 deletions libs/ui/src/lib/menu-bar/menu-bar.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MatButtonModule, MatIconModule, MatMenuModule, MatToolbarModule } from '@angular/material';
import { MenuBarComponent } from './menu-bar.component';

@NgModule({
declarations: [MenuBarComponent],
imports: [CommonModule, MatButtonModule, MatIconModule, MatMenuModule, MatToolbarModule],
exports: [MenuBarComponent],
})
export class MenuBarModule {}
4 changes: 1 addition & 3 deletions libs/ui/src/lib/scene-viewer/scene-viewer.component.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
:host,
canvas {
display: block;
width: 100%;
height: 100%;
width: 100%;
}
1 change: 0 additions & 1 deletion libs/ui/src/lib/sidenav-shell/sidenav-shell.component.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
:host,
mat-sidenav-container {
display: block;
height: 100%;
}

Expand Down