mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-10 11:33:04 +00:00
finished look of sidebar
This commit is contained in:
@@ -25,7 +25,7 @@
|
|||||||
"prebuild:prod": "yarn run prebuild",
|
"prebuild:prod": "yarn run prebuild",
|
||||||
"build": "webpack --progress --mode development",
|
"build": "webpack --progress --mode development",
|
||||||
"build:aot": "webpack --env.aot --env.server --mode development && webpack --env.aot --env.client --mode development",
|
"build:aot": "webpack --env.aot --env.server --mode development && webpack --env.aot --env.client --mode development",
|
||||||
"build:prod": "webpack --env.aot --env.server --env.production && webpack --env.aot --env.client --env.production",
|
"build:prod": "webpack --env.aot --env.server --mode production && webpack --env.aot --env.client --mode production",
|
||||||
"postbuild:prod": "yarn run rollup",
|
"postbuild:prod": "yarn run rollup",
|
||||||
"rollup": "rollup -c rollup.config.js",
|
"rollup": "rollup -c rollup.config.js",
|
||||||
"prestart": "yarn run build:prod",
|
"prestart": "yarn run build:prod",
|
||||||
|
@@ -12,6 +12,7 @@ import { type } from '../../shared/ngrx/type';
|
|||||||
*/
|
*/
|
||||||
export const AdminSidebarActionTypes = {
|
export const AdminSidebarActionTypes = {
|
||||||
SECTION_COLLAPSE: type('dspace/admin-sidebar/SECTION_COLLAPSE'),
|
SECTION_COLLAPSE: type('dspace/admin-sidebar/SECTION_COLLAPSE'),
|
||||||
|
SECTION_COLLAPSE_ALL: type('dspace/admin-sidebar/SECTION_COLLAPSE_ALL'),
|
||||||
SECTION_EXPAND: type('dspace/admin-sidebar/SECTION_EXPAND'),
|
SECTION_EXPAND: type('dspace/admin-sidebar/SECTION_EXPAND'),
|
||||||
SECTION_TOGGLE: type('dspace/admin-sidebar/SECTION_TOGGLE'),
|
SECTION_TOGGLE: type('dspace/admin-sidebar/SECTION_TOGGLE'),
|
||||||
COLLAPSE: type('dspace/admin-sidebar/COLLAPSE'),
|
COLLAPSE: type('dspace/admin-sidebar/COLLAPSE'),
|
||||||
@@ -73,6 +74,13 @@ export class AdminSidebarSectionCollapseAction extends AdminSidebarSectionAction
|
|||||||
type = AdminSidebarActionTypes.SECTION_COLLAPSE;
|
type = AdminSidebarActionTypes.SECTION_COLLAPSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to collapse a section
|
||||||
|
*/
|
||||||
|
export class AdminSidebarSectionCollapseAllAction extends AdminSidebarAction {
|
||||||
|
type = AdminSidebarActionTypes.SECTION_COLLAPSE_ALL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to expand a section
|
* Used to expand a section
|
||||||
*/
|
*/
|
||||||
|
@@ -1,13 +1,16 @@
|
|||||||
<nav class="navbar navbar-dark bg-dark p-0" [ngClass]="{'active': (sidebarCollapsed | async)}"
|
<nav class="navbar navbar-dark bg-dark p-0" [ngClass]="{'active': sidebarActive}"
|
||||||
[@slideSidebar]="{
|
[@slideSidebar]="{
|
||||||
value: ((sidebarCollapsed | async) ? 'collapsed' : 'expanded'),
|
value: ((sidebarCollapsed | async) ? 'collapsed' : 'expanded'),
|
||||||
params: {sidebarWidth: (sidebarWidth | async)}
|
params: {sidebarWidth: (sidebarWidth | async)}
|
||||||
}">
|
}" (@slideSidebar.done)="finishSlide($event)">
|
||||||
|
|
||||||
<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">
|
||||||
<a class="shortcuts-tree navbar-brand" href="#">
|
<a class="shortcuts-tree navbar-brand mr-0" href="#">
|
||||||
<img class="admin-logo mr-2" src="assets/images/dspace-logo-mini.svg">
|
<span class="logo-wrapper">
|
||||||
|
<img class="admin-logo" src="assets/images/dspace-logo-mini.svg">
|
||||||
|
</span>
|
||||||
<h4 class="section-header-text">Admin</h4>
|
<h4 class="section-header-text">Admin</h4>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -17,7 +20,7 @@
|
|||||||
<i class="fas fa-plus-circle fa-fw"></i>
|
<i class="fas fa-plus-circle fa-fw"></i>
|
||||||
<span class="section-header-text">New</span>
|
<span class="section-header-text">New</span>
|
||||||
<i class="fas fa-chevron-right fa-pull-right fa-xxs"
|
<i class="fas fa-chevron-right fa-pull-right fa-xxs"
|
||||||
[ngClass]="{'fa-rotate-90': (active('new') | async)}"></i>
|
[@rotateInOut]="(active('new') | async) ? 'rotateOut': 'rotateIn'"></i>
|
||||||
</a>
|
</a>
|
||||||
<ul class="sidebar-sub-level-items" [ngbCollapse]="!(active('new') | async)">
|
<ul class="sidebar-sub-level-items" [ngbCollapse]="!(active('new') | async)">
|
||||||
<li><a class="nav-item nav-link" href="#">Community</a></li>
|
<li><a class="nav-item nav-link" href="#">Community</a></li>
|
||||||
|
@@ -16,9 +16,9 @@
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.section-header-text, .fa-chevron-right {
|
||||||
.section-header-text {
|
display: none;
|
||||||
display: inline;
|
padding-left: $spacer/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-nav {
|
.navbar-nav {
|
||||||
@@ -27,11 +27,9 @@
|
|||||||
&.active {
|
&.active {
|
||||||
background-color: $admin-sidebar-dark;
|
background-color: $admin-sidebar-dark;
|
||||||
}
|
}
|
||||||
.fa-fw {
|
|
||||||
text-align: left;
|
|
||||||
width: 1.75em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-sub-level-items {
|
.sidebar-sub-level-items {
|
||||||
list-style: disc;
|
list-style: disc;
|
||||||
color: $navbar-dark-color;
|
color: $navbar-dark-color;
|
||||||
@@ -42,16 +40,25 @@
|
|||||||
}
|
}
|
||||||
.admin-menu-header {
|
.admin-menu-header {
|
||||||
background-color: $admin-sidebar-dark;
|
background-color: $admin-sidebar-dark;
|
||||||
img {
|
.logo-wrapper {
|
||||||
height: 1em;
|
text-align: center;
|
||||||
vertical-align: baseline;
|
display: inline-block;
|
||||||
|
width: 1.25em;
|
||||||
|
img {
|
||||||
|
height: 1em;
|
||||||
|
vertical-align: text-bottom;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
.section-header-text {
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
.section-header-text, .fa-chevron-right {
|
.section-header-text, .fa-chevron-right {
|
||||||
display: none;
|
display: inline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,10 +4,15 @@ import { MemoizedSelector, select, Store } from '@ngrx/store';
|
|||||||
import { AdminSidebarSectionState, AdminSidebarState, } from './admin-sidebar.reducer';
|
import { AdminSidebarSectionState, AdminSidebarState, } from './admin-sidebar.reducer';
|
||||||
import { hasValue } from '../../shared/empty.util';
|
import { hasValue } from '../../shared/empty.util';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { AdminSidebarSectionToggleAction, AdminSidebarToggleAction } from './admin-sidebar.actions';
|
import {
|
||||||
|
AdminSidebarSectionCollapseAllAction,
|
||||||
|
AdminSidebarSectionToggleAction,
|
||||||
|
AdminSidebarToggleAction
|
||||||
|
} from './admin-sidebar.actions';
|
||||||
import { AppState, keySelector } from '../../app.reducer';
|
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';
|
||||||
|
|
||||||
const sidebarSectionStateSelector = (state: AppState) => state.adminSidebar.sections;
|
const sidebarSectionStateSelector = (state: AppState) => state.adminSidebar.sections;
|
||||||
const sidebarStateSelector = (state) => state.adminSidebar;
|
const sidebarStateSelector = (state) => state.adminSidebar;
|
||||||
@@ -20,11 +25,12 @@ const sectionByNameSelector = (name: string): MemoizedSelector<AppState, AdminSi
|
|||||||
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]
|
animations: [slideSidebar, rotateInOut]
|
||||||
})
|
})
|
||||||
export class AdminSidebarComponent implements OnInit {
|
export class AdminSidebarComponent implements OnInit {
|
||||||
sidebarCollapsed: Observable<boolean>;
|
sidebarCollapsed: Observable<boolean>;
|
||||||
sidebarWidth: Observable<string>;
|
sidebarWidth: Observable<string>;
|
||||||
|
sidebarActive = true;
|
||||||
|
|
||||||
constructor(private store: Store<AdminSidebarState>,
|
constructor(private store: Store<AdminSidebarState>,
|
||||||
private variableService: CSSVariableService) {
|
private variableService: CSSVariableService) {
|
||||||
@@ -52,6 +58,21 @@ export class AdminSidebarComponent implements OnInit {
|
|||||||
|
|
||||||
toggle(event: Event) {
|
toggle(event: Event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
// Is sidebar closing?
|
||||||
|
if (this.sidebarActive) {
|
||||||
|
this.sidebarActive = false;
|
||||||
|
this.store.dispatch(new AdminSidebarSectionCollapseAllAction());
|
||||||
|
}
|
||||||
this.store.dispatch(new AdminSidebarToggleAction());
|
this.store.dispatch(new AdminSidebarToggleAction());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to change this.collapsed to false when the slide animation ends and is sliding open
|
||||||
|
* @param event The animation event
|
||||||
|
*/
|
||||||
|
finishSlide(event: any): void {
|
||||||
|
if (event.fromState === 'collapsed') {
|
||||||
|
this.sidebarActive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -59,6 +59,16 @@ export function adminSidebarReducer(state = initialState, action: AdminSidebarAc
|
|||||||
collapsed: !collapsed
|
collapsed: !collapsed
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
case AdminSidebarActionTypes.SECTION_COLLAPSE_ALL: {
|
||||||
|
const newSectionState: AdminSidebarSectionState = Object.create(null);
|
||||||
|
if (hasValue(state.sections)) {
|
||||||
|
Object.keys(state.sections).forEach((section) =>
|
||||||
|
newSectionState[section] = {
|
||||||
|
sectionCollapsed: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Object.assign({}, state, { sections: newSectionState });
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,10 @@ export const rotateLeave = transition('rotateIn => rotateOut', [
|
|||||||
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
|
||||||
]);
|
]);
|
||||||
|
@@ -2,7 +2,11 @@ import { Store, StoreModule } from '@ngrx/store';
|
|||||||
import { async, inject, TestBed } from '@angular/core/testing';
|
import { async, inject, TestBed } from '@angular/core/testing';
|
||||||
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
|
|
||||||
import { DynamicFormControlModel, DynamicInputModel } from '@ng-dynamic-forms/core';
|
import {
|
||||||
|
DynamicFormControlModel,
|
||||||
|
DynamicFormGroupModel,
|
||||||
|
DynamicInputModel
|
||||||
|
} from '@ng-dynamic-forms/core';
|
||||||
|
|
||||||
import { FormService } from './form.service';
|
import { FormService } from './form.service';
|
||||||
import { FormBuilderService } from './builder/form-builder.service';
|
import { FormBuilderService } from './builder/form-builder.service';
|
||||||
@@ -10,7 +14,7 @@ import { AppState } from '../../app.reducer';
|
|||||||
import { formReducer } from './form.reducer';
|
import { formReducer } from './form.reducer';
|
||||||
import { getMockFormBuilderService } from '../mocks/mock-form-builder-service';
|
import { getMockFormBuilderService } from '../mocks/mock-form-builder-service';
|
||||||
|
|
||||||
describe('FormService test suite', () => {
|
fdescribe('FormService test suite', () => {
|
||||||
const config = {
|
const config = {
|
||||||
form: {
|
form: {
|
||||||
validatorMap: {
|
validatorMap: {
|
||||||
@@ -37,30 +41,30 @@ describe('FormService test suite', () => {
|
|||||||
}),
|
}),
|
||||||
new DynamicInputModel({ id: 'date' }),
|
new DynamicInputModel({ id: 'date' }),
|
||||||
new DynamicInputModel({ id: 'description' }),
|
new DynamicInputModel({ id: 'description' }),
|
||||||
// new DynamicFormGroupModel({
|
new DynamicFormGroupModel({
|
||||||
//
|
|
||||||
// id: 'addressLocation',
|
id: 'addressLocation',
|
||||||
// group: [
|
group: [
|
||||||
// new DynamicInputModel({
|
new DynamicInputModel({
|
||||||
//
|
|
||||||
// id: 'zipCode',
|
id: 'zipCode',
|
||||||
// label: 'Zip Code',
|
label: 'Zip Code',
|
||||||
// placeholder: 'ZIP'
|
placeholder: 'ZIP'
|
||||||
// }),
|
}),
|
||||||
// new DynamicInputModel({
|
new DynamicInputModel({
|
||||||
//
|
|
||||||
// id: 'state',
|
id: 'state',
|
||||||
// label: 'State',
|
label: 'State',
|
||||||
// placeholder: 'State'
|
placeholder: 'State'
|
||||||
// }),
|
}),
|
||||||
// new DynamicInputModel({
|
new DynamicInputModel({
|
||||||
//
|
|
||||||
// id: 'city',
|
id: 'city',
|
||||||
// label: 'City',
|
label: 'City',
|
||||||
// placeholder: 'City'
|
placeholder: 'City'
|
||||||
// })
|
})
|
||||||
// ]
|
]
|
||||||
// }),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
let controls;
|
let controls;
|
||||||
|
@@ -19,7 +19,7 @@ describe('HostWindowService', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const _initialState = { hostWindow: { width: 1600, height: 770 } };
|
const _initialState = { hostWindow: { width: 1600, height: 770 } };
|
||||||
store = new Store<AppState>(observableOf(_initialState), undefined, undefined);
|
store = new Store<AppState>(observableOf(_initialState), undefined, undefined);
|
||||||
service = new HostWindowService(store);
|
service = new HostWindowService(store, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('isXs() should return false with width = 1600', () => {
|
it('isXs() should return false with width = 1600', () => {
|
||||||
@@ -55,7 +55,7 @@ describe('HostWindowService', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const _initialState = { hostWindow: { width: 1100, height: 770 } };
|
const _initialState = { hostWindow: { width: 1100, height: 770 } };
|
||||||
store = new Store<AppState>(observableOf(_initialState), undefined, undefined);
|
store = new Store<AppState>(observableOf(_initialState), undefined, undefined);
|
||||||
service = new HostWindowService(store);
|
service = new HostWindowService(store, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('isXs() should return false with width = 1100', () => {
|
it('isXs() should return false with width = 1100', () => {
|
||||||
@@ -91,7 +91,7 @@ describe('HostWindowService', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const _initialState = { hostWindow: { width: 800, height: 770 } };
|
const _initialState = { hostWindow: { width: 800, height: 770 } };
|
||||||
store = new Store<AppState>(observableOf(_initialState), undefined, undefined);
|
store = new Store<AppState>(observableOf(_initialState), undefined, undefined);
|
||||||
service = new HostWindowService(store);
|
service = new HostWindowService(store, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('isXs() should return false with width = 800', () => {
|
it('isXs() should return false with width = 800', () => {
|
||||||
@@ -127,7 +127,7 @@ describe('HostWindowService', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const _initialState = { hostWindow: { width: 600, height: 770 } };
|
const _initialState = { hostWindow: { width: 600, height: 770 } };
|
||||||
store = new Store<AppState>(observableOf(_initialState), undefined, undefined);
|
store = new Store<AppState>(observableOf(_initialState), undefined, undefined);
|
||||||
service = new HostWindowService(store);
|
service = new HostWindowService(store, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('isXs() should return false with width = 600', () => {
|
it('isXs() should return false with width = 600', () => {
|
||||||
@@ -163,7 +163,7 @@ describe('HostWindowService', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const _initialState = { hostWindow: { width: 400, height: 770 } };
|
const _initialState = { hostWindow: { width: 400, height: 770 } };
|
||||||
store = new Store<AppState>(observableOf(_initialState), undefined, undefined);
|
store = new Store<AppState>(observableOf(_initialState), undefined, undefined);
|
||||||
service = new HostWindowService(store);
|
service = new HostWindowService(store, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('isXs() should return true with width = 400', () => {
|
it('isXs() should return true with width = 400', () => {
|
||||||
@@ -197,7 +197,7 @@ describe('HostWindowService', () => {
|
|||||||
|
|
||||||
describe('widthCategory', () => {
|
describe('widthCategory', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
service = new HostWindowService({} as Store<AppState>);
|
service = new HostWindowService({} as Store<AppState>, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call getWithObs to get the current width', () => {
|
it('should call getWithObs to get the current width', () => {
|
||||||
|
@@ -27,7 +27,8 @@ module.exports = function(env, options) {
|
|||||||
getAotPlugin('client', !!env.aot)
|
getAotPlugin('client', !!env.aot)
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
if (env.production) {
|
console.log(options.mode);
|
||||||
|
if (options.mode === 'production') {
|
||||||
serverConfig = webpackMerge({}, serverConfig, prodPartial);
|
serverConfig = webpackMerge({}, serverConfig, prodPartial);
|
||||||
clientConfig = webpackMerge({}, clientConfig, prodPartial);
|
clientConfig = webpackMerge({}, clientConfig, prodPartial);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user