bug fixed

This commit is contained in:
richard-loafle 2020-04-08 16:46:41 +09:00
parent 09bcca908e
commit 40f2587b3a
29 changed files with 429 additions and 78 deletions

View File

@ -1,5 +1,5 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; import { Routes, RouterModule, UrlSegment } from '@angular/router';
import { DefaultLayoutComponent } from '@app/layouts/components/default.layout.component'; import { DefaultLayoutComponent } from '@app/layouts/components/default.layout.component';
import { NoNaviLayoutComponent } from '@app/layouts/components/no-navi.layout.component'; import { NoNaviLayoutComponent } from '@app/layouts/components/no-navi.layout.component';
@ -7,6 +7,19 @@ import { NoNaviLayoutComponent } from '@app/layouts/components/no-navi.layout.co
import { AppAuthenticationGuard } from '@app/guards/app-authentication.guard'; import { AppAuthenticationGuard } from '@app/guards/app-authentication.guard';
import { AppAuthenticationResolver } from './resolvers/app-authentication.resolver'; import { AppAuthenticationResolver } from './resolvers/app-authentication.resolver';
export function appMatcher(url: UrlSegment[]) {
if (1 === url.length) {
if (
['organization', 'group', 'chat', 'message'].some(
(p) => p === url[0].path
)
) {
return { consumed: url };
}
}
return null;
}
const routes: Routes = [ const routes: Routes = [
{ {
path: 'account', path: 'account',
@ -25,59 +38,59 @@ const routes: Routes = [
) )
}, },
{ {
path: '', matcher: appMatcher,
component: DefaultLayoutComponent, component: DefaultLayoutComponent,
canActivate: [AppAuthenticationGuard], canActivate: [AppAuthenticationGuard],
resolve: { resolve: {
authentication: AppAuthenticationResolver authentication: AppAuthenticationResolver
},
children: [
{ path: '', redirectTo: '/organization', pathMatch: 'full' },
{
path: 'organization',
loadChildren: () =>
import('./pages/organization/organization.page.module').then(
(m) => m.AppOrganizationPageModule
)
},
{
path: 'group',
loadChildren: () =>
import('./pages/group/group.page.module').then(
(m) => m.AppGroupPageModule
)
},
{
path: 'group',
outlet: 'subContent',
loadChildren: () =>
import('./pages/group/group.page.module').then(
(m) => m.AppGroupPageModule
)
},
{
path: 'chat',
loadChildren: () =>
import('./pages/chat/chat.page.module').then(
(m) => m.AppChatPageModule
)
},
{
path: 'call',
loadChildren: () =>
import('./pages/call/call.page.module').then(
(m) => m.AppCallPageModule
)
},
{
path: 'message',
loadChildren: () =>
import('./pages/message/message.page.module').then(
(m) => m.AppMessagePageModule
)
} }
]
}, },
// {
// path: '',
// component: DefaultLayoutComponent,
// canActivate: [AppAuthenticationGuard],
// resolve: {
// authentication: AppAuthenticationResolver
// },
// children: [
// { path: '', redirectTo: '/organization', pathMatch: 'full' },
// {
// path: 'organization',
// loadChildren: () =>
// import('./pages/organization/organization.page.module').then(
// (m) => m.AppOrganizationPageModule
// )
// },
// {
// path: 'group',
// loadChildren: () =>
// import('./pages/group/group.page.module').then(
// (m) => m.AppGroupPageModule
// )
// },
// {
// path: 'chat',
// loadChildren: () =>
// import('./pages/chat/chat.page.module').then(
// (m) => m.AppChatPageModule
// )
// },
// {
// path: 'call',
// loadChildren: () =>
// import('./pages/call/call.page.module').then(
// (m) => m.AppCallPageModule
// )
// },
// {
// path: 'message',
// loadChildren: () =>
// import('./pages/message/message.page.module').then(
// (m) => m.AppMessagePageModule
// )
// }
// ]
// },
{ {
path: '**', path: '**',
redirectTo: '/common/e404' redirectTo: '/common/e404'

View File

@ -1,13 +1,44 @@
import { Component } from '@angular/core'; import { Component, OnDestroy, OnInit } from '@angular/core';
import { CommonApiService } from '@ucap/ng-api-common';
import { Store } from '@ngrx/store';
import { AppActions } from '@app/store/actions';
import { fromEvent, interval, Subscription } from 'rxjs';
import { debounce } from 'rxjs/operators';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'] styleUrls: ['./app.component.scss']
}) })
export class AppComponent { export class AppComponent implements OnInit, OnDestroy {
title = 'ucap-lg-web'; private resizeWindowSubscription: Subscription;
constructor(private commonApiService: CommonApiService) {} constructor(private store: Store<any>) {
this.resizeWindowSubscription = fromEvent(window, 'resize')
.pipe(debounce(() => interval(100)))
.subscribe((event: any) => {
this.dispatchWindowSize({
width: event.target.innerWidth,
height: event.target.innerHeight
});
});
}
ngOnInit(): void {
this.dispatchWindowSize({
width: window.innerWidth,
height: window.innerHeight
});
}
ngOnDestroy(): void {
if (!!this.resizeWindowSubscription) {
this.resizeWindowSubscription.unsubscribe();
}
}
private dispatchWindowSize(size: { width: number; height: number }) {
this.store.dispatch(AppActions.windowResized(size));
}
} }

