sidebar animations

This commit is contained in:
lotte
2018-11-23 14:44:11 +01:00
parent ea3a2076c7
commit 567d4dc331
20 changed files with 326 additions and 231 deletions

View File

@@ -210,6 +210,75 @@
"no-items": "No bitstream formats to show." "no-items": "No bitstream formats to show."
} }
} }
},
"sidebar": {
"section": {
"new": {
"header": "New",
"subsections": {
"community": "Community",
"collection": "Collection",
"item": "Item",
"item_version": "Item Version"
}
},
"edit": {
"header": "Edit",
"subsections": {
"community": "Community",
"collection": "Collection",
"item": "Item"
}
},
"import": {
"header": "Import",
"subsections": {
"metadata": "Metadata",
"batch_import": "Batch Import (ZIP)"
}
},
"export": {
"header": "Export",
"subsections": {
"community": "Community",
"collection": "Collection",
"item": "Item",
"metadata": "Metadata"
}
},
"access_control": {
"header": "Access Control",
"subsections": {
"people": "People",
"groups": "Groups",
"authorizations": "Authorizations"
}
},
"find": {
"header": "Find",
"subsections": {
"items": "Items",
"withdrawn_items": "Withdrawn Items",
"private_items": "Private Items"
}
},
"registries": {
"header": "Registries",
"subsections": {
"metadata": "Metadata",
"format": "Format"
}
},
"curation_task": {
"header": "Curation Task"
},
"statistics": {
"header": "Statistics Task"
},
"control_panel": {
"header": "Control Panel"
}
}
} }
}, },
"loading": { "loading": {

View File

@@ -0,0 +1 @@
@import '../../../../styles/variables.scss';

View File

@@ -6,137 +6,58 @@
<div class="sidebar-top-level-items"> <div class="sidebar-top-level-items">
<ul class="navbar-nav"> <ul class="navbar-nav">
<li class="admin-menu-header"> <li class="admin-menu-header sidebar-section">
<a class="shortcuts-tree navbar-brand mr-0" href="#"> <a class="shortcuts-tree navbar-brand mr-0 p-0" href="#">
<span class="logo-wrapper"> <span class="logo-wrapper">
<img class="admin-logo" src="assets/images/dspace-logo-mini.svg"> <img class="admin-logo" src="assets/images/dspace-logo-mini.svg">
</span> </span>
<h4 class="section-header-text">Admin</h4> <h4 class="section-header-text">Admin</h4>
</a> </a>
</li> </li>
<li [ngClass]="{'active': (active('new') | async)}"> <ds-expandable-admin-sidebar-section name="new" icon="plus-circle" [subSections]="[
<a class="nav-item nav-link shortcuts-tree" href="#" {name: 'Community', link: '#'},
(click)="toggleSection($event, 'new')"> {name: 'Collection', link: '#'},
<i class="fas fa-plus-circle fa-fw"></i> {name: 'Item', link: '#'},
<span class="section-header-text">New</span> {name: 'Item Version', link: '#'}
<i class="fas fa-chevron-right fa-pull-right fa-xxs" ]"></ds-expandable-admin-sidebar-section>
[@rotateInOut]="(active('new') | async) ? 'rotateOut': 'rotateIn'"></i> <ds-expandable-admin-sidebar-section name="edit" icon="pencil-alt" [subSections]="[
</a> {name: 'Community', link: '#'},
<ul class="sidebar-sub-level-items" [ngbCollapse]="!(active('new') | async)"> {name: 'Collection', link: '#'},
<li><a class="nav-item nav-link" href="#">Community</a></li> {name: 'Item', link: '#'}
<li><a class="nav-item nav-link" href="#">Collection</a></li> ]"></ds-expandable-admin-sidebar-section>
<li><a class="nav-item nav-link" href="#">Item</a></li> <ds-expandable-admin-sidebar-section name="import" icon="sign-in-alt" [subSections]="[
<li><a class="nav-item nav-link" href="#">Item Version</a></li> {name: 'Metadata', link: '#'},
</ul> {name: 'Batch Import (ZIP)', link: '#'}
</li> ]"></ds-expandable-admin-sidebar-section>
<li [ngClass]="{'active': (active('edit') | async)}"> <ds-expandable-admin-sidebar-section name="export" icon="sign-out-alt" [subSections]="[
<a class="nav-item nav-link shortcuts-tree" href="#" {name: 'Community', link: '#'},
(click)="toggleSection($event, 'edit')"> {name: 'Collection', link: '#'},
<i class="fas fa-pencil-alt fa-fw"></i> {name: 'Item', link: '#'},
<span class="section-header-text">Edit</span> {name: 'Metadata', link: '#'}
<i class="fas fa-chevron-right fa-pull-right fa-xxs" ]"></ds-expandable-admin-sidebar-section>
[ngClass]="{'fa-rotate-90': (active('edit') | async)}"></i> <ds-expandable-admin-sidebar-section name="access_control" icon="key" [subSections]="[
</a> {name: 'People', link: '#'},
<ul class="sidebar-sub-level-items" [ngbCollapse]="!(active('edit') | async)"> {name: 'Groups', link: '#'},
<li><a class="nav-item nav-link" href="#">Community</a></li> {name: 'Authorizations', link: '#'}
<li><a class="nav-item nav-link" href="#">Collection</a></li> ]"></ds-expandable-admin-sidebar-section>
<li><a class="nav-item nav-link" href="#">Item</a></li> <ds-expandable-admin-sidebar-section name="find" icon="search" [subSections]="[
</ul> {name: 'Items', link: '#'},
</li> {name: 'Withdrawn Items', link: '#'},
<li [ngClass]="{'active': (active('import') | async)}"> {name: 'Private Items', link: '#'}
<a class="nav-item nav-link shortcuts-tree" href="#" ]"></ds-expandable-admin-sidebar-section>
(click)="toggleSection($event, 'import')"> <ds-expandable-admin-sidebar-section name="registries" icon="list" [subSections]="[
<i class="fas fa-arrow-circle-up fa-fw"></i> {name: 'Metadata', link: '#'},
<span class="section-header-text">Import</span> {name: 'Format', link: '#'}
<i class="fas fa-chevron-right fa-pull-right fa-xxs" ]"></ds-expandable-admin-sidebar-section>
[ngClass]="{'fa-rotate-90': (active('import') | async)}"></i> <ds-admin-sidebar-section name="curation_task" icon="filter" link="#"></ds-admin-sidebar-section>
</a> <ds-admin-sidebar-section name="statistics" icon="chart-bar" link="#"></ds-admin-sidebar-section>
<ul class="sidebar-sub-level-items" [ngbCollapse]="!(active('import') | async)"> <ds-admin-sidebar-section name="control_panel" icon="cogs" link="#"></ds-admin-sidebar-section>
<li><a class="nav-item nav-link" href="#">Metadata</a></li>
<li><a class="nav-item nav-link" href="#">Batch Import (ZIP)</a></li>
</ul>
</li>
<li [ngClass]="{'active': (active('export') | async)}">
<a class="nav-item nav-link shortcuts-tree" href="#"
(click)="toggleSection($event, 'export')">
<i class="fas fa-arrow-circle-down fa-fw"></i>
<span class="section-header-text">Export</span>
<i class="fas fa-chevron-right fa-pull-right fa-xxs"
[ngClass]="{'fa-rotate-90': (active('export') | async)}"></i>
</a>
<ul class="sidebar-sub-level-items" [ngbCollapse]="!(active('export') | async)">
<li><a class="nav-item nav-link" href="#">Community</a></li>
<li><a class="nav-item nav-link" href="#">Collection</a></li>
<li><a class="nav-item nav-link" href="#">Item</a></li>
<li><a class="nav-item nav-link" href="#">Metadata</a></li>
</ul>
</li>
<li [ngClass]="{'active': (active('access_control') | async)}">
<a class="nav-item nav-link shortcuts-tree" href="#"
(click)="toggleSection($event, 'access_control')">
<i class="fas fa-key fa-fw"></i>
<span class="section-header-text">Access Control</span>
<i class="fas fa-chevron-right fa-pull-right fa-xxs"
[ngClass]="{'fa-rotate-90': (active('access_control') | async)}"></i>
</a>
<ul class="sidebar-sub-level-items"
[ngbCollapse]="!(active('access_control') | async)">
<li><a class="nav-item nav-link" href="#">People</a></li>
<li><a class="nav-item nav-link" href="#">Groups</a></li>
<li><a class="nav-item nav-link" href="#">Authorizations</a></li>
</ul>
</li>
<li [ngClass]="{'active': (active('find') | async)}">
<a class="nav-item nav-link shortcuts-tree" href="#"
(click)="toggleSection($event, 'find')">
<i class="fas fa-search fa-fw"></i>
<span class="section-header-text">Find</span>
<i class="fas fa-chevron-right fa-pull-right fa-xxs"
[ngClass]="{'fa-rotate-90': (active('find') | async)}"></i>
</a>
<ul class="sidebar-sub-level-items" [ngbCollapse]="!(active('find') | async)">
<li><a class="nav-item nav-link" href="#">Items</a></li>
<li><a class="nav-item nav-link" href="#">Withdrawn Items</a></li>
<li><a class="nav-item nav-link" href="#">Private Items</a></li>
</ul>
</li>
<li [ngClass]="{'active': (active('registries') | async)}">
<a class="nav-item nav-link shortcuts-tree" href="#"
(click)="toggleSection($event, 'registries')">
<i class="fas fa-list fa-fw"></i>
<span class="section-header-text">Registries</span>
<i class="fas fa-chevron-right fa-pull-right fa-xxs"
[ngClass]="{'fa-rotate-90': (active('registries') | async)}"></i>
</a>
<ul class="sidebar-sub-level-items" [ngbCollapse]="!(active('registries') | async)">
<li><a class="nav-item nav-link" href="#">Metadata</a></li>
<li><a class="nav-item nav-link" href="#">Format</a></li>
</ul>
</li>
<li>
<a class="nav-item nav-link shortcuts-tree" href="#">
<i class="fas fa-filter fa-fw"></i>
<span class="section-header-text">Curation Tasks</span>
</a>
</li>
<li>
<a class="nav-item nav-link shortcuts-tree" href="#">
<i class="fas fa-chart-bar fa-fw"></i>
<span class="section-header-text">Statistics</span>
</a>
</li>
<li>
<a class="nav-item nav-link shortcuts-tree" href="#">
<i class="fas fa-cogs fa-fw"></i>
<span class="section-header-text">Control Panel</span>
</a>
</li>
</ul> </ul>
</div> </div>
<div class="navbar-nav"> <div class="navbar-nav">
<a class="nav-item nav-link shortcuts-tree" href="#" <a class="nav-item nav-link shortcuts-tree sidebar-section" id="sidebar-collapse-toggle" href="#"
(click)="toggle($event)"> (click)="toggle($event)">
<i class="fas fa-fw fa-angle-double-right"></i> <i class="fas fa-fw fa-angle-double-right" [ngClass]="{'fa-angle-double-right': (sidebarCollapsed | async), 'fa-angle-double-left': !(sidebarCollapsed | async)}"></i>
<span class="section-header-text">Collapse</span> <span class="section-header-text">Collapse</span>
</a> </a>
</div> </div>

