aboutsummaryrefslogtreecommitdiffstats
path: root/webapp/src/app/@theme/components
diff options
context:
space:
mode:
Diffstat (limited to 'webapp/src/app/@theme/components')
-rw-r--r--webapp/src/app/@theme/components/footer/footer.component.scss30
-rw-r--r--webapp/src/app/@theme/components/footer/footer.component.ts23
-rw-r--r--webapp/src/app/@theme/components/header/header.component.html32
-rw-r--r--webapp/src/app/@theme/components/header/header.component.scss115
-rw-r--r--webapp/src/app/@theme/components/header/header.component.ts51
-rw-r--r--webapp/src/app/@theme/components/index.ts6
-rw-r--r--webapp/src/app/@theme/components/search-input/search-input.component.scss33
-rw-r--r--webapp/src/app/@theme/components/search-input/search-input.component.ts35
-rw-r--r--webapp/src/app/@theme/components/theme-settings/theme-settings.component.scss36
-rw-r--r--webapp/src/app/@theme/components/theme-settings/theme-settings.component.ts65
-rw-r--r--webapp/src/app/@theme/components/theme-switcher/theme-switcher.component.scss101
-rw-r--r--webapp/src/app/@theme/components/theme-switcher/theme-switcher.component.ts48
-rw-r--r--webapp/src/app/@theme/components/tiny-mce/tiny-mce.component.ts33
13 files changed, 608 insertions, 0 deletions
diff --git a/webapp/src/app/@theme/components/footer/footer.component.scss b/webapp/src/app/@theme/components/footer/footer.component.scss
new file mode 100644
index 0000000..78d8114
--- /dev/null
+++ b/webapp/src/app/@theme/components/footer/footer.component.scss
@@ -0,0 +1,30 @@
+@import '../../styles/themes';
+@import '~@nebular/theme/styles/global/bootstrap/breakpoints';
+@import '~bootstrap/scss/mixins/breakpoints';
+
+@include nb-install-component() {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ .socials {
+ font-size: 2rem;
+
+ a {
+ padding: 0.4rem;
+ color: nb-theme(color-fg);
+ transition: color ease-out 0.1s;
+
+ &:hover {
+ color: nb-theme(color-fg-heading);
+ }
+ }
+ }
+
+ @include media-breakpoint-down(is) {
+ .socials {
+ font-size: 1.5rem;
+ }
+ }
+}
diff --git a/webapp/src/app/@theme/components/footer/footer.component.ts b/webapp/src/app/@theme/components/footer/footer.component.ts
new file mode 100644
index 0000000..8e1e825
--- /dev/null
+++ b/webapp/src/app/@theme/components/footer/footer.component.ts
@@ -0,0 +1,23 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'ngx-footer',
+ styleUrls: ['./footer.component.scss'],
+ template: `
+ <span class="created-by">Created by
+ <b><a href="http://iot.bzh" target="_blank">IoT.bzh</a></b> 2017
+ &nbsp;&nbsp;
+ <span style="font-size: small;">(powered by <a href="https://github.com/akveo/ngx-admin" target="_blank">akveo/ngx-admin</a>)</span>
+ </span>
+ <!-- MODS_XDS
+ <div class="socials">
+ <a href="#" target="_blank" class="ion ion-social-github"></a>
+ <a href="#" target="_blank" class="ion ion-social-facebook"></a>
+ <a href="#" target="_blank" class="ion ion-social-twitter"></a>
+ <a href="#" target="_blank" class="ion ion-social-linkedin"></a>
+ </div>
+ -->
+ `,
+})
+export class FooterComponent {
+}
diff --git a/webapp/src/app/@theme/components/header/header.component.html b/webapp/src/app/@theme/components/header/header.component.html
new file mode 100644
index 0000000..5d5eff6
--- /dev/null
+++ b/webapp/src/app/@theme/components/header/header.component.html
@@ -0,0 +1,32 @@
+<div class="header-container"
+ [class.left]="position === 'normal'"
+ [class.right]="position === 'inverse'">
+ <div class="logo-containter">
+ <a (click)="toggleSidebar()" href="#" class="navigation"><i class="nb-menu"></i></a>
+<!-- MODS_XDS
+ <div class="logo" (click)="goToHome()">ngx-<span>admin</span></div>
+-->
+ <div class="logo" (click)="goToHome()">XDS <span>dashboard</span></div>
+ </div>
+<!-- MODS_XDS
+ <ngx-theme-switcher></ngx-theme-switcher>
+-->
+</div>
+
+<nb-actions
+ size="medium"
+ class="header-container"
+ [class.right]="position === 'normal'"
+ [class.left]="position === 'inverse'">
+ <nb-action icon="nb-grid-b" class="toggle-layout" (click)="toggleSettings()"></nb-action>
+ <nb-action>
+ <nb-user [menu]="userMenu" [name]="user?.name" [picture]="user?.picture"></nb-user>
+ </nb-action>
+ <nb-action class="control-item" disabled icon="nb-notifications"></nb-action>
+<!-- MODS_XDS
+ <nb-action class="control-item" icon="nb-email"></nb-action>
+-->
+ <nb-action class="control-item">
+ <nb-search type="rotate-layout" (click)="startSearch()"></nb-search>
+ </nb-action>
+</nb-actions>
diff --git a/webapp/src/app/@theme/components/header/header.component.scss b/webapp/src/app/@theme/components/header/header.component.scss
new file mode 100644
index 0000000..647311b
--- /dev/null
+++ b/webapp/src/app/@theme/components/header/header.component.scss
@@ -0,0 +1,115 @@
+@import '../../styles/themes';
+@import '~bootstrap/scss/mixins/breakpoints';
+@import '~@nebular/theme/styles/global/bootstrap/breakpoints';
+
+@include nb-install-component() {
+ display: flex;
+ justify-content: space-between;
+ width: 100%;
+
+ .left {
+ display: flex;
+ width: 100%;
+ order: 0;
+ flex-direction: row;
+ }
+ .right {
+ order: 1;
+ flex-direction: row-reverse;
+ }
+
+ .logo-containter {
+ display: flex;
+ align-items: center;
+ }
+
+ .control-item {
+ display: block;
+ }
+
+ .header-container {
+ display: flex;
+ align-items: center;
+ width: 100%;
+
+ .navigation {
+ padding-right: nb-theme(padding);
+ font-size: 2.5rem;
+ text-decoration: none;
+
+ i {
+ display: block;
+ }
+
+ }
+
+ .logo {
+ padding: 0 nb-theme(padding);
+ font-size: 1.75rem;
+ font-weight: nb-theme(font-weight-bolder);
+ border-left: 1px solid nb-theme(separator);
+ white-space: nowrap;
+
+ span {
+ font-weight: nb-theme(font-weight-normal);
+ }
+ }
+ }
+
+ .toggle-layout /deep/ a {
+ display: block;
+ text-decoration: none;
+ line-height: 1;
+
+ i {
+ color: nb-theme(color-fg-highlight);
+ font-size: 2.25rem;
+ }
+ }
+
+ @include media-breakpoint-down(md) {
+
+ nb-action:not(.toggle-layout) {
+ border: none;
+ }
+
+ .control-item {
+ display: none;
+ }
+
+ .toggle-layout {
+ padding: 0;
+ }
+ }
+
+ @include media-breakpoint-down(sm) {
+
+ nb-user /deep/ .user-name {
+ display: none;
+ }
+ }
+
+ @include media-breakpoint-down(is) {
+
+ .header-container {
+ .logo {
+ font-size: 1.25rem;
+ }
+ }
+
+ .toggle-layout {
+ display: none;
+ }
+
+ nb-action:not(.toggle-layout) {
+ padding: 0;
+ }
+ }
+
+ @include media-breakpoint-down(xs) {
+ .right /deep/ {
+ display: none;
+ }
+ }
+}
+
diff --git a/webapp/src/app/@theme/components/header/header.component.ts b/webapp/src/app/@theme/components/header/header.component.ts
new file mode 100644
index 0000000..e2a84cb
--- /dev/null
+++ b/webapp/src/app/@theme/components/header/header.component.ts
@@ -0,0 +1,51 @@
+import { Component, Input, OnInit } from '@angular/core';
+
+import { NbMenuService, NbSidebarService } from '@nebular/theme';
+// XDS_MODS
+import { UserService } from '../../../@core-xds/services/users.service';
+import { AnalyticsService } from '../../../@core/utils/analytics.service';
+
+@Component({
+ selector: 'ngx-header',
+ styleUrls: ['./header.component.scss'],
+ templateUrl: './header.component.html',
+})
+export class HeaderComponent implements OnInit {
+
+
+ @Input() position = 'normal';
+
+ user: any;
+
+ userMenu = [{ title: 'Profile' }, { title: 'Log out' }];
+
+ constructor(private sidebarService: NbSidebarService,
+ private menuService: NbMenuService,
+ private userService: UserService,
+ private analyticsService: AnalyticsService) {
+ }
+
+ ngOnInit() {
+ // XDS_MODS
+ this.userService.getUsers()
+ .subscribe((users: any) => this.user = users.anonymous);
+ }
+
+ toggleSidebar(): boolean {
+ this.sidebarService.toggle(true, 'menu-sidebar');
+ return false;
+ }
+
+ toggleSettings(): boolean {
+ this.sidebarService.toggle(false, 'settings-sidebar');
+ return false;
+ }
+
+ goToHome() {
+ this.menuService.navigateHome();
+ }
+
+ startSearch() {
+ this.analyticsService.trackEvent('startSearch');
+ }
+}
diff --git a/webapp/src/app/@theme/components/index.ts b/webapp/src/app/@theme/components/index.ts
new file mode 100644
index 0000000..4a25efe
--- /dev/null
+++ b/webapp/src/app/@theme/components/index.ts
@@ -0,0 +1,6 @@
+export * from './header/header.component';
+export * from './footer/footer.component';
+export * from './search-input/search-input.component';
+// XDS_MODS export * from './tiny-mce/tiny-mce.component';
+export * from './theme-settings/theme-settings.component';
+export * from './theme-switcher/theme-switcher.component';
diff --git a/webapp/src/app/@theme/components/search-input/search-input.component.scss b/webapp/src/app/@theme/components/search-input/search-input.component.scss
new file mode 100644
index 0000000..5ef07ef
--- /dev/null
+++ b/webapp/src/app/@theme/components/search-input/search-input.component.scss
@@ -0,0 +1,33 @@
+:host {
+ display: flex;
+ align-items: center;
+
+ i.control-icon {
+ &::before {
+ font-size: 2.3rem;
+ }
+
+ &:hover {
+ cursor: pointer;
+ }
+ }
+
+ input {
+ border: none;
+ outline: none;
+ margin-left: 1rem;
+ width: 15rem;
+ transition: width 0.2s ease;
+
+ &.hidden {
+ width: 0;
+ margin: 0;
+ }
+ }
+
+ /deep/ search-input {
+ input {
+ background: transparent;
+ }
+ }
+}
diff --git a/webapp/src/app/@theme/components/search-input/search-input.component.ts b/webapp/src/app/@theme/components/search-input/search-input.component.ts
new file mode 100644
index 0000000..d9f0f10
--- /dev/null
+++ b/webapp/src/app/@theme/components/search-input/search-input.component.ts
@@ -0,0 +1,35 @@
+import { Component, ElementRef, EventEmitter, Output, ViewChild } from '@angular/core';
+
+@Component({
+ selector: 'ngx-search-input',
+ styleUrls: ['./search-input.component.scss'],
+ template: `
+ <i class="control-icon ion ion-ios-search"
+ (click)="showInput()"></i>
+ <input placeholder="Type your search request here..."
+ #input
+ [class.hidden]="!isInputShown"
+ (blur)="hideInput()"
+ (input)="onInput($event)">
+ `,
+})
+export class SearchInputComponent {
+ @ViewChild('input') input: ElementRef;
+
+ @Output() search: EventEmitter<string> = new EventEmitter<string>();
+
+ isInputShown = false;
+
+ showInput() {
+ this.isInputShown = true;
+ this.input.nativeElement.focus();
+ }
+
+ hideInput() {
+ this.isInputShown = false;
+ }
+
+ onInput(val: string) {
+ this.search.emit(val);
+ }
+}
diff --git a/webapp/src/app/@theme/components/theme-settings/theme-settings.component.scss b/webapp/src/app/@theme/components/theme-settings/theme-settings.component.scss
new file mode 100644
index 0000000..4a0a93e
--- /dev/null
+++ b/webapp/src/app/@theme/components/theme-settings/theme-settings.component.scss
@@ -0,0 +1,36 @@
+@import '../../styles/themes';
+
+@include nb-install-component() {
+ h6 {
+ margin-bottom: 0.5rem;
+ }
+
+ .settings-row {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ flex-wrap: wrap;
+
+ width: 90%;
+ margin: 0 0 1rem;
+
+ a {
+ text-decoration: none;
+ font-size: 2.25rem;
+
+ color: nb-theme(color-fg);
+
+ &.selected {
+ color: nb-theme(color-success);
+ }
+
+ @include nb-for-theme(cosmic) {
+ &.selected {
+ color: nb-theme(link-color);
+ }
+ }
+ }
+ }
+}
+
diff --git a/webapp/src/app/@theme/components/theme-settings/theme-settings.component.ts b/webapp/src/app/@theme/components/theme-settings/theme-settings.component.ts
new file mode 100644
index 0000000..9cd60fe
--- /dev/null
+++ b/webapp/src/app/@theme/components/theme-settings/theme-settings.component.ts
@@ -0,0 +1,65 @@
+import { Component, Input, OnInit } from '@angular/core';
+
+import { StateService } from '../../../@core/data/state.service';
+
+@Component({
+ selector: 'ngx-theme-settings',
+ styleUrls: ['./theme-settings.component.scss'],
+ template: `
+ <h6>LAYOUTS</h6>
+ <div class="settings-row">
+ <a *ngFor="let layout of layouts"
+ href="#"
+ [class.selected]="layout.selected"
+ [attr.title]="layout.name"
+ (click)="layoutSelect(layout)">
+ <i [attr.class]="layout.icon"></i>
+ </a>
+ </div>
+ <h6>SIDEBAR</h6>
+ <div class="settings-row">
+ <a *ngFor="let sidebar of sidebars"
+ href="#"
+ [class.selected]="sidebar.selected"
+ [attr.title]="sidebar.name"
+ (click)="sidebarSelect(sidebar)">
+ <i [attr.class]="sidebar.icon"></i>
+ </a>
+ </div>
+ `,
+})
+export class ThemeSettingsComponent {
+
+ layouts = [];
+ sidebars = [];
+
+ constructor(protected stateService: StateService) {
+ this.stateService.getLayoutStates()
+ .subscribe((layouts: any[]) => this.layouts = layouts);
+
+ this.stateService.getSidebarStates()
+ .subscribe((sidebars: any[]) => this.sidebars = sidebars);
+ }
+
+ layoutSelect(layout: any): boolean {
+ this.layouts = this.layouts.map((l: any) => {
+ l.selected = false;
+ return l;
+ });
+
+ layout.selected = true;
+ this.stateService.setLayoutState(layout);
+ return false;
+ }
+
+ sidebarSelect(sidebars: any): boolean {
+ this.sidebars = this.sidebars.map((s: any) => {
+ s.selected = false;
+ return s;
+ });
+
+ sidebars.selected = true;
+ this.stateService.setSidebarState(sidebars);
+ return false;
+ }
+}
diff --git a/webapp/src/app/@theme/components/theme-switcher/theme-switcher.component.scss b/webapp/src/app/@theme/components/theme-switcher/theme-switcher.component.scss
new file mode 100644
index 0000000..210add8
--- /dev/null
+++ b/webapp/src/app/@theme/components/theme-switcher/theme-switcher.component.scss
@@ -0,0 +1,101 @@
+@import '../../styles/themes';
+@import '~@nebular/theme/styles/global/bootstrap/hero-buttons';
+@import '~bootstrap/scss/mixins/breakpoints';
+@import '~@nebular/theme/styles/global/bootstrap/breakpoints';
+
+@include nb-install-component() {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 50%;
+
+ .theme-switch {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ cursor: pointer;
+ margin: 0;
+
+ & > span {
+ font-size: 1.125rem;
+ font-weight: nb-theme(font-weight-bold);
+ transition: opacity 0.3s ease;
+
+ &.light {
+ color: nb-theme(color-fg-text);
+ padding-right: 10px;
+ }
+
+ &.cosmic {
+ color: nb-theme(color-fg);
+ padding-left: 10px;
+ }
+
+ @include nb-for-theme(cosmic) {
+ &.light {
+ color: nb-theme(color-fg);
+ }
+
+ &.cosmic {
+ color: nb-theme(color-white);
+ }
+ }
+
+ &:active {
+ opacity: 0.78;
+ }
+ }
+ }
+
+ .switch {
+ position: relative;
+ display: inline-block;
+ width: 4rem;
+ height: 1.75rem;
+ margin: 0;
+
+ input {
+ display: none;
+
+ &:checked + .slider::before {
+ transform: translateX(2.25rem);
+ }
+ }
+
+ .slider {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ border-radius: 1.75rem;
+ background-color: nb-theme(layout-bg);
+ }
+
+ .slider::before {
+ position: absolute;
+ content: '';
+ height: 1.75rem;
+ width: 1.75rem;
+ border-radius: 50%;
+ background-color: nb-theme(color-success);
+ transition: 0.2s;
+
+ box-shadow: 0 0 0.25rem 0 rgba(nb-theme(color-fg), 0.4);
+
+ @include nb-for-theme(cosmic) {
+ @include btn-hero-primary-gradient();
+ }
+ }
+ }
+
+ @include media-breakpoint-down(is) {
+ .light, .cosmic {
+ display: none;
+ }
+ }
+
+ @include media-breakpoint-down(xs) {
+ align-items: flex-end;
+ }
+}
diff --git a/webapp/src/app/@theme/components/theme-switcher/theme-switcher.component.ts b/webapp/src/app/@theme/components/theme-switcher/theme-switcher.component.ts
new file mode 100644
index 0000000..e84b942
--- /dev/null
+++ b/webapp/src/app/@theme/components/theme-switcher/theme-switcher.component.ts
@@ -0,0 +1,48 @@
+import { Component, OnInit } from '@angular/core';
+import { NbThemeService } from '@nebular/theme';
+import { NbJSThemeOptions } from '@nebular/theme/services/js-themes/theme.options';
+import { AnalyticsService } from '../../../@core/utils/analytics.service';
+
+@Component({
+ selector: 'ngx-theme-switcher',
+ styleUrls: ['./theme-switcher.component.scss'],
+ template: `
+ <label class="theme-switch">
+ <span class="light">Light</span>
+ <div class="switch">
+ <input type="checkbox" [checked]="currentBoolTheme()" (change)="toggleTheme(theme.checked)" #theme>
+ <span class="slider"></span>
+ </div>
+ <span class="cosmic">Cosmic</span>
+ </label>
+ `,
+})
+export class ThemeSwitcherComponent implements OnInit {
+ theme: NbJSThemeOptions;
+
+ constructor(private themeService: NbThemeService, private analyticsService: AnalyticsService) {
+ }
+
+ ngOnInit() {
+ this.themeService.getJsTheme()
+ .subscribe((theme: NbJSThemeOptions) => this.theme = theme);
+ }
+
+ toggleTheme(theme: boolean) {
+ const boolTheme = this.boolToTheme(theme);
+ this.themeService.changeTheme(boolTheme);
+ this.analyticsService.trackEvent('switchTheme');
+ }
+
+ currentBoolTheme() {
+ return this.themeToBool(this.theme);
+ }
+
+ private themeToBool(theme: NbJSThemeOptions) {
+ return theme.name === 'cosmic';
+ }
+
+ private boolToTheme(theme: boolean) {
+ return theme ? 'cosmic' : 'default';
+ }
+}
diff --git a/webapp/src/app/@theme/components/tiny-mce/tiny-mce.component.ts b/webapp/src/app/@theme/components/tiny-mce/tiny-mce.component.ts
new file mode 100644
index 0000000..c54685b
--- /dev/null
+++ b/webapp/src/app/@theme/components/tiny-mce/tiny-mce.component.ts
@@ -0,0 +1,33 @@
+import { Component, OnDestroy, AfterViewInit, Output, EventEmitter, ElementRef } from '@angular/core';
+
+@Component({
+ selector: 'ngx-tiny-mce',
+ template: '',
+})
+export class TinyMCEComponent implements OnDestroy, AfterViewInit {
+
+ @Output() editorKeyup = new EventEmitter<any>();
+
+ editor: any;
+
+ constructor(private host: ElementRef) { }
+
+ ngAfterViewInit() {
+ tinymce.init({
+ target: this.host.nativeElement,
+ plugins: ['link', 'paste', 'table'],
+ skin_url: 'assets/skins/lightgray',
+ setup: editor => {
+ this.editor = editor;
+ editor.on('keyup', () => {
+ this.editorKeyup.emit(editor.getContent());
+ });
+ },
+ height: '320',
+ });
+ }
+
+ ngOnDestroy() {
+ tinymce.remove(this.editor);
+ }
+}