View File

@ -93,7 +93,16 @@
</mat-tab> </mat-tab>
</mat-tab-group> </mat-tab-group>
</div> </div>
<div> <div class="content-container" fxFlexFill>
<router-outlet></router-outlet> <mat-sidenav-container autosize="true" fxFlexFill>
<mat-sidenav #leftSidenav class="left-sidenav" mode="side" opened="true">
<ng-container fxFlexFill *ngComponentOutlet="leftSectionComponent">
</ng-container>
</mat-sidenav>
<div fxFlex="1 1 auto">
<ng-container *ngComponentOutlet="contentSectionComponent">
</ng-container>
</div>
</mat-sidenav-container>
</div> </div>
</div> </div>

View File

@ -4,4 +4,19 @@
.navi-container { .navi-container {
width: 70px; width: 70px;
} }
.content-container {
.left-sidenav {
display: flex;
flex-direction: column;
width: 370px;
height: 100%;
max-width: 90%;
overflow: hidden;
}
.content-drawer {
flex: 0 0 auto;
}
}
} }

View File

@ -1,31 +1,83 @@
import { Component } from '@angular/core'; import { Component, ViewChild, OnDestroy, OnInit, Type } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { MatTabChangeEvent } from '@angular/material/tabs'; import { MatTabChangeEvent } from '@angular/material/tabs';
import { MatSidenav } from '@angular/material/sidenav';
import { Store, select } from '@ngrx/store';
import { AppSelector } from '@app/store/state';
import { Subscription } from 'rxjs';
@Component({ @Component({
selector: 'app-layouts-default', selector: 'app-layouts-default',
templateUrl: './default.layout.component.html', templateUrl: './default.layout.component.html',
styleUrls: ['./default.layout.component.scss'] styleUrls: ['./default.layout.component.scss']
}) })
export class DefaultLayoutComponent { export class DefaultLayoutComponent implements OnInit, OnDestroy {
constructor(private router: Router) {} @ViewChild('leftSidenav', { static: true })
leftSidenav: MatSidenav;
leftSectionComponent: Type<any>;
contentSectionComponent: Type<any>;
private windowSizeSubscription: Subscription;
constructor(private router: Router, private store: Store<any>) {}
ngOnInit(): void {
this.windowSizeSubscription = this.store
.pipe(select(AppSelector.windowSize))
.subscribe((size) => {
if (size.width < 780) {
if (this.leftSidenav.opened) {
this.leftSidenav.close();
}
} else {
if (!this.leftSidenav.opened) {
this.leftSidenav.open();
}
}
});
}
ngOnDestroy(): void {
if (!this.windowSizeSubscription) {
this.windowSizeSubscription.unsubscribe();
}
}
onSelectedTabChange(event: MatTabChangeEvent) { onSelectedTabChange(event: MatTabChangeEvent) {
switch (event.index) { switch (event.index) {
case 1: case 1:
this.router.navigate(['/chat']); // this.router.navigate(['/chat']);
break; break;
case 2: case 2:
this.router.navigate(['/organization']); import('@app/sections/organization/organization.section.module').then(
(m) => {
this.leftSectionComponent = m.TreeListSectionComponent;
}
);
import('@app/sections/organization/organization.section.module').then(
(m) => {
this.contentSectionComponent = m.MembersSectionComponent;
}
);
break; break;
case 3: case 3:
this.router.navigate(['/message']); // this.router.navigate(['/message']);
break; break;
default: default:
this.router.navigate(['/group']); // this.router.navigate(['/group']);
break; break;
} }
console.log('onClickButton', event.index); }
onClickToggleLeftSidenav() {
if (this.leftSidenav.opened) {
this.leftSidenav.close();
} else {
this.leftSidenav.open();
}
} }
} }

View File