View File

@@ -16,50 +16,46 @@
overflow: auto; overflow: auto;
} }
} }
.section-header-text, .fa-chevron-right {
display: none; .admin-menu-header {
padding-left: $spacer/2; background-color: $admin-sidebar-header-bg;
.logo-wrapper {
text-align: center;
display: inline-block;
width: 1.25em;
img {
height: 1em;
vertical-align: text-bottom;
}
}
.section-header-text {
vertical-align: bottom;
}
} }
.navbar-nav { ::ng-deep {
> li, > a {
padding: $spacer/2 $spacer;
&.active {
background-color: $admin-sidebar-dark;
}
} .navbar-nav {
.sidebar-section {
.sidebar-sub-level-items { padding: $spacer;
list-style: disc;
color: $navbar-dark-color;
}
.fa-xxs {
font-size: 0.5rem;
line-height: 3;
}
.admin-menu-header {
background-color: $admin-sidebar-dark;
.logo-wrapper {
text-align: center;
display: inline-block;
width: 1.25em;
img {
height: 1em;
vertical-align: text-bottom;
}
} }
.section-header-text { .section-header-text {
vertical-align: bottom; display: none;
padding-left: $spacer/2;
}
#sidebar-collapse-toggle {
border-top: 2px solid rgba(255, 255, 255, 0.1);
} }
} }
} }
&.active { &.active {
.section-header-text, .fa-chevron-right { ::ng-deep {
display: inline; .section-header-text, .fa-chevron-right {
display: inline;
}
} }
} }
} }
} }

