feat: add material
|
@ -197,7 +197,7 @@
|
|||
"styles": [
|
||||
"node_modules/bootstrap/dist/css/bootstrap.css",
|
||||
"node_modules/nebular-icons/scss/nebular-icons.scss",
|
||||
"node_modules/swiper/dist/css/swiper.min.css",
|
||||
"node_modules/swiper/css/swiper.min.css",
|
||||
"node_modules/highlight.js/styles/dracula.css",
|
||||
"docs/app/@theme/styles/styles.scss"
|
||||
]
|
||||
|
|
|
@ -29,8 +29,8 @@ export class CoreModule {
|
|||
throwIfAlreadyLoaded(parentModule, 'CoreModule');
|
||||
}
|
||||
|
||||
static forRoot(): ModuleWithProviders {
|
||||
return <ModuleWithProviders>{
|
||||
static forRoot(): ModuleWithProviders<CoreModule> {
|
||||
return {
|
||||
ngModule: CoreModule,
|
||||
providers: [
|
||||
...NB_CORE_PROVIDERS,
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
</div>
|
||||
<div class="section middle">
|
||||
<nb-menu [items]="headerMenu"></nb-menu>
|
||||
<ng-content></ng-content>
|
||||
<a routerLink="/" fragment="backend-bundles" class="backend-bundles eva-parent-hover">
|
||||
<i [innerHTML]="'gift-outline' | eva: { width: 24, height: 24, fill: '#ff4d6b', animationType: 'shake' }"></i>
|
||||
<span>Backend Bundles</span>
|
||||
|
|
|
@ -56,7 +56,8 @@ export class NgxStructureService {
|
|||
}
|
||||
|
||||
if (item.block === 'markdown') {
|
||||
item.children = this.textService.mdToSectionsHTML(require(`raw-loader!../../../articles/${item.source}`));
|
||||
item.children = this.textService.mdToSectionsHTML(
|
||||
require(`raw-loader!../../../articles/${item.source}`).default);
|
||||
}
|
||||
|
||||
if (item.children) {
|
||||
|
|
|
@ -25,7 +25,7 @@ $grid-breakpoints: (
|
|||
xxxl: 1600px
|
||||
);
|
||||
|
||||
$nb-enabled-themes: (ngx-landing, docs-page);
|
||||
$nb-enabled-themes: (ngx-landing, ngx-landing-material, docs-page);
|
||||
|
||||
/* stylelint-disable */
|
||||
$nb-themes: nb-register-theme((
|
||||
|
@ -127,6 +127,30 @@ $nb-themes: nb-register-theme((
|
|||
|
||||
), ngx-landing, corporate);
|
||||
|
||||
$nb-themes: nb-register-theme((
|
||||
font-family-primary: unquote('Roboto, sans-serif'),
|
||||
|
||||
shadow: unquote('0 2px 1px -1px rgba(0,0,0,.2), 0 1px 1px 0 rgba(0,0,0,.14), 0 1px 3px 0 rgba(0,0,0,.12)'),
|
||||
header-shadow: unquote(
|
||||
'0 3px 5px -1px rgba(0,0,0,.2), 0 6px 10px 0 rgba(0,0,0,.14), 0 1px 18px 0 rgba(0,0,0,.12)'
|
||||
),
|
||||
shadow-default: shadow,
|
||||
shadow-btn: shadow,
|
||||
shadow-hover-btn: shadow,
|
||||
shadow-active-btn: shadow,
|
||||
shadow-hover-green-btn: shadow,
|
||||
shadow-active-green-btn: shadow,
|
||||
|
||||
color-primary-default: #6200ee,
|
||||
color-active-fg: color-primary-default,
|
||||
color-active-bg: color-primary-default,
|
||||
header-background-color: color-primary-default,
|
||||
header-text-color: #ffffff !important,
|
||||
menu-text-color: #ffffff !important,
|
||||
footer-background-color: color-primary-default,
|
||||
footer-text-color: #ffffff !important
|
||||
), ngx-landing-material, ngx-landing);
|
||||
|
||||
/* stylelint-enable foo */
|
||||
$nb-themes: nb-register-theme((
|
||||
// custom
|
||||
|
|
|
@ -9,6 +9,17 @@ import { ModuleWithProviders, NgModule } from '@angular/core';
|
|||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { LazyLoadImageModule } from 'ng-lazyload-image';
|
||||
import {
|
||||
NbLayoutModule,
|
||||
NbThemeModule,
|
||||
NbMenuModule,
|
||||
NbCheckboxModule,
|
||||
NbCardModule,
|
||||
NbSidebarModule,
|
||||
NbTabsetModule,
|
||||
} from '@nebular/theme';
|
||||
|
||||
import { LandingSharedModule } from '../shared/landing-shared.module';
|
||||
|
||||
// components
|
||||
import {
|
||||
|
@ -26,21 +37,6 @@ import {
|
|||
import { ngxLandingServices } from './services';
|
||||
// services
|
||||
|
||||
// pipes
|
||||
import { EvaIconsPipe } from './pipes/eva-icons.pipe';
|
||||
import { CapitalizePipe } from './pipes/capitalize.pipe';
|
||||
// pipes
|
||||
|
||||
import {
|
||||
NbLayoutModule,
|
||||
NbThemeModule,
|
||||
NbMenuModule,
|
||||
NbCheckboxModule,
|
||||
NbCardModule,
|
||||
NbSidebarModule,
|
||||
NbTabsetModule,
|
||||
} from '@nebular/theme';
|
||||
|
||||
const BASE_MODULES = [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
|
@ -67,14 +63,10 @@ const COMPONENTS = [
|
|||
NgxDocsFooterComponent,
|
||||
];
|
||||
|
||||
const PIPES = [
|
||||
EvaIconsPipe,
|
||||
CapitalizePipe,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule,
|
||||
LandingSharedModule,
|
||||
|
||||
...BASE_MODULES,
|
||||
|
||||
|
@ -82,8 +74,6 @@ const PIPES = [
|
|||
],
|
||||
declarations: [
|
||||
...COMPONENTS,
|
||||
|
||||
...PIPES,
|
||||
],
|
||||
exports: [
|
||||
RouterModule,
|
||||
|
@ -93,15 +83,11 @@ const PIPES = [
|
|||
...NB_MODULES,
|
||||
|
||||
...COMPONENTS,
|
||||
|
||||
...PIPES,
|
||||
],
|
||||
entryComponents: [
|
||||
],
|
||||
})
|
||||
export class NgxLandingThemeModule {
|
||||
static forRoot(): ModuleWithProviders {
|
||||
return <ModuleWithProviders>{
|
||||
static forRoot(): ModuleWithProviders<NgxLandingThemeModule> {
|
||||
return {
|
||||
ngModule: NgxLandingThemeModule,
|
||||
providers: [
|
||||
...NbThemeModule.forRoot({ name: 'ngx-landing' }).providers,
|
||||
|
|
|
@ -13,6 +13,7 @@ import { NgxLandingThemeModule } from './@theme/theme.module';
|
|||
import { CoreModule } from './@core/core.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { LandingSharedModule } from './shared/landing-shared.module';
|
||||
|
||||
import { DOCS, STRUCTURE } from './app.options';
|
||||
const docs = require('../output.json');
|
||||
|
@ -28,6 +29,7 @@ import { structure } from '../structure';
|
|||
HttpClientModule,
|
||||
AppRoutingModule,
|
||||
|
||||
LandingSharedModule,
|
||||
NgxLandingThemeModule.forRoot(),
|
||||
CoreModule.forRoot(),
|
||||
],
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<nb-layout>
|
||||
<nb-layout-header fixed>
|
||||
<div class="content-center">
|
||||
<ngx-landing-header class="docs-header" [sidebarTag]="sidebarTag" [isDocs]="true"></ngx-landing-header>
|
||||
<ngx-landing-header class="docs-header" [sidebarTag]="sidebarTag" [isDocs]="true">
|
||||
<ngx-material-theme-link></ngx-material-theme-link>
|
||||
</ngx-landing-header>
|
||||
</div>
|
||||
</nb-layout-header>
|
||||
<nb-sidebar class="menu-sidebar" [tag]="sidebarTag" [responsive]="true" [compactedBreakpoints]="[]" [collapsedBreakpoints]="collapsedBreakpoints">
|
||||
|
|
|
@ -11,6 +11,7 @@ import { NgxLandingThemeModule } from '../../@theme/theme.module';
|
|||
import { SwiperModule } from 'ngx-swiper-wrapper';
|
||||
import { NgxBlocksModule } from '../../blocks/blocks.module';
|
||||
import { LandingDocsRoutingModule } from './landing-docs-routing.module';
|
||||
import { LandingSharedModule } from '../../shared/landing-shared.module';
|
||||
// modules
|
||||
|
||||
// components
|
||||
|
@ -32,6 +33,7 @@ const COMPONENTS = [
|
|||
imports: [
|
||||
NgxLandingThemeModule,
|
||||
SwiperModule,
|
||||
LandingSharedModule,
|
||||
LandingDocsRoutingModule,
|
||||
NgxBlocksModule,
|
||||
],
|
||||
|
|
6
docs/app/pages/home/contact-form/contact.component.html
Normal file
|
@ -0,0 +1,6 @@
|
|||
<div class="contact">
|
||||
<h1>Need customization?</h1>
|
||||
<p>Thinking of building something outstanding based on ngx-admin or just need some Angular/React experts?</p>
|
||||
<a class="btn btn-demo" href="https://hubs.ly/H0nJf_b0"
|
||||
target="_blank">Contact us</a>
|
||||
</div>
|
53
docs/app/pages/home/contact-form/contact.component.scss
Normal file
|
@ -0,0 +1,53 @@
|
|||
@import '../../../@theme/styles/themes';
|
||||
@import '~@nebular/theme/styles/global/breakpoints';
|
||||
|
||||
@include nb-install-component() {
|
||||
$color-active: nb-theme(color-active-fg);
|
||||
|
||||
.contact {
|
||||
text-align: center;
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: 'Helvetica Neue Bold', sans-serif;
|
||||
font-size: 2.5rem;
|
||||
color: $color-active;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
font-family: unquote('"Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'), sans-serif;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.5;
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.btn {
|
||||
font-family: nb-theme(font-main), sans-serif;
|
||||
border-radius: 3px;
|
||||
border: none;
|
||||
background: #ffffff;
|
||||
color: #000000;
|
||||
box-shadow: nb-theme(shadow-default);
|
||||
cursor: pointer;
|
||||
text-transform: uppercase;
|
||||
|
||||
&.btn-demo {
|
||||
margin-top: 0.375rem;
|
||||
padding: 1.125rem 6.25rem;
|
||||
color: #ffffff;
|
||||
background-color: nb-theme(color-active-fg);
|
||||
box-shadow: nb-theme(shadow-btn);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: nb-theme(shadow-hover-green-btn);
|
||||
}
|
||||
|
||||
&:active {
|
||||
box-shadow: nb-theme(shadow-active-green-btn);
|
||||
}
|
||||
}
|
||||
}
|
13
docs/app/pages/home/contact-form/contact.component.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-contact-form',
|
||||
templateUrl: './contact.component.html',
|
||||
styleUrls: ['./contact.component.scss'],
|
||||
})
|
||||
export class ContactFormComponent {
|
||||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { LandingHomeComponent } from './landing-home.component';
|
||||
import { MaterialLandingComponent } from './material-landing/material-landing.component';
|
||||
|
||||
|
||||
export const routes: Routes = [
|
||||
|
@ -14,6 +15,14 @@ export const routes: Routes = [
|
|||
path: '',
|
||||
component: LandingHomeComponent,
|
||||
},
|
||||
{
|
||||
path: 'material',
|
||||
component: MaterialLandingComponent,
|
||||
},
|
||||
// {
|
||||
// path: 'overview',
|
||||
// component: OverviewComponent,
|
||||
// },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<nb-layout>
|
||||
<nb-layout-header fixed>
|
||||
<ngx-landing-header></ngx-landing-header>
|
||||
<ngx-landing-header>
|
||||
<ngx-material-theme-link withPopover></ngx-material-theme-link>
|
||||
</ngx-landing-header>
|
||||
</nb-layout-header>
|
||||
|
||||
<nb-layout-column>
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
::ng-deep nb-layout-header {
|
||||
box-shadow: nb-theme(shadow-default);
|
||||
background: nb-theme(header-bg);
|
||||
nav {
|
||||
ngx-landing-header {
|
||||
max-width: calc(#{$content-width} - 8.125rem * 2);
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
@ -48,9 +48,9 @@
|
|||
background-color: nb-theme(color-white);
|
||||
box-shadow: nb-theme(shadow-default);
|
||||
|
||||
nav {
|
||||
ngx-landing-footer {
|
||||
max-width: $content-width;
|
||||
width: 100%;
|
||||
justify-content: space-evenly;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,14 +26,24 @@ import { NgxLandingSectionsContainerComponent } from './sections-container/ngx-l
|
|||
import { BackendBundlesSectionComponent } from './backend-bundles-section/backend-bundles-section.component';
|
||||
import { LicensePipe } from './backend-bundles-section/license.pipe';
|
||||
import { BackgroundImagePipe } from './backend-bundles-section/background-image.pipe';
|
||||
import { MaterialLandingComponent } from './material-landing/material-landing.component';
|
||||
import { LandingSharedModule } from '../../shared/landing-shared.module';
|
||||
import {MaterialFeaturesSectionComponent} from './material-features/material-features.component';
|
||||
import {DefaultAdminInfoComponent} from './main-info-section/default-admin-main-info/default-info.component';
|
||||
import {MaterialAdminInfoComponent} from './main-info-section/material-admin-main-info/material-info.component';
|
||||
import {ContactFormComponent} from './contact-form/contact.component';
|
||||
import {NbButtonModule} from '@nebular/theme';
|
||||
// components
|
||||
|
||||
const PIPES = [LicensePipe, BackgroundImagePipe];
|
||||
|
||||
const COMPONENTS = [
|
||||
LandingHomeComponent,
|
||||
MaterialLandingComponent,
|
||||
NgxLandingSectionsContainerComponent,
|
||||
MainInfoSectionComponent,
|
||||
DefaultAdminInfoComponent,
|
||||
MaterialAdminInfoComponent,
|
||||
DescriptionSectionComponent,
|
||||
ReasonSectionComponent,
|
||||
ThemeSectionComponent,
|
||||
|
@ -42,6 +52,8 @@ const COMPONENTS = [
|
|||
SocialSectionComponent,
|
||||
ContactSectionComponent,
|
||||
BackendBundlesSectionComponent,
|
||||
MaterialFeaturesSectionComponent,
|
||||
ContactFormComponent,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@ -53,6 +65,8 @@ const COMPONENTS = [
|
|||
NgxLandingThemeModule,
|
||||
SwiperModule,
|
||||
LandingHomeRoutingModule,
|
||||
LandingSharedModule,
|
||||
NbButtonModule,
|
||||
],
|
||||
providers: [
|
||||
...PIPES,
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<div>
|
||||
<h1>ngx-admin</h1>
|
||||
<p class="description">
|
||||
The most popular admin dashboard based on <strong>Angular 9+</strong> and
|
||||
<a href="https://hubs.ly/H0n5N9P0" target="_blank">Nebular</a> with
|
||||
<a href="https://hubs.ly/H0n5PKH0">Eva Design System</a> support.
|
||||
Free and Open Source for personal and commercial purposes.
|
||||
<br>
|
||||
<span class="bundles">
|
||||
Never start from scratch again.
|
||||
<a href="https://hubs.ly/H0n5NVz0" target="_blank">
|
||||
Integrate ready-made solution: ngx-admin with backend.
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
|
@ -0,0 +1,9 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-default-admin-info',
|
||||
templateUrl: './default-info.component.html',
|
||||
styleUrls: ['./../main-info-section.component.scss'],
|
||||
})
|
||||
export class DefaultAdminInfoComponent {
|
||||
}
|
|
@ -5,24 +5,18 @@
|
|||
<img *ngIf="breakpoint.width >= breakpoints.md"
|
||||
class="main-img"
|
||||
defaultImage="assets/img/default.png"
|
||||
lazyLoad="assets/img/ngx-admin.png"/>
|
||||
[lazyLoad]="imageUrl"/>
|
||||
</a>
|
||||
</div>
|
||||
<div class="main-inf">
|
||||
<h1>ngx-admin</h1>
|
||||
<p class="description">
|
||||
The most popular admin dashboard based on <strong>Angular 8+</strong>, Bootstrap 4+ and
|
||||
<a href="https://hubs.ly/H0n5N9P0" target="_blank">Nebular</a> with
|
||||
<a href="https://hubs.ly/H0n5PKH0">Eva Design System</a> support.
|
||||
Free and Open Source for personal and commercial purposes.
|
||||
<br>
|
||||
<span class="bundles">
|
||||
Never start from scratch again.
|
||||
<a href="https://hubs.ly/H0n5NVz0" target="_blank">
|
||||
Integrate ready-made solution: ngx-admin with backend.
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
<ng-container *ngIf="forMaterialTheme === false">
|
||||
<ngx-default-admin-info></ngx-default-admin-info>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="forMaterialTheme !== false">
|
||||
<ngx-material-admin-info></ngx-material-admin-info>
|
||||
</ng-container>
|
||||
|
||||
<div class="mobile-main-img-container">
|
||||
<img *ngIf="breakpoint.width <= breakpoints.sm" class="main-img" lazyLoad="assets/img/corporate-theme.png" alt="Light theme Dashboard"/>
|
||||
</div>
|
||||
|
@ -42,3 +36,4 @@
|
|||
target="_blank">Demo</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -70,6 +70,11 @@
|
|||
margin: 4.625rem 9% 0 6%;
|
||||
}
|
||||
|
||||
ngx-default-admin-info,
|
||||
ngx-material-admin-info {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: 'Helvetica Neue Bold', sans-serif;
|
||||
font-size: 4rem;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import { Component, OnDestroy } from '@angular/core';
|
||||
import { Component, OnDestroy, Input } from '@angular/core';
|
||||
import { NbMediaBreakpoint, NbMediaBreakpointsService, NbThemeService } from '@nebular/theme';
|
||||
import { takeWhile } from 'rxjs/operators';
|
||||
|
||||
|
@ -14,24 +14,31 @@ import { takeWhile } from 'rxjs/operators';
|
|||
styleUrls: ['./main-info-section.component.scss'],
|
||||
})
|
||||
export class MainInfoSectionComponent implements OnDestroy {
|
||||
|
||||
private alive = true;
|
||||
|
||||
breakpoint: NbMediaBreakpoint;
|
||||
breakpoints: any;
|
||||
|
||||
constructor(private themeService: NbThemeService,
|
||||
private breakpointService: NbMediaBreakpointsService) {
|
||||
|
||||
this.breakpoints = this.breakpointService.getBreakpointsMap();
|
||||
this.themeService.onMediaQueryChange()
|
||||
constructor(themeService: NbThemeService, breakpointService: NbMediaBreakpointsService) {
|
||||
this.breakpoints = breakpointService.getBreakpointsMap();
|
||||
themeService.onMediaQueryChange()
|
||||
.pipe(takeWhile(() => this.alive))
|
||||
.subscribe(([oldValue, newValue]) => {
|
||||
this.breakpoint = newValue;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
private alive = true;
|
||||
public forMaterialTheme: boolean = false;
|
||||
public readonly breakpoints: any;
|
||||
public breakpoint: NbMediaBreakpoint;
|
||||
|
||||
@Input() public set material(value: any) {
|
||||
this.forMaterialTheme = (value);
|
||||
}
|
||||
|
||||
public get imageUrl(): string {
|
||||
return this.forMaterialTheme !== false
|
||||
? 'assets/img/ngx-admin-material.png'
|
||||
: 'assets/img/ngx-admin.png';
|
||||
}
|
||||
|
||||
public ngOnDestroy() {
|
||||
this.alive = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<div>
|
||||
<h1>material ngx-admin</h1>
|
||||
<p class="description">
|
||||
Material admin theme based on the most popular Angular dashboard template - <a href="https://hubs.ly/H0nJjJ00"
|
||||
target="_blank">ngx-admin</a>.
|
||||
Included: <strong>Angular 9+</strong>,
|
||||
<a href="https://hubs.ly/H0n5N9P0" target="_blank">Nebular</a> and
|
||||
<a href="https://hubs.ly/H0n5PKH0">Eva Design System</a>.
|
||||
Free for personal and commercial usage.
|
||||
<br>
|
||||
<span class="bundles">
|
||||
Get material ngx-admin integrated with backend technology of your choice.
|
||||
<a href="https://hubs.ly/H0nJfXB0" target="_blank">
|
||||
Check out our store.
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
|
@ -0,0 +1,9 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-material-admin-info',
|
||||
templateUrl: './material-info.component.html',
|
||||
styleUrls: ['./../main-info-section.component.scss'],
|
||||
})
|
||||
export class MaterialAdminInfoComponent {
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<ngx-landing-section-title>
|
||||
Features and benefits
|
||||
</ngx-landing-section-title>
|
||||
|
||||
<ul class="features">
|
||||
<li class="feature">
|
||||
<div class="number">1</div>
|
||||
<div class="description">
|
||||
The most popular and trusted Angular open source dashboard template is out there. Used by hundreds of thousands developers worldwide and Fortune 500 companies*
|
||||
</div>
|
||||
</li>
|
||||
<li class="feature">
|
||||
<div class="number">2</div>
|
||||
<div class="description">
|
||||
Over 40+ Angular Components and 60+ Usage Examples. Kick off your project and save money by using ngx-admin.
|
||||
</div>
|
||||
</li>
|
||||
<li class="feature">
|
||||
<div class="number">3</div>
|
||||
<div class="description">
|
||||
Already using ngx-admin and willing to switch to material theme? Material theme is backward-compatible. Check out the article describing how to do that
|
||||
</div>
|
||||
</li>
|
||||
<li class="feature">
|
||||
<div class="number">4</div>
|
||||
<div class="description">
|
||||
ngx-admin material works perfectly with Angular Material and Nebular. Take the best from both!
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
@import '../../../@theme/styles/themes';
|
||||
@import '~@nebular/theme/styles/global/breakpoints';
|
||||
|
||||
@include nb-install-component() {
|
||||
$features-section-offset: 10.625rem;
|
||||
|
||||
display: block;
|
||||
padding: 5.25rem 0;
|
||||
|
||||
.features {
|
||||
width: calc(100% - #{$features-section-offset} * 2);
|
||||
margin: -1.375rem auto 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
padding: 0;
|
||||
|
||||
.feature {
|
||||
display: flex;
|
||||
width: 50%;
|
||||
list-style: none;
|
||||
padding-right: 3.75rem;
|
||||
padding-left: 0.25rem;
|
||||
margin-top: 7.875rem;
|
||||
|
||||
&:nth-child(2n) {
|
||||
padding-right: 0;
|
||||
padding-left: 3.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.number {
|
||||
font-family: 'Helvetica Neue Bold', sans-serif;
|
||||
font-size: 8.75rem;
|
||||
color: #ffffff;
|
||||
text-shadow: 0 0.5rem 1rem #dae0eb;
|
||||
line-height: 0.3;
|
||||
}
|
||||
|
||||
.description {
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
height: 0.25rem;
|
||||
width: 3.5rem;
|
||||
margin-bottom: 0.375rem;
|
||||
background-color: nb-theme(color-active-bg);
|
||||
}
|
||||
|
||||
font-family: nb-theme(font-secondary), sans-serif;
|
||||
font-size: nb-theme(font-size-lg);
|
||||
line-height: 1.5;
|
||||
margin-left: 1.75rem;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
font-family: nb-theme(font-main), sans-serif;
|
||||
}
|
||||
|
||||
.active {
|
||||
text-decoration: none;
|
||||
font-family: nb-theme(font-main), sans-serif;
|
||||
color: nb-theme(color-active-fg);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(xl) {
|
||||
.features {
|
||||
width: 100%;
|
||||
padding: 0 1rem;
|
||||
margin: 0;
|
||||
|
||||
.number {
|
||||
font-size: 6rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(sm) {
|
||||
padding-top: 2.625rem;
|
||||
padding-bottom: 0;
|
||||
|
||||
.features {
|
||||
flex-direction: column;
|
||||
|
||||
.feature {
|
||||
width: 100%;
|
||||
margin: 1.625rem 0 0.375rem;
|
||||
padding: 0;
|
||||
|
||||
&:nth-child(2n) {
|
||||
padding: 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.number {
|
||||
font-size: 5rem;
|
||||
line-height: 1.3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-material-features',
|
||||
templateUrl: './material-features.component.html',
|
||||
styleUrls: ['./material-features.component.scss'],
|
||||
})
|
||||
export class MaterialFeaturesSectionComponent {
|
||||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<nb-layout>
|
||||
<nb-layout-header fixed>
|
||||
<ngx-landing-header></ngx-landing-header>
|
||||
</nb-layout-header>
|
||||
|
||||
<nb-layout-column class="main-section">
|
||||
<ngx-landing-main-info material></ngx-landing-main-info>
|
||||
<ngx-material-features></ngx-material-features>
|
||||
<ngx-landing-theme-section material></ngx-landing-theme-section>
|
||||
<ngx-contact-form></ngx-contact-form>
|
||||
</nb-layout-column>
|
||||
|
||||
<nb-layout-footer class="footer" fixed>
|
||||
<ngx-landing-footer></ngx-landing-footer>
|
||||
</nb-layout-footer>
|
||||
</nb-layout>
|
|
@ -0,0 +1,34 @@
|
|||
@import '../../../@theme/styles/themes';
|
||||
|
||||
@include nb-install-component() {
|
||||
|
||||
$content-width: nb-theme(content-width);
|
||||
|
||||
::ng-deep {
|
||||
.version {
|
||||
color: nb-theme(color-basic-500) !important;
|
||||
}
|
||||
|
||||
ngx-landing-footer{
|
||||
.h6, .copy {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main-section {
|
||||
background-color: nb-theme(gray-section-bg);
|
||||
}
|
||||
|
||||
ngx-material-features {
|
||||
max-width: $content-width;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(is) {
|
||||
ngx-material-features {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { NbThemeService } from '@nebular/theme';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-material-landing',
|
||||
templateUrl: './material-landing.component.html',
|
||||
styleUrls: [
|
||||
'./material-landing.component.scss',
|
||||
'../landing-home.component.scss',
|
||||
],
|
||||
})
|
||||
export class MaterialLandingComponent {
|
||||
constructor(private themeService: NbThemeService) {
|
||||
this.themeService.changeTheme('ngx-landing-material');
|
||||
}
|
||||
}
|
|
@ -7,37 +7,57 @@
|
|||
[swiper]="swiperConfig"
|
||||
[(index)]="sliderIndex">
|
||||
<div class="swiper-wrapper">
|
||||
<a href="https://hubs.ly/H0n54_z0" target="_blank" class="image-container swiper-slide">
|
||||
<a [href]="materialLightDemoUrl" target="_blank" class="image-container swiper-slide">
|
||||
<img *ngIf="breakpoint.width <= breakpoints.sm"
|
||||
data-src="assets/img/light-theme.png"
|
||||
class="swiper-lazy"
|
||||
alt="Light Theme" />
|
||||
data-src="assets/img/material-light-theme.png"
|
||||
class="swiper-lazy"
|
||||
alt="Material Light Theme" />
|
||||
<img *ngIf="!(breakpoint.width <= breakpoints.sm)"
|
||||
lazyLoad="assets/img/light-theme.png"
|
||||
defaultImage="assets/img/default.png"
|
||||
alt="Light Theme" />
|
||||
lazyLoad="assets/img/material-light-theme.png"
|
||||
defaultImage="assets/img/default.png"
|
||||
alt="Material Light Theme" />
|
||||
</a>
|
||||
<a href="https://hubs.ly/H0n54SN0" target="_blank" class="image-container swiper-slide">
|
||||
<a [href]="materialDarkDemoUrl" target="_blank" class="image-container swiper-slide">
|
||||
<img *ngIf="breakpoint.width <= breakpoints.sm"
|
||||
data-src="assets/img/dark-theme.png"
|
||||
class="swiper-lazy"
|
||||
alt="Dark Theme" />
|
||||
data-src="assets/img/material-dark-theme.png"
|
||||
class="swiper-lazy"
|
||||
alt="Material Dark Theme" />
|
||||
<img *ngIf="!(breakpoint.width <= breakpoints.sm)"
|
||||
lazyLoad="assets/img/dark-theme.png"
|
||||
defaultImage="assets/img/default.png"
|
||||
alt="Dark Theme" />
|
||||
lazyLoad="assets/img/material-dark-theme.png"
|
||||
defaultImage="assets/img/default.png"
|
||||
alt="Material Dark Theme" />
|
||||
</a>
|
||||
<a href="https://hubs.ly/H0n55cG0" target="_blank" class="image-container swiper-slide">
|
||||
<a [href]="lightDemoUrl" target="_blank" class="image-container swiper-slide">
|
||||
<img *ngIf="breakpoint.width <= breakpoints.sm"
|
||||
data-src="assets/img/light-theme.png"
|
||||
class="swiper-lazy"
|
||||
alt="Eva Light Theme" />
|
||||
<img *ngIf="!(breakpoint.width <= breakpoints.sm)"
|
||||
lazyLoad="assets/img/light-theme.png"
|
||||
defaultImage="assets/img/default.png"
|
||||
alt="Eva Light Theme" />
|
||||
</a>
|
||||
<a [href]="darkDemoUrl" target="_blank" class="image-container swiper-slide">
|
||||
<img *ngIf="breakpoint.width <= breakpoints.sm"
|
||||
data-src="assets/img/dark-theme.png"
|
||||
class="swiper-lazy"
|
||||
alt="Eva Dark Theme" />
|
||||
<img *ngIf="!(breakpoint.width <= breakpoints.sm)"
|
||||
src="assets/img/dark-theme.png"
|
||||
alt="Eva Dark Theme"
|
||||
class="ng-lazyloaded" />
|
||||
</a>
|
||||
<a [href]="cosmicDemoUrl" target="_blank" class="image-container swiper-slide">
|
||||
<img *ngIf="breakpoint.width <= breakpoints.sm"
|
||||
data-src="assets/img/cosmic-theme.png"
|
||||
class="swiper-lazy"
|
||||
alt="Cosmic Theme" />
|
||||
<img *ngIf="!(breakpoint.width <= breakpoints.sm)"
|
||||
lazyLoad="assets/img/cosmic-theme.png"
|
||||
defaultImage="assets/img/default.png"
|
||||
alt="Cosmic Theme" />
|
||||
src="assets/img/cosmic-theme.png"
|
||||
alt="Cosmic Theme"
|
||||
class="ng-lazyloaded"/>
|
||||
</a>
|
||||
<a href="https://hubs.ly/H0n55170" target="_blank" class="image-container swiper-slide">
|
||||
<a [href]="corporateDemoUrl" target="_blank" class="image-container swiper-slide">
|
||||
<img *ngIf="breakpoint.width <= breakpoints.sm"
|
||||
data-src="assets/img/corporate-theme.png"
|
||||
class="swiper-lazy"
|
||||
|
@ -52,10 +72,10 @@
|
|||
<div class="swiper-pagination"></div>
|
||||
|
||||
<div class="swiper-button-prev">
|
||||
<i [innerHTML]="'arrow-ios-back' | eva: { width: 36, height: 36, fill: '#00db92' }"></i>
|
||||
<i [innerHTML]="'arrow-ios-back' | eva: { width: 36, height: 36, fill: iconColor }"></i>
|
||||
</div>
|
||||
<div class="swiper-button-next">
|
||||
<i [innerHTML]="'arrow-ios-forward' | eva: { width: 36, height: 36, fill: '#00db92' }"></i>
|
||||
<i [innerHTML]="'arrow-ios-forward' | eva: { width: 36, height: 36, fill: iconColor }"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -55,6 +55,10 @@
|
|||
&:active {
|
||||
box-shadow: nb-theme(shadow-active-btn);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
.swiper-button-prev {
|
||||
|
@ -93,7 +97,7 @@
|
|||
|
||||
span {
|
||||
display: inline-block;
|
||||
padding: 0.75rem 3.5rem;
|
||||
padding: 0.75rem 1.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
@ -205,6 +209,7 @@
|
|||
|
||||
span {
|
||||
padding: 0.75rem 0;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
&.swiper-pagination-bullet-active {
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import { Component, OnDestroy } from '@angular/core';
|
||||
import { Component, OnDestroy, Input } from '@angular/core';
|
||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { SwiperConfigInterface } from 'ngx-swiper-wrapper';
|
||||
import { takeWhile } from 'rxjs/operators';
|
||||
import {
|
||||
|
@ -21,9 +22,12 @@ import {
|
|||
export class ThemeSectionComponent implements OnDestroy {
|
||||
|
||||
private alive = true;
|
||||
private forMaterialTheme: boolean = false;
|
||||
private themes: string[] = [
|
||||
'Light',
|
||||
'Dark',
|
||||
'Material\nLight',
|
||||
'Material\nDark',
|
||||
'Eva\nLight',
|
||||
'Eva\nDark',
|
||||
'Cosmic',
|
||||
'Corporate',
|
||||
];
|
||||
|
@ -32,6 +36,7 @@ export class ThemeSectionComponent implements OnDestroy {
|
|||
breakpoints: any;
|
||||
sliderIndex: number = 1;
|
||||
initialSwiperConfig: SwiperConfigInterface = {
|
||||
initialSlide: 1,
|
||||
direction: 'horizontal',
|
||||
spaceBetween: 200,
|
||||
slidesPerView: 'auto',
|
||||
|
@ -55,9 +60,7 @@ export class ThemeSectionComponent implements OnDestroy {
|
|||
renderBullet: (index, className) => {
|
||||
return `
|
||||
<span class="${className}">
|
||||
<span>
|
||||
${this.themes[index]}
|
||||
</span>
|
||||
<span>${this.themes[index]}</span>
|
||||
</span>`;
|
||||
},
|
||||
},
|
||||
|
@ -66,8 +69,54 @@ export class ThemeSectionComponent implements OnDestroy {
|
|||
...this.initialSwiperConfig,
|
||||
};
|
||||
|
||||
constructor(private themeService: NbThemeService,
|
||||
private breakpointService: NbMediaBreakpointsService) {
|
||||
@Input() public set material(value: any) {
|
||||
this.forMaterialTheme = coerceBooleanProperty(value);
|
||||
}
|
||||
|
||||
public get iconColor(): string {
|
||||
return this.forMaterialTheme ? '#6200ee' : '#00db92';
|
||||
}
|
||||
|
||||
public get materialLightDemoUrl(): string {
|
||||
return this.forMaterialTheme
|
||||
? 'https://www.akveo.com/ngx-admin/pages/dashboard?theme=material-light&utm_campaign=ngx_admin%20-%20demo%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_material_themes_material_light'
|
||||
: 'https://www.akveo.com/ngx-admin/pages/dashboard?theme=material-light&utm_campaign=ngx_admin%20-%20demo%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_landing_themes_material_light';
|
||||
}
|
||||
|
||||
public get materialDarkDemoUrl(): string {
|
||||
return this.forMaterialTheme
|
||||
? 'https://www.akveo.com/ngx-admin/pages/dashboard?theme=material-dark&utm_campaign=ngx_admin%20-%20demo%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_material_themes_material_dark'
|
||||
: 'https://www.akveo.com/ngx-admin/pages/dashboard?theme=material-dark&utm_campaign=ngx_admin%20-%20demo%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_landing_themes_material_dark';
|
||||
}
|
||||
|
||||
public get lightDemoUrl(): string {
|
||||
return this.forMaterialTheme
|
||||
? 'https://www.akveo.com/ngx-admin/pages/dashboard?theme=default&utm_campaign=ngx_admin%20-%20demo%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_material_themes_default'
|
||||
: 'https://www.akveo.com/ngx-admin/pages/dashboard?theme=default&utm_campaign=ngx_admin%20-%20demo%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_landing_themes_default';
|
||||
}
|
||||
|
||||
public get darkDemoUrl(): string {
|
||||
return this.forMaterialTheme
|
||||
? 'https://www.akveo.com/ngx-admin/pages/dashboard?theme=dark&utm_campaign=ngx_admin%20-%20demo%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_material_themes_dark'
|
||||
: 'https://www.akveo.com/ngx-admin/pages/dashboard?theme=dark&utm_campaign=ngx_admin%20-%20demo%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_landing_themes_dark';
|
||||
}
|
||||
|
||||
public get cosmicDemoUrl(): string {
|
||||
return this.forMaterialTheme
|
||||
? 'https://www.akveo.com/ngx-admin/pages/dashboard?theme=cosmic&utm_campaign=ngx_admin%20-%20demo%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_material_themes_cosmic'
|
||||
: 'https://www.akveo.com/ngx-admin/pages/dashboard?theme=cosmic&utm_campaign=ngx_admin%20-%20demo%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_landing_themes_cosmic';
|
||||
}
|
||||
|
||||
public get corporateDemoUrl(): string {
|
||||
return this.forMaterialTheme
|
||||
? 'https://www.akveo.com/ngx-admin/pages/dashboard?theme=corporate&utm_campaign=ngx_admin%20-%20demo%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_material_themes_corporate'
|
||||
: 'https://www.akveo.com/ngx-admin/pages/dashboard?theme=corporate&utm_campaign=ngx_admin%20-%20demo%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_landing_themes_corporate';
|
||||
}
|
||||
|
||||
constructor(
|
||||
private themeService: NbThemeService,
|
||||
private breakpointService: NbMediaBreakpointsService,
|
||||
) {
|
||||
this.breakpoints = this.breakpointService.getBreakpointsMap();
|
||||
this.themeService.onMediaQueryChange()
|
||||
.pipe(takeWhile(() => this.alive))
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<a
|
||||
routerLink="/material"
|
||||
class="eva-parent-hover"
|
||||
[nbPopover]="popoverContent"
|
||||
nbPopoverPlacement="bottom"
|
||||
nbPopoverTrigger="noop"
|
||||
>
|
||||
<i [innerHTML]="'color-palette-outline' | eva: { width: 24, height: 24, fill: '#ff4d6b', animationType: 'shake' }"
|
||||
></i>
|
||||
Material Theme
|
||||
</a>
|
||||
|
||||
<ng-template #popoverContent>
|
||||
<p class="material-theme-popover" (mouseover)="hidePopover()">New theme is available!</p>
|
||||
</ng-template>
|
|
@ -0,0 +1,22 @@
|
|||
:host {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: 32px;
|
||||
}
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.material-theme-popover {
|
||||
margin: 0;
|
||||
padding: 1rem 2rem;
|
||||
color: #ff4d6b;
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
import { Component, ViewChild, AfterViewInit, Input } from '@angular/core';
|
||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { NbPopoverDirective } from '@nebular/theme';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-material-theme-link',
|
||||
templateUrl: './material-theme-link.component.html',
|
||||
styleUrls: ['./material-theme-link.component.scss'],
|
||||
})
|
||||
export class MaterialThemeLinkComponent implements AfterViewInit {
|
||||
public showPopover: boolean = false;
|
||||
|
||||
@Input() public set withPopover(value: any) {
|
||||
this.showPopover = coerceBooleanProperty(value);
|
||||
}
|
||||
|
||||
@ViewChild(NbPopoverDirective, { static: true }) public popover: NbPopoverDirective;
|
||||
|
||||
public ngAfterViewInit(): void {
|
||||
this.showPopover && this.popover && this.popover.show();
|
||||
}
|
||||
|
||||
public hidePopover(): void {
|
||||
this.popover && this.popover.hide();
|
||||
}
|
||||
}
|
16
docs/app/shared/landing-shared.module.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { NbPopoverModule } from '@nebular/theme';
|
||||
import { MaterialThemeLinkComponent } from './components/material-theme-link/material-theme-link.component';
|
||||
import { CapitalizePipe } from './pipes/capitalize.pipe';
|
||||
import { EvaIconsPipe } from './pipes/eva-icons.pipe';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
const component = [MaterialThemeLinkComponent];
|
||||
const pipes = [CapitalizePipe, EvaIconsPipe];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule, NbPopoverModule],
|
||||
declarations: [...component, ...pipes],
|
||||
exports: [NbPopoverModule, ...component, ...pipes],
|
||||
})
|
||||
export class LandingSharedModule {}
|
BIN
docs/assets/img/material-dark-theme.png
Normal file
After Width: | Height: | Size: 658 KiB |
BIN
docs/assets/img/material-light-theme.png
Normal file
After Width: | Height: | Size: 656 KiB |
BIN
docs/assets/img/ngx-admin-material-dark.png
Normal file
After Width: | Height: | Size: 1 MiB |
BIN
docs/assets/img/ngx-admin-material.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
|
@ -1,19 +1,8 @@
|
|||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"lib": [
|
||||
"es2017",
|
||||
"dom"
|
||||
],
|
||||
"outDir": "../out-tsc/app",
|
||||
"module": "es2015",
|
||||
"baseUrl": ".",
|
||||
"types": []
|
||||
"baseUrl": "."
|
||||
},
|
||||
"exclude": [
|
||||
"test.ts",
|
||||
|
|
8
docs/typings.d.ts
vendored
|
@ -5,9 +5,11 @@
|
|||
*/
|
||||
|
||||
/* SystemJS module definition */
|
||||
declare var module: {
|
||||
declare var module: NodeModule;
|
||||
interface NodeModule {
|
||||
id: string;
|
||||
};
|
||||
declare var require: any;
|
||||
}
|
||||
|
||||
declare var require: NodeRequire;
|
||||
declare var structure: any;
|
||||
declare var docs: any;
|
||||
|
|
14647
package-lock.json
generated
14
package.json
|
@ -48,30 +48,30 @@
|
|||
"@angular/router": "^9.0.4",
|
||||
"@asymmetrik/ngx-leaflet": "3.0.1",
|
||||
"@nebular/auth": "5.0.0",
|
||||
"@nebular/bootstrap": "5.0.0",
|
||||
"@nebular/bootstrap": "^5.0.0",
|
||||
"@nebular/eva-icons": "5.0.0",
|
||||
"@nebular/security": "5.0.0",
|
||||
"@nebular/theme": "5.0.0",
|
||||
"@swimlane/ngx-charts": "^13.0.2",
|
||||
"angular2-chartjs": "0.4.1",
|
||||
"bootstrap": "4.3.1",
|
||||
"bootstrap": "^4.4.1",
|
||||
"chart.js": "2.7.1",
|
||||
"ckeditor": "4.7.3",
|
||||
"classlist.js": "1.1.20150312",
|
||||
"core-js": "2.5.1",
|
||||
"echarts": "^4.0.2",
|
||||
"eva-icons": "^1.1.3",
|
||||
"highlight.js": "^9.13.1",
|
||||
"highlight.js": "^9.18.1",
|
||||
"intl": "1.2.5",
|
||||
"ionicons": "2.0.1",
|
||||
"leaflet": "1.2.0",
|
||||
"marked": "^0.5.2",
|
||||
"nebular-icons": "1.1.0",
|
||||
"ng-lazyload-image": "5.0.0",
|
||||
"ng-lazyload-image": "^7.1.0",
|
||||
"ng2-ckeditor": "^1.2.2",
|
||||
"ng2-smart-table": "^1.6.0",
|
||||
"ngx-echarts": "^4.2.2",
|
||||
"ngx-swiper-wrapper": "^7.1.1",
|
||||
"ngx-swiper-wrapper": "^9.0.1",
|
||||
"node-sass": "^4.12.0",
|
||||
"normalize.css": "6.0.0",
|
||||
"pace-js": "1.0.2",
|
||||
|
@ -79,7 +79,6 @@
|
|||
"rxjs": "6.5.4",
|
||||
"rxjs-compat": "6.3.0",
|
||||
"socicon": "3.0.5",
|
||||
"style-loader": "^1.1.3",
|
||||
"tinymce": "4.5.7",
|
||||
"tslib": "^1.10.0",
|
||||
"typeface-exo": "0.0.22",
|
||||
|
@ -99,7 +98,7 @@
|
|||
"@types/jasminewd2": "2.0.3",
|
||||
"@types/leaflet": "1.2.3",
|
||||
"@types/node": "^12.11.1",
|
||||
"angular-cli-ghpages": "0.5.0",
|
||||
"angular-cli-ghpages": "^0.6.2",
|
||||
"codelyzer": "^5.1.2",
|
||||
"conventional-changelog-cli": "1.3.4",
|
||||
"husky": "0.13.3",
|
||||
|
@ -114,6 +113,7 @@
|
|||
"npm-run-all": "4.0.2",
|
||||
"protractor": "5.1.2",
|
||||
"rimraf": "2.6.1",
|
||||
"style-loader": "^1.1.3",
|
||||
"stylelint": "7.13.0",
|
||||
"ts-node": "3.2.2",
|
||||
"tslint": "^5.7.0",
|
||||
|
|
|
@ -55,6 +55,8 @@ import { SecurityCamerasService } from './mock/security-cameras.service';
|
|||
import { RippleService } from './utils/ripple.service';
|
||||
import { MockDataModule } from './mock/mock-data.module';
|
||||
import { AbService } from './utils/ab.service';
|
||||
import {CurrentThemeService} from './utils/theme.service';
|
||||
import {ThemeGuard} from './guard/theme.guard';
|
||||
|
||||
const socialLinks = [
|
||||
{
|
||||
|
@ -97,6 +99,10 @@ const DATA_SERVICES = [
|
|||
{provide: MAT_RIPPLE_GLOBAL_OPTIONS, useExisting: RippleService},
|
||||
];
|
||||
|
||||
const GUARDS = [
|
||||
ThemeGuard,
|
||||
];
|
||||
|
||||
export class NbSimpleRoleProvider extends NbRoleProvider {
|
||||
getRole() {
|
||||
// here you could provide any role based on any auth flow
|
||||
|
@ -107,6 +113,7 @@ export class NbSimpleRoleProvider extends NbRoleProvider {
|
|||
export const NB_CORE_PROVIDERS = [
|
||||
...MockDataModule.forRoot().providers,
|
||||
...DATA_SERVICES,
|
||||
...GUARDS,
|
||||
...NbAuthModule.forRoot({
|
||||
|
||||
strategies: [
|
||||
|
@ -148,6 +155,7 @@ export const NB_CORE_PROVIDERS = [
|
|||
SeoService,
|
||||
StateService,
|
||||
AbService,
|
||||
CurrentThemeService,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
|
26
src/app/@core/guard/theme.guard.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import {Injectable} from '@angular/core';
|
||||
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from '@angular/router';
|
||||
import {Observable} from 'rxjs';
|
||||
import {map} from 'rxjs/operators';
|
||||
import {CurrentThemeService} from '../utils/theme.service';
|
||||
|
||||
@Injectable()
|
||||
export class ThemeGuard implements CanActivate {
|
||||
constructor(private router: Router,
|
||||
private currentThemeService: CurrentThemeService) {}
|
||||
|
||||
canActivate(
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot,
|
||||
): Observable<boolean> | Promise<boolean> | boolean {
|
||||
return this.currentThemeService.currentTheme$.pipe(
|
||||
map(theme => {
|
||||
const currentThemeExpiration = JSON.parse(theme).expires_in;
|
||||
const currentDate = new Date().getTime();
|
||||
if (!theme || currentDate > currentThemeExpiration) {
|
||||
this.router.navigate(['themes']);
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
}
|
33
src/app/@core/utils/theme.service.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
import {Injectable, OnDestroy} from '@angular/core';
|
||||
import {Observable} from 'rxjs';
|
||||
import {takeWhile} from 'rxjs/operators';
|
||||
import {environment} from '../../../environments/environment';
|
||||
|
||||
@Injectable()
|
||||
export class CurrentThemeService implements OnDestroy {
|
||||
alive = true;
|
||||
|
||||
readonly currentTheme$: Observable<any> = new Observable(subscriber => {
|
||||
subscriber.next(localStorage.theme);
|
||||
}).pipe(takeWhile(() => this.alive));
|
||||
|
||||
setCurrentTheme(themeName: string): void {
|
||||
const currentTheme = {
|
||||
themeName: themeName,
|
||||
expires_in: this.calculateExpiration(environment.currentThemeLife),
|
||||
};
|
||||
|
||||
localStorage.setItem('theme', JSON.stringify(currentTheme));
|
||||
}
|
||||
|
||||
calculateExpiration(iat: number): number {
|
||||
const currentDate = new Date().getTime();
|
||||
const timestamp = iat || Math.floor(Date.now() / 1000);
|
||||
|
||||
return Math.floor(timestamp + currentDate);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.alive = false;
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@
|
|||
<nb-icon icon="download"></nb-icon>
|
||||
<span class="subtitle number">470.000</span>
|
||||
</nb-action>
|
||||
<nb-action class="control-item contact-us">
|
||||
<nb-action class="control-item contact-us" matRipple [matRippleUnbounded]="false" [matRippleCentered]="true">
|
||||
<a nbButton ghost href="mailto:contact@akveo.com" (click)="trackEmailClick()">
|
||||
<nb-icon icon="email-outline" pack="eva"></nb-icon>
|
||||
<span>contact@akveo.com</span>
|
||||
|
@ -52,9 +52,9 @@
|
|||
[matRippleCentered]="true">
|
||||
</nb-search>
|
||||
</nb-action>
|
||||
<nb-action class="control-item email" icon="email-outline"></nb-action>
|
||||
<nb-action class="control-item notifications" icon="bell-outline"></nb-action>
|
||||
<nb-action class="user-action" *nbIsGranted="['view', 'user']" >
|
||||
<nb-action class="control-item email" icon="email-outline" matRipple [matRippleUnbounded]="true" [matRippleCentered]="true"></nb-action>
|
||||
<nb-action class="control-item notifications" icon="bell-outline" matRipple [matRippleUnbounded]="true" [matRippleCentered]="true"></nb-action>
|
||||
<nb-action class="user-action" *nbIsGranted="['view', 'user']" matRipple [matRippleUnbounded]="false" [matRippleCentered]="true">
|
||||
<nb-user [nbContextMenu]="userMenu"
|
||||
[onlyPicture]="userPictureOnly"
|
||||
[name]="user?.name"
|
||||
|
|
|
@ -6,6 +6,7 @@ import { AnalyticsService, LayoutService } from '../../../@core/utils';
|
|||
import { map, takeUntil } from 'rxjs/operators';
|
||||
import { Subject, Observable } from 'rxjs';
|
||||
import { RippleService } from '../../../@core/utils/ripple.service';
|
||||
import {CurrentThemeService} from '../../../@core/utils/theme.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-header',
|
||||
|
@ -57,6 +58,7 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
|||
private layoutService: LayoutService,
|
||||
private breakpointService: NbMediaBreakpointsService,
|
||||
private rippleService: RippleService,
|
||||
private currentThemeService: CurrentThemeService,
|
||||
private analytics: AnalyticsService,
|
||||
) {
|
||||
this.materialTheme$ = this.themeService.onThemeChange()
|
||||
|
@ -98,6 +100,7 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
changeTheme(themeName: string) {
|
||||
this.currentThemeService.setCurrentTheme(themeName);
|
||||
this.themeService.changeTheme(themeName);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,16 +8,24 @@ import {
|
|||
NbRequestPasswordComponent,
|
||||
NbResetPasswordComponent,
|
||||
} from '@nebular/auth';
|
||||
import {ThemeGuard} from './@core/guard/theme.guard';
|
||||
|
||||
export const routes: Routes = [
|
||||
{
|
||||
path: 'pages',
|
||||
canActivate: [ThemeGuard],
|
||||
loadChildren: () => import('./pages/pages.module')
|
||||
.then(m => m.PagesModule),
|
||||
},
|
||||
{
|
||||
path: 'themes',
|
||||
loadChildren: () => import('app/themes-screen/starter.module')
|
||||
.then(m => m.StarterModule),
|
||||
},
|
||||
{
|
||||
path: 'auth',
|
||||
component: NbAuthComponent,
|
||||
canActivate: [ThemeGuard],
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
|
@ -45,8 +53,8 @@ export const routes: Routes = [
|
|||
},
|
||||
],
|
||||
},
|
||||
{ path: '', redirectTo: 'pages', pathMatch: 'full' },
|
||||
{ path: '**', redirectTo: 'pages' },
|
||||
{ path: '', redirectTo: 'themes', pathMatch: 'full' },
|
||||
{ path: '**', redirectTo: 'themes' },
|
||||
];
|
||||
|
||||
const config: ExtraOptions = {
|
||||
|
|
21
src/app/themes-screen/starter-routing.module.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import {NgModule} from '@angular/core';
|
||||
import {RouterModule, Routes} from '@angular/router';
|
||||
import {NgxStarterComponent} from './starter.component';
|
||||
|
||||
const routes: Routes = [{
|
||||
path: '',
|
||||
component: NgxStarterComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: NgxStarterComponent,
|
||||
},
|
||||
],
|
||||
}];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class StarterRoutingModule {
|
||||
}
|
53
src/app/themes-screen/starter.component.html
Normal file
|
@ -0,0 +1,53 @@
|
|||
<nb-layout windowMode>
|
||||
<nb-layout-header fixed>
|
||||
<div class="header-container">
|
||||
<div class="logo-container">
|
||||
<p class="logo">ngx-<span>admin</span></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="header-container">
|
||||
<nb-actions size="small">
|
||||
<nb-action class="control-item github-stars">
|
||||
<span class="subtitle text">Support us: </span>
|
||||
<iframe src="https://ghbtns.com/github-btn.html?user=akveo&repo=ngx-admin&type=star&count=true"
|
||||
frameborder="0"
|
||||
scrolling="0"
|
||||
width="170px"
|
||||
height="20px">
|
||||
</iframe>
|
||||
</nb-action>
|
||||
<nb-action class="control-item downloads-count">
|
||||
<nb-icon icon="download"></nb-icon>
|
||||
<span class="subtitle number">470.000</span>
|
||||
</nb-action>
|
||||
<nb-action class="control-item contact-us" (click)="trackEmailClick()">
|
||||
<a nbButton ghost href="mailto:contact@akveo.com">
|
||||
<nb-icon icon="email-outline" pack="eva"></nb-icon>
|
||||
<span>contact@akveo.com</span>
|
||||
</a>
|
||||
</nb-action>
|
||||
</nb-actions>
|
||||
</div>
|
||||
</nb-layout-header>
|
||||
|
||||
<nb-layout-column>
|
||||
<h4>Choose theme</h4>
|
||||
|
||||
<ng-container *ngFor="let theme of themes">
|
||||
<nb-card (click)="navigate(theme.value)">
|
||||
<nb-card-header>{{theme.name}}</nb-card-header>
|
||||
<nb-card-body>
|
||||
<img src="../../assets/images/{{theme.value}}-theme.png"
|
||||
class="theme-preview"
|
||||
alt="{{theme.name}} Theme"/>
|
||||
</nb-card-body>
|
||||
</nb-card>
|
||||
</ng-container>
|
||||
</nb-layout-column>
|
||||
|
||||
<nb-layout-footer fixed>
|
||||
<ngx-footer></ngx-footer>
|
||||
</nb-layout-footer>
|
||||
|
||||
</nb-layout>
|
174
src/app/themes-screen/starter.component.scss
Normal file
|
@ -0,0 +1,174 @@
|
|||
@import '~bootstrap/scss/mixins/breakpoints';
|
||||
@import '~@nebular/theme/styles/global/breakpoints';
|
||||
@import '../@theme/styles/themes';
|
||||
|
||||
@include nb-install-component() {
|
||||
img {
|
||||
width: 100%;
|
||||
object-fit: contain;
|
||||
height: auto;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
h4 {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
height: 35px;
|
||||
margin-bottom: 36px;
|
||||
}
|
||||
|
||||
nb-layout-column {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
nb-card {
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
width: 32%;
|
||||
}
|
||||
|
||||
nb-card-body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
nb-layout-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
|
||||
::ng-deep nav {
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.logo-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: calc(#{nb-theme(sidebar-width)} - #{nb-theme(header-padding)});
|
||||
}
|
||||
|
||||
nb-action {
|
||||
height: auto;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-family: nb-theme(text-subtitle-font-family);
|
||||
font-size: nb-theme(text-subtitle-font-size);
|
||||
font-weight: nb-theme(text-subtitle-font-weight);
|
||||
line-height: nb-theme(text-subtitle-line-height);
|
||||
}
|
||||
|
||||
.downloads-count .number {
|
||||
@include nb-ltr(margin-left, 0.5rem);
|
||||
@include nb-rtl(margin-right, 0.5rem);
|
||||
}
|
||||
|
||||
::ng-deep nb-search button {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.contact-us {
|
||||
padding: 0;
|
||||
|
||||
nb-icon {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.header-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: auto;
|
||||
|
||||
.logo {
|
||||
padding: 0 1.25rem;
|
||||
font-size: 1.75rem;
|
||||
margin-bottom: 0.5rem;
|
||||
@include nb-rtl(border-right, 1px solid nb-theme(divider-color));
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.github-stars {
|
||||
width: 245px;
|
||||
display: flex;
|
||||
|
||||
iframe {
|
||||
width: 100px;
|
||||
@include nb-ltr(margin-left, 1rem);
|
||||
@include nb-rtl(margin-right, 1rem);
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(xl) {
|
||||
.control-item.github-stars .text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.control-item.github-stars {
|
||||
width: auto;
|
||||
|
||||
iframe {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(lg) {
|
||||
.downloads-count {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(sm) {
|
||||
.contact-us {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(is) {
|
||||
.github-stars {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(xl) {
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(lg) {
|
||||
|
||||
nb-card-header {
|
||||
padding: 12px 20px;
|
||||
}
|
||||
|
||||
nb-card {
|
||||
width: 48%;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(sm) {
|
||||
nb-card-header {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(is) {
|
||||
nb-card {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
61
src/app/themes-screen/starter.component.ts
Normal file
|
@ -0,0 +1,61 @@
|
|||
import {Component, OnDestroy} from '@angular/core';
|
||||
import {NbMediaBreakpoint, NbThemeService} from '@nebular/theme';
|
||||
import {Router} from '@angular/router';
|
||||
import {AnalyticsService} from '../@core/utils';
|
||||
import {CurrentThemeService} from '../@core/utils/theme.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-starter',
|
||||
templateUrl: './starter.component.html',
|
||||
styleUrls: ['./starter.component.scss'],
|
||||
})
|
||||
export class NgxStarterComponent implements OnDestroy {
|
||||
breakpoint: NbMediaBreakpoint;
|
||||
breakpoints: any;
|
||||
|
||||
themes = [
|
||||
{
|
||||
value: 'material-light',
|
||||
name: 'Material Light',
|
||||
},
|
||||
{
|
||||
value: 'dark',
|
||||
name: 'Dark',
|
||||
},
|
||||
{
|
||||
value: 'default',
|
||||
name: 'Light',
|
||||
},
|
||||
{
|
||||
value: 'material-dark',
|
||||
name: 'Material Dark',
|
||||
},
|
||||
{
|
||||
value: 'corporate',
|
||||
name: 'Corporate',
|
||||
},
|
||||
{
|
||||
value: 'cosmic',
|
||||
name: 'Cosmic',
|
||||
},
|
||||
];
|
||||
|
||||
constructor(private router: Router,
|
||||
private themeService: NbThemeService,
|
||||
private currentThemeService: CurrentThemeService,
|
||||
private analytics: AnalyticsService,
|
||||
) {}
|
||||
|
||||
navigate(themeName: string) {
|
||||
this.currentThemeService.setCurrentTheme(themeName);
|
||||
this.themeService.changeTheme(themeName);
|
||||
this.router.navigate(['/pages/dashboard'], {queryParams: {theme: themeName}});
|
||||
}
|
||||
|
||||
trackEmailClick() {
|
||||
this.analytics.trackEvent('clickContactEmail', 'click');
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
}
|
||||
}
|
27
src/app/themes-screen/starter.module.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import {NgModule} from '@angular/core';
|
||||
import {StarterRoutingModule} from './starter-routing.module';
|
||||
import {NgxStarterComponent} from './starter.component';
|
||||
import {NbActionsModule, NbButtonModule, NbCardModule, NbIconModule, NbLayoutModule} from '@nebular/theme';
|
||||
import {ThemeModule} from '../@theme/theme.module';
|
||||
|
||||
const NB_MODULES = [
|
||||
NbIconModule,
|
||||
NbLayoutModule,
|
||||
NbCardModule,
|
||||
NbButtonModule,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
StarterRoutingModule,
|
||||
...NB_MODULES,
|
||||
ThemeModule,
|
||||
NbActionsModule,
|
||||
],
|
||||
declarations: [
|
||||
NgxStarterComponent,
|
||||
NgxStarterComponent,
|
||||
],
|
||||
})
|
||||
export class StarterModule {
|
||||
}
|
BIN
src/assets/images/corporate-theme.png
Normal file
After Width: | Height: | Size: 328 KiB |
BIN
src/assets/images/cosmic-theme.png
Normal file
After Width: | Height: | Size: 355 KiB |
BIN
src/assets/images/dark-theme.png
Normal file
After Width: | Height: | Size: 958 KiB |
BIN
src/assets/images/default-theme.png
Normal file
After Width: | Height: | Size: 381 KiB |
BIN
src/assets/images/material-dark-theme.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 1.9 MiB |
BIN
src/assets/images/material-light-theme.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 1.9 MiB |
|
@ -5,4 +5,5 @@
|
|||
*/
|
||||
export const environment = {
|
||||
production: true,
|
||||
currentThemeLife: 604800000, // 1 week in milliseconds
|
||||
};
|
||||
|
|
|
@ -10,4 +10,5 @@
|
|||
|
||||
export const environment = {
|
||||
production: false,
|
||||
currentThemeLife: 604800000, // 1 week in milliseconds
|
||||
};
|
||||
|
|