@ -7,6 +7,7 @@ import { FlexLayoutModule } from '@angular/flex-layout';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { MatTabsModule } from '@angular/material/tabs'; import { MatTabsModule } from '@angular/material/tabs';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatToolbarModule } from '@angular/material/toolbar'; import { MatToolbarModule } from '@angular/material/toolbar';
import { UiModule } from '@ucap/ng-ui'; import { UiModule } from '@ucap/ng-ui';
@ -24,6 +25,7 @@ import { DIALOGS } from './dialogs';
MatIconModule, MatIconModule,
MatTabsModule, MatTabsModule,
MatSidenavModule,
MatToolbarModule, MatToolbarModule,
UiModule UiModule

View File

@ -5,7 +5,7 @@ import { IndexPageComponent } from './components/index.page.component';
const routes: Routes = [ const routes: Routes = [
{ {
path: '', path: 'index',
component: IndexPageComponent component: IndexPageComponent
} }
]; ];

View File

@ -2,11 +2,17 @@ import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; import { Routes, RouterModule } from '@angular/router';
import { IndexPageComponent } from './components/index.page.component'; import { IndexPageComponent } from './components/index.page.component';
import { RoomListPageComponent } from './components/room-list.page.component';
const routes: Routes = [ const routes: Routes = [
{ {
path: '**', path: 'index',
component: IndexPageComponent component: IndexPageComponent
},
{
path: 'room-list',
component: RoomListPageComponent,
outlet: 'outlet-content'
} }
]; ];

View File

@ -1,3 +1,4 @@
import { IndexPageComponent } from './index.page.component'; import { IndexPageComponent } from './index.page.component';
import { RoomListPageComponent } from './room-list.page.component';
export const COMPONENTS = [IndexPageComponent]; export const COMPONENTS = [IndexPageComponent, RoomListPageComponent];

View File

@ -0,0 +1 @@
Room list page of chat is works!

View File