View File

@@ -1,59 +1,27 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/internal/Observable'; import { Observable } from 'rxjs/internal/Observable';
import { MemoizedSelector, select, Store } from '@ngrx/store';
import { AdminSidebarSectionState, AdminSidebarState, } from './admin-sidebar.reducer';
import { hasValue } from '../../shared/empty.util';
import { map } from 'rxjs/operators';
import {
AdminSidebarSectionCollapseAllAction,
AdminSidebarSectionToggleAction,
AdminSidebarToggleAction
} from './admin-sidebar.actions';
import { AppState, keySelector } from '../../app.reducer';
import { slideSidebar } from '../../shared/animations/slide'; import { slideSidebar } from '../../shared/animations/slide';
import { CSSVariableService } from '../../shared/sass-helper/sass-helper.service'; import { CSSVariableService } from '../../shared/sass-helper/sass-helper.service';
import { rotateInOut } from '../../shared/animations/rotate'; import { AdminSidebarService } from './admin-sidebar.service';
const sidebarSectionStateSelector = (state: AppState) => state.adminSidebar.sections;
const sidebarStateSelector = (state) => state.adminSidebar;
const sectionByNameSelector = (name: string): MemoizedSelector<AppState, AdminSidebarSectionState> => {
return keySelector<AdminSidebarSectionState>(name, sidebarSectionStateSelector);
};
@Component({ @Component({
selector: 'ds-admin-sidebar', selector: 'ds-admin-sidebar',
templateUrl: './admin-sidebar.component.html', templateUrl: './admin-sidebar.component.html',
styleUrls: ['./admin-sidebar.component.scss'], styleUrls: ['./admin-sidebar.component.scss'],
animations: [slideSidebar, rotateInOut] animations: [slideSidebar]
}) })
export class AdminSidebarComponent implements OnInit { export class AdminSidebarComponent implements OnInit {
sidebarCollapsed: Observable<boolean>; sidebarCollapsed: Observable<boolean>;
sidebarWidth: Observable<string>; sidebarWidth: Observable<string>;
sidebarActive = true; sidebarActive = true;
constructor(private store: Store<AdminSidebarState>, constructor(private sidebarService: AdminSidebarService,
private variableService: CSSVariableService) { private variableService: CSSVariableService) {
} }
ngOnInit(): void { ngOnInit(): void {
this.sidebarWidth = this.variableService.getVariable('adminSidebarWidth') this.sidebarWidth = this.variableService.getVariable('adminSidebarWidth');
this.sidebarCollapsed = this.store.pipe( this.sidebarCollapsed = this.sidebarService.isSidebarCollapsed();
select(sidebarStateSelector),
map((state: AdminSidebarState) => state.collapsed)
);
}
public active(name: string): Observable<boolean> {
return this.store.pipe(
select(sectionByNameSelector(name)),
map((state: AdminSidebarSectionState) => hasValue(state) ? !state.sectionCollapsed : false)
);
}
toggleSection(event: Event, name: string) {
event.preventDefault();
this.store.dispatch(new AdminSidebarSectionToggleAction(name));
} }
toggle(event: Event) { toggle(event: Event) {
@@ -61,9 +29,9 @@ export class AdminSidebarComponent implements OnInit {
// Is sidebar closing? // Is sidebar closing?
if (this.sidebarActive) { if (this.sidebarActive) {
this.sidebarActive = false; this.sidebarActive = false;
this.store.dispatch(new AdminSidebarSectionCollapseAllAction()); this.sidebarService.collapseAllSections();
} }
this.store.dispatch(new AdminSidebarToggleAction()); this.sidebarService.toggleSidebar();
} }
/** /**

View File

@@ -0,0 +1,55 @@
import { Injectable } from '@angular/core';
import { AppState, keySelector } from '../../app.reducer';
import { MemoizedSelector, select, Store } from '@ngrx/store';
import { AdminSidebarSectionState, AdminSidebarState } from './admin-sidebar.reducer';
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs/internal/Observable';
import { hasValue } from '../../shared/empty.util';
import {
AdminSidebarSectionCollapseAllAction,
AdminSidebarSectionToggleAction,
AdminSidebarToggleAction
} from './admin-sidebar.actions';
const sidebarStateSelector = (state) => state.adminSidebar;
const sidebarSectionStateSelector = (state: AppState) => state.adminSidebar.sections;
const sectionByNameSelector = (name: string): MemoizedSelector<AppState, AdminSidebarSectionState> => {
return keySelector<AdminSidebarSectionState>(name, sidebarSectionStateSelector);
};
/**
* Service that performs all actions that have to do with search the admin sidebar
*/
@Injectable()
export class AdminSidebarService {
constructor(private store: Store<AdminSidebarState>) {
}
isSidebarCollapsed(): Observable<boolean> {
return this.store.pipe(
select(sidebarStateSelector),
map((state: AdminSidebarState) => state.collapsed)
);
}
toggleSidebar(): void {
this.store.dispatch(new AdminSidebarToggleAction());
}
toggleSection(name: string): void {
this.store.dispatch(new AdminSidebarSectionToggleAction(name));
}
collapseAllSections(): void {
this.store.dispatch(new AdminSidebarSectionCollapseAllAction());
}
isSectionCollapsed(name: string): Observable<boolean> {
return this.store.pipe(
select(sectionByNameSelector(name)),
map((state: AdminSidebarSectionState) => hasValue(state) ? state.sectionCollapsed : true)
);
}
}

View File

@@ -0,0 +1,19 @@
@import '../../../../styles/variables.scss';
.fa-chevron-right {
display: none;
padding-left: $spacer/2;
font-size: 0.5rem;
line-height: 3;
}
.sub-section-wrapper {
overflow: hidden;
}
.sidebar-sub-level-items {
list-style: disc;
color: $navbar-dark-color;
/** To make sure animation is smooth */
width: 0;
}

View File

@@ -1,7 +1,7 @@
<div> <div>
<div (click)="toggle()" class="filter-name"><h5 class="d-inline-block mb-0">{{'search.filters.filter.' + filter.name + '.head'| translate}}</h5> <span class="filter-toggle fas float-right" <div (click)="toggle()" class="filter-name"><h5 class="d-inline-block mb-0">{{'search.filters.filter.' + filter.name + '.head'| translate}}</h5> <span class="filter-toggle fas float-right"
[ngClass]="(isCollapsed() | async) ? 'fa-plus' : 'fa-minus'"></span></div> [ngClass]="(isCollapsed() | async) ? 'fa-plus' : 'fa-minus'"></span></div>
<div [@slide]="(isCollapsed() | async) ? 'collapsed' : 'expanded'" (@slide.start)="startSlide($event)" (@slide.done)="finishSlide($event)" class="search-filter-wrapper" [ngClass]="{'closed' : collapsed}"> <div @slide *ngIf="!(isCollapsed() | async)" (@slide.start)="startSlide($event)" (@slide.done)="finishSlide($event)" class="search-filter-wrapper" [ngClass]="{'closed' : collapsed}">
<ds-search-facet-filter-wrapper [filterConfig]="filter"></ds-search-facet-filter-wrapper> <ds-search-facet-filter-wrapper [filterConfig]="filter"></ds-search-facet-filter-wrapper>
</div> </div>
</div> </div>

View File

@@ -34,6 +34,8 @@ import { SharedModule } from './shared/shared.module';
import { NavbarComponent } from './navbar/navbar.component'; import { NavbarComponent } from './navbar/navbar.component';
import { HeaderNavbarWrapperComponent } from './header-nav-wrapper/header-navbar-wrapper.component'; import { HeaderNavbarWrapperComponent } from './header-nav-wrapper/header-navbar-wrapper.component';
import { AdminSidebarComponent } from './+admin/admin-sidebar/admin-sidebar.component'; import { AdminSidebarComponent } from './+admin/admin-sidebar/admin-sidebar.component';
import { AdminSidebarSectionComponent } from './+admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component';
import { ExpandableAdminSidebarSectionComponent } from './+admin/admin-sidebar/expandable-admin-sidebar-section/expandable-admin-sidebar-section.component';
export function getConfig() { export function getConfig() {
return ENV_CONFIG; return ENV_CONFIG;
@@ -94,6 +96,8 @@ const DECLARATIONS = [
NavbarComponent, NavbarComponent,
HeaderNavbarWrapperComponent, HeaderNavbarWrapperComponent,
AdminSidebarComponent, AdminSidebarComponent,
AdminSidebarSectionComponent,
ExpandableAdminSidebarSectionComponent,
FooterComponent, FooterComponent,
PageNotFoundComponent, PageNotFoundComponent,
NotificationComponent, NotificationComponent,
@@ -112,7 +116,7 @@ const EXPORTS = [
...PROVIDERS ...PROVIDERS
], ],
declarations: [ declarations: [
...DECLARATIONS ...DECLARATIONS,
], ],
exports: [ exports: [
...EXPORTS ...EXPORTS

View File

@@ -65,6 +65,7 @@ import { UploaderService } from '../shared/uploader/uploader.service';
import { BrowseItemsResponseParsingService } from './data/browse-items-response-parsing-service'; import { BrowseItemsResponseParsingService } from './data/browse-items-response-parsing-service';
import { DSpaceObjectDataService } from './data/dspace-object-data.service'; import { DSpaceObjectDataService } from './data/dspace-object-data.service';
import { CSSVariableService } from '../shared/sass-helper/sass-helper.service'; import { CSSVariableService } from '../shared/sass-helper/sass-helper.service';
import { AdminSidebarService } from '../+admin/admin-sidebar/admin-sidebar.service';
const IMPORTS = [ const IMPORTS = [
CommonModule, CommonModule,
@@ -130,6 +131,7 @@ const PROVIDERS = [
UUIDService, UUIDService,
DSpaceObjectDataService, DSpaceObjectDataService,
CSSVariableService, CSSVariableService,
AdminSidebarService,
// register AuthInterceptor as HttpInterceptor // register AuthInterceptor as HttpInterceptor
{ {
provide: HTTP_INTERCEPTORS, provide: HTTP_INTERCEPTORS,

View File

@@ -5,6 +5,8 @@
</a> </a>
<nav class="navbar navbar-light navbar-expand-md float-right px-0"> <nav class="navbar navbar-light navbar-expand-md float-right px-0">
<a href="#" class="px-1"><i class="fas fa-search fa-lg fa-fw"></i></a>
<a href="#" class="px-1"><i class="fas fa-globe-asia fa-lg fa-fw"></i></a>
<ds-auth-nav-menu></ds-auth-nav-menu> <ds-auth-nav-menu></ds-auth-nav-menu>
<div class="pl-2"> <div class="pl-2">
<button class="navbar-toggler" type="button" (click)="toggle()" <button class="navbar-toggler" type="button" (click)="toggle()"

View File

@@ -13,7 +13,7 @@
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{
'nav.browse.header' | translate }}</a> 'nav.browse.header' | translate }}</a>
<div ngbDropdownMenu aria-labelledby="browseDropdown" <div ngbDropdownMenu aria-labelledby="browseDropdown"
class="rounded-bottom m-0 shadow-none border-top-0"> class="m-0 shadow-none border-top-0 browse-dropdown-menu">
<a class="dropdown-item" href="/communitylist">Communities & <a class="dropdown-item" href="/communitylist">Communities &
Collections</a> Collections</a>
<a class="dropdown-item" href="/browse?type=dateissued">By Issue <a class="dropdown-item" href="/browse?type=dateissued">By Issue

View File

@@ -7,6 +7,8 @@ nav.navbar {
.dropdown-menu { .dropdown-menu {
min-width: 100%; min-width: 100%;
border-top-left-radius: 0;
border-top-right-radius: 0;
} }
/** Mobile menu styling **/ /** Mobile menu styling **/

View File

@@ -0,0 +1,26 @@
import {
animate,
animateChild,
group, query,
state,
style,
transition,
trigger
} from '@angular/animations';
const startStyle = style({ backgroundColor: '{{ startColor }}' });
const endStyle = style({ backgroundColor: '{{ endColor }}' });
export const bgColor = trigger('bgColor',
[
state('startBackground', startStyle, { params: { startColor: '*' } }),
state('endBackground', endStyle, { params: { endColor: '*' } }),
transition('startBackground <=> endBackground',
group(
[
query('@*', animateChild()),
animate('200ms'),
]
))
]);

View File

@@ -1,21 +1,17 @@
import { animate, state, style, transition, trigger } from '@angular/animations'; import { animate, state, style, transition, trigger } from '@angular/animations';
export const rotateInState = state('rotateIn', style({opacity: 1, transform: 'rotate(0deg)'})); export const rotateInState = state('rotateIn', style({ opacity: 1, transform: 'rotate(0deg)' }));
export const rotateEnter = transition('* => rotateIn', [ export const rotateEnter = transition('* => rotateIn', [
style({opacity: 0, transform: 'rotate(5deg)'}), style({ opacity: 0, transform: 'rotate(5deg)' }),
animate('400ms ease-in-out') animate('400ms ease-in-out')
]); ]);
export const rotateOutState = state('rotateOut', style({opacity: 0, transform: 'rotate(5deg)'})); export const rotateOutState = state('rotateOut', style({ opacity: 0, transform: 'rotate(5deg)' }));
export const rotateLeave = transition('rotateIn => rotateOut', [ export const rotateLeave = transition('rotateIn => rotateOut', [
style({opacity: 1, transform: 'rotate(0deg)'}), style({ opacity: 1, transform: 'rotate(0deg)' }),
animate('400ms ease-in-out') animate('400ms ease-in-out')
]); ]);
export const rotate = state('rotate', style({opacity: 0, transform: 'rotate(90deg)'}));
export const rotateIn = trigger('rotateIn', [ export const rotateIn = trigger('rotateIn', [
rotateEnter rotateEnter
]); ]);
@@ -28,3 +24,16 @@ export const rotateInOut = trigger('rotateInOut', [
rotateEnter, rotateEnter,
rotateLeave rotateLeave
]); ]);
const expandedStyle = { transform: 'rotate(90deg)' };
const collapsedStyle = { transform: 'rotate(0deg)' };
export const rotate = trigger('rotate',
[
state('expanded', style(expandedStyle)),
state('collapsed', style(collapsedStyle)),
transition('expanded <=> collapsed', [
animate('200ms')
])
]);

View File

@@ -1,12 +1,18 @@
import { animate, state, style, transition, trigger } from '@angular/animations'; import {
animate,
animateChild,
group, query, sequence,
state,
style,
transition,
trigger
} from '@angular/animations';
export const slide = trigger('slide', [ export const slide = trigger('slide', [
state('void', style({ height: 0 })),
state('expanded', style({ height: '*' })), state('*', style({ height: '*' })),
transition(':enter', [animate('200ms')]),
state('collapsed', style({ height: 0 })), transition(':leave', [animate('200ms')])
transition('expanded <=> collapsed', animate('250ms'))
]); ]);
export const slideMobileNav = trigger('slideMobileNav', [ export const slideMobileNav = trigger('slideMobileNav', [
@@ -27,5 +33,14 @@ export const slideSidebar = trigger('slideSidebar', [
state('collapsed', style({ width: '*' })), state('collapsed', style({ width: '*' })),
transition('expanded <=> collapsed', animate('300ms ease-in-out')), transition('expanded <=> collapsed',
group
(
[
query('@*', animateChild()),
animate('300ms ease-in-out'),
]
))
]); ]);

View File

@@ -1,25 +1,29 @@
<ul class="navbar-nav" [ngClass]="{'mr-auto': (isXsOrSm$ | async)}"> <ul class="navbar-nav" [ngClass]="{'mr-auto': (isXsOrSm$ | async)}">
<li *ngIf="!(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item" (click)="$event.stopPropagation();"> <li *ngIf="!(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item" (click)="$event.stopPropagation();">
<div ngbDropdown placement="bottom-right" class="d-inline-block" @fadeInOut> <div ngbDropdown placement="bottom-right" class="d-inline-block" @fadeInOut>
<a href="#" id="dropdownLogin" class="nav-link" (click)="$event.preventDefault()" ngbDropdownToggle><i class="fas fa-sign-in-alt fa-fw" aria-hidden="true"></i> {{ 'nav.login' | translate }}<span class="caret"></span></a> <a href="#" id="dropdownLogin" (click)="$event.preventDefault()" ngbDropdownToggle class="px-1">{{ 'nav.login' | translate }}</a>
<div id="loginDropdownMenu" [ngClass]="{'pl-3 pr-3': (loading | async)}" ngbDropdownMenu aria-labelledby="dropdownLogin"> <div id="loginDropdownMenu" [ngClass]="{'pl-3 pr-3': (loading | async)}" ngbDropdownMenu aria-labelledby="dropdownLogin">
<ds-log-in></ds-log-in> <ds-log-in></ds-log-in>
</div> </div>
</div> </div>
</li> </li>
<li *ngIf="!(isAuthenticated | async) && (isXsOrSm$ | async)" class="nav-item"> <li *ngIf="!(isAuthenticated | async) && (isXsOrSm$ | async)" class="nav-item">
<a id="loginLink" class="nav-link" routerLink="/login" routerLinkActive="active"><i class="fas fa-sign-in-alt fa-fw" aria-hidden="true"></i> {{ 'nav.login' | translate }}<span class="sr-only">(current)</span></a> <a id="loginLink" routerLink="/login" routerLinkActive="active" class="px-1" >{{ 'nav.login' | translate }}<span class="sr-only">(current)</span></a>
</li> </li>
<li *ngIf="(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item"> <li *ngIf="(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item">
<div ngbDropdown placement="bottom-right" class="d-inline-block" @fadeInOut> <div ngbDropdown placement="bottom-right" class="d-inline-block" @fadeInOut>
<a href="#" id="dropdownUser" class="nav-link" (click)="$event.preventDefault()" ngbDropdownToggle><i class="fas fa-user fa-fw" aria-hidden="true"></i>Hello {{(user | async).name}}<span class="caret"></span></a> <!--<a href="#" id="dropdownUser" (click)="$event.preventDefault()" ngbDropdownToggle><i class="fas fa-user fa-fw" aria-hidden="true"></i>Hello {{(user | async).name}}<span class="caret"></span></a>-->
<div id="logoutDropdownMenu" ngbDropdownMenu aria-labelledby="dropdownUser"> <a href="#" id="dropdownUser" (click)="$event.preventDefault()" class="px-1" ngbDropdownToggle><i class="fas fa-user-circle fa-lg fa-fw"></i></a>
<ds-log-out></ds-log-out> <ul id="logoutDropdownMenu" ngbDropdownMenu aria-labelledby="dropdownUser">
</div> <li class="dropdown-item">{{(user | async).name}}</li>
<li class="dropdown-item"><ds-log-out></ds-log-out></li>
</ul>
</div> </div>
</li> </li>
<li *ngIf="(isAuthenticated | async) && (isXsOrSm$ | async)" class="nav-item"> <li *ngIf="(isAuthenticated | async) && (isXsOrSm$ | async)" class="nav-item">
<a id="logoutLink" class="nav-link" routerLink="/logout" routerLinkActive="active"><i class="fas fa-sign-out-alt fa-fw" aria-hidden="true"></i> {{ 'nav.logout' | translate }}<span class="sr-only">(current)</span></a> <a id="logoutLink" routerLink="/logout" routerLinkActive="active" class="px-1"><i class="fas fa-user-circle fa-lg fa-fw"></i><span class="sr-only">(current)</span></a>
<!--<a id="logoutLink" routerLink="/logout" routerLinkActive="active"><i class="fas fa-sign-out-alt fa-fw" aria-hidden="true"></i> {{ 'nav.logout' | translate }}<span class="sr-only">(current)</span></a>-->
</li> </li>
</ul> </ul>

View File

@@ -11,12 +11,12 @@ $gray-600: lighten($gray-base, 73.3%) !default; // #bbb
$gray-100: lighten($gray-base, 93.5%) !default; // #eee $gray-100: lighten($gray-base, 93.5%) !default; // #eee
/* Reassign color vars to semantic color scheme */ /* Reassign color vars to semantic color scheme */
$blue: #2B4E72 !default; $blue: #2B4E72 !default;
$green: #94BA65 !default; $green: #94BA65 !default;
$cyan: #2790B0 !default; $cyan: #2790B0 !default;
$yellow: #EBBB54 !default; $yellow: #EBBB54 !default;
$red: #CF4444 !default; $red: #CF4444 !default;
$dark: #132333 !default; $dark: darken($blue, 17%) !default;
$theme-colors: ( $theme-colors: (
primary: $blue, primary: $blue,
@@ -31,10 +31,9 @@ $theme-colors: (
/* Fonts */ /* Fonts */
$link-color: map-get($theme-colors, info) !default; $link-color: map-get($theme-colors, info) !default;
$navbar-dark-color: rgba(white, .5) !default; $navbar-dark-color: rgba(white, .5) !default;
$navbar-light-color: rgba(black, .5) !default; $navbar-light-color: rgba(black, .5) !default;
$navbar-dark-toggler-icon-bg: url("data%3Aimage%2Fsvg+xml%3Bcharset%3Dutf8%2C%3Csvg+viewBox%3D%270+0+30+30%27+xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3Cpath+stroke%3D%27#{$navbar-dark-color}%27+stroke-width%3D%272%27+stroke-linecap%3D%27round%27+stroke-miterlimit%3D%2710%27+d%3D%27M4+7h22M4+15h22M4+23h22%27%2F%3E%3C%2Fsvg%3E"); $navbar-dark-toggler-icon-bg: url("data%3Aimage%2Fsvg+xml%3Bcharset%3Dutf8%2C%3Csvg+viewBox%3D%270+0+30+30%27+xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3Cpath+stroke%3D%27#{$navbar-dark-color}%27+stroke-width%3D%272%27+stroke-linecap%3D%27round%27+stroke-miterlimit%3D%2710%27+d%3D%27M4+7h22M4+15h22M4+23h22%27%2F%3E%3C%2Fsvg%3E");
$navbar-light-toggler-icon-bg: url("data%3Aimage%2Fsvg+xml%3Bcharset%3Dutf8%2C%3Csvg+viewBox%3D%270+0+30+30%27+xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3Cpath+stroke%3D%27#{$navbar-light-color}%27+stroke-width%3D%272%27+stroke-linecap%3D%27round%27+stroke-miterlimit%3D%2710%27+d%3D%27M4+7h22M4+15h22M4+23h22%27%2F%3E%3C%2Fsvg%3E"); $navbar-light-toggler-icon-bg: url("data%3Aimage%2Fsvg+xml%3Bcharset%3Dutf8%2C%3Csvg+viewBox%3D%270+0+30+30%27+xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3Cpath+stroke%3D%27#{$navbar-light-color}%27+stroke-width%3D%272%27+stroke-linecap%3D%27round%27+stroke-miterlimit%3D%2710%27+d%3D%27M4+7h22M4+15h22M4+23h22%27%2F%3E%3C%2Fsvg%3E");
$dropdown-border-radius: 0px;
$enable-shadows: true !default; $enable-shadows: true !default;

View File

@@ -15,5 +15,7 @@ $sidebar-z-index: 20;
$header-logo-height: 80px; $header-logo-height: 80px;
$admin-sidebar-dark: #0a1118; $admin-sidebar-bg: darken($dark, 17%);
$admin-sidebar-active-bg: darken($dark, 3%);
$admin-sidebar-header-bg: darken($dark, 7%);
$admin-sidebar-width: 250px; $admin-sidebar-width: 250px;

View File

@@ -6,4 +6,5 @@
mdMin: map-get($grid-breakpoints, md); mdMin: map-get($grid-breakpoints, md);
lgMin: map-get($grid-breakpoints, lg); lgMin: map-get($grid-breakpoints, lg);
smMin: map-get($grid-breakpoints, sm); smMin: map-get($grid-breakpoints, sm);
adminSidebarActiveBg: $admin-sidebar-active-bg;
} }