mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-10 03:23:07 +00:00
sidebar animations
This commit is contained in:
@@ -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": {
|
||||||
|
@@ -0,0 +1 @@
|
|||||||
|
@import '../../../../styles/variables.scss';
|
@@ -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>
|
||||||
|
@@ -16,30 +16,9 @@
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.section-header-text, .fa-chevron-right {
|
|
||||||
display: none;
|
|
||||||
padding-left: $spacer/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-nav {
|
|
||||||
> li, > a {
|
|
||||||
padding: $spacer/2 $spacer;
|
|
||||||
&.active {
|
|
||||||
background-color: $admin-sidebar-dark;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-sub-level-items {
|
|
||||||
list-style: disc;
|
|
||||||
color: $navbar-dark-color;
|
|
||||||
}
|
|
||||||
.fa-xxs {
|
|
||||||
font-size: 0.5rem;
|
|
||||||
line-height: 3;
|
|
||||||
}
|
|
||||||
.admin-menu-header {
|
.admin-menu-header {
|
||||||
background-color: $admin-sidebar-dark;
|
background-color: $admin-sidebar-header-bg;
|
||||||
.logo-wrapper {
|
.logo-wrapper {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -54,12 +33,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
::ng-deep {
|
||||||
|
|
||||||
|
.navbar-nav {
|
||||||
|
.sidebar-section {
|
||||||
|
padding: $spacer;
|
||||||
|
}
|
||||||
|
.section-header-text {
|
||||||
|
display: none;
|
||||||
|
padding-left: $spacer/2;
|
||||||
|
}
|
||||||
|
#sidebar-collapse-toggle {
|
||||||
|
border-top: 2px solid rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
&.active {
|
&.active {
|
||||||
|
::ng-deep {
|
||||||
.section-header-text, .fa-chevron-right {
|
.section-header-text, .fa-chevron-right {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
55
src/app/+admin/admin-sidebar/admin-sidebar.service.ts
Normal file
55
src/app/+admin/admin-sidebar/admin-sidebar.service.ts
Normal 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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -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;
|
||||||
|
}
|
@@ -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>
|
@@ -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
|
||||||
|
@@ -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,
|
||||||
|
@@ -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()"
|
||||||
|
@@ -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
|
||||||
|
@@ -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 **/
|
||||||
|
26
src/app/shared/animations/bgColor.ts
Normal file
26
src/app/shared/animations/bgColor.ts
Normal 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'),
|
||||||
|
|
||||||
|
]
|
||||||
|
))
|
||||||
|
]);
|
@@ -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')
|
||||||
|
])
|
||||||
|
|
||||||
|
]);
|
@@ -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'),
|
||||||
|
|
||||||
|
]
|
||||||
|
))
|
||||||
]);
|
]);
|
||||||
|
@@ -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>
|
||||||
|
|
||||||
|
@@ -16,7 +16,7 @@ $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,
|
||||||
@@ -35,6 +35,5 @@ $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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
Reference in New Issue
Block a user