@ -0,0 +1,32 @@
import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { RoomListPageComponent } from './room-list.page.component';
describe('app::pages::chat::RoomListPageComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [RoomListPageComponent]
}).compileComponents();
}));
it('should create the app', () => {
const fixture = TestBed.createComponent(RoomListPageComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'ucap-lg-web'`, () => {
const fixture = TestBed.createComponent(RoomListPageComponent);
const app = fixture.componentInstance;
});
it('should render title', () => {
const fixture = TestBed.createComponent(RoomListPageComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain(
'ucap-lg-web app is running!'
);
});
});

View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-pages-chat-room-list',
templateUrl: './room-list.page.component.html',
styleUrls: ['./room-list.page.component.scss']
})
export class RoomListPageComponent {
constructor() {}
}

View File

@ -5,7 +5,7 @@ import { IndexPageComponent } from './components/index.page.component';
const routes: Routes = [ const routes: Routes = [
{ {
path: '', path: 'index',
component: IndexPageComponent component: IndexPageComponent
} }
]; ];

View File

@ -5,7 +5,7 @@ import { IndexPageComponent } from './components/index.page.component';
const routes: Routes = [ const routes: Routes = [
{ {
path: '', path: 'index',
component: IndexPageComponent component: IndexPageComponent
} }
]; ];

View File

@ -5,7 +5,7 @@ import { IndexPageComponent } from './components/index.page.component';
const routes: Routes = [ const routes: Routes = [
{ {
path: '', path: 'index',
component: IndexPageComponent component: IndexPageComponent
} }
]; ];

View File

@ -0,0 +1,3 @@
<div fxFlexFill>
members
</div>

View File

@ -0,0 +1,32 @@
import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { MembersSectionComponent } from './members.section.component';
describe('app::sections::organization::MembersSectionComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [MembersSectionComponent]
}).compileComponents();
}));
it('should create the app', () => {
const fixture = TestBed.createComponent(MembersSectionComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'ucap-lg-web'`, () => {
const fixture = TestBed.createComponent(MembersSectionComponent);
const app = fixture.componentInstance;
});
it('should render title', () => {
const fixture = TestBed.createComponent(MembersSectionComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain(
'ucap-lg-web app is running!'
);
});
});

View File

@ -0,0 +1,19 @@
import { Subscription } from 'rxjs';
import { take, filter } from 'rxjs/operators';
import { Component, OnInit, OnDestroy, Input, ViewChild } from '@angular/core';
import { LogService } from '@ucap/ng-logger';
@Component({
selector: 'app-sections-organization-members',
templateUrl: './members.section.component.html',
styleUrls: ['./members.section.component.scss']
})
export class MembersSectionComponent implements OnInit, OnDestroy {
constructor(private logService: LogService) {}
ngOnInit(): void {}
ngOnDestroy(): void {}
}

View File

@ -0,0 +1,3 @@
<div fxFlexFill>
tree list
</div>

View File

@ -0,0 +1,32 @@
import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { TreeListSectionComponent } from './tree-list.section.component';
describe('app::sections::organization::TreeListSectionComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [TreeListSectionComponent]
}).compileComponents();
}));
it('should create the app', () => {
const fixture = TestBed.createComponent(TreeListSectionComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'ucap-lg-web'`, () => {
const fixture = TestBed.createComponent(TreeListSectionComponent);
const app = fixture.componentInstance;
});
it('should render title', () => {
const fixture = TestBed.createComponent(TreeListSectionComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain(
'ucap-lg-web app is running!'
);
});
});

View File

@ -0,0 +1,19 @@
import { Subscription } from 'rxjs';
import { take, filter } from 'rxjs/operators';
import { Component, OnInit, OnDestroy, Input, ViewChild } from '@angular/core';
import { LogService } from '@ucap/ng-logger';
@Component({
selector: 'app-sections-organization-tree-list',
templateUrl: './tree-list.section.component.html',
styleUrls: ['./tree-list.section.component.scss']
})
export class TreeListSectionComponent implements OnInit, OnDestroy {
constructor(private logService: LogService) {}
ngOnInit(): void {}
ngOnDestroy(): void {}
}

View File

@ -0,0 +1,37 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { I18nModule, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n';
import { AuthenticationUiModule } from '@ucap/ng-ui-authentication';
import { MembersSectionComponent } from './components/members.section.component';
import { TreeListSectionComponent } from './components/tree-list.section.component';
const COMPONENTS = [MembersSectionComponent, TreeListSectionComponent];
export { MembersSectionComponent, TreeListSectionComponent };
@NgModule({
imports: [
CommonModule,
FlexLayoutModule,
MatCheckboxModule,
I18nModule,
AuthenticationUiModule
],
exports: [...COMPONENTS],
declarations: [...COMPONENTS],
entryComponents: [],
providers: [
{
provide: UCAP_I18N_NAMESPACE,
useValue: ['organization']
}
]
})
export class AppOrganizationSectionModule {}

View File

@ -1,3 +1,8 @@
import { createAction, props } from '@ngrx/store'; import { createAction, props } from '@ngrx/store';
export const init = createAction('[ucap::LG::app] init'); export const init = createAction('[ucap::LG::app] init');
export const windowResized = createAction(
'[ucap::LG::app] windowResized',
props<{ width: number; height: number }>()
);

View File

@ -1,4 +1,16 @@
import { createReducer, on } from '@ngrx/store'; import { createReducer, on } from '@ngrx/store';
import { initialState } from './state'; import { initialState } from './state';
import { windowResized } from './actions';
export const reducer = createReducer(initialState); export const reducer = createReducer(
initialState,
on(windowResized, (state, action) => {
return {
...state,
windowSize: {
width: action.width,
height: action.height
}
};
})
);

View File

@ -1,9 +1,21 @@
import { Selector, createSelector } from '@ngrx/store'; import { Selector, createSelector } from '@ngrx/store';
export interface State {} export interface State {
windowSize: {
width: number;
height: number;
};
}
export const initialState: State = {}; export const initialState: State = {
windowSize: {
width: 0,
height: 0
}
};
export function selectors<S>(selector: Selector<any, State>) { export function selectors<S>(selector: Selector<any, State>) {
return {}; return {
windowSize: createSelector(selector, (state: State) => state.windowSize)
};
} }

View File

@ -8,15 +8,20 @@ import * as fromRouter from '@ngrx/router-store';
import { environment } from '@environments'; import { environment } from '@environments';
import { State as AppState } from './app/state'; import * as AppState from './app/state';
import { State as AppAuthenticationState } from './authentication/state'; import * as AppAuthenticationState from './authentication/state';
export interface State { export interface State {
appRouter: fromRouter.RouterReducerState<any>; appRouter: fromRouter.RouterReducerState<any>;
app: AppState; app: AppState.State;
appAuthentication: AppAuthenticationState; appAuthentication: AppAuthenticationState.State;
} }
export const metaReducers: MetaReducer<State>[] = !environment.production export const metaReducers: MetaReducer<State>[] = !environment.production
? [] ? []
: []; : [];
export const AppSelector = AppState.selectors((state: State) => state.app);
export const AppAuthenticationSelector = AppAuthenticationState.selectors(
(state: State) => state.appAuthentication
);