mirror of
https://github.com/akveo/ngx-admin.git
synced 2025-09-22 05:50:48 +02:00
feat: demo version additions
This commit is contained in:
parent
0eec54695f
commit
eee950248e
322 changed files with 23456 additions and 188 deletions
40
.github/workflows/azureCliDeploy.yml
vendored
Normal file
40
.github/workflows/azureCliDeploy.yml
vendored
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
name: Deploy to demo (azure storage)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- demo
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Use Node.js 10.x
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '10.x'
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
ref: demo
|
||||||
|
- name: npm install, build
|
||||||
|
run: |
|
||||||
|
npm install
|
||||||
|
npm run build:demo:prod
|
||||||
|
|
||||||
|
# Azure CLI Upload to storage
|
||||||
|
- uses: azure/login@v1
|
||||||
|
with:
|
||||||
|
creds: ${{ secrets.AZURE_RBAC_CREDENTIALS }}
|
||||||
|
- name: Upload to blob storage
|
||||||
|
uses: azure/CLI@v1
|
||||||
|
with:
|
||||||
|
azcliversion: 2.0.72
|
||||||
|
inlineScript: |
|
||||||
|
az storage blob upload-batch -d '$web' -s dist --account-name ngxadmin --debug
|
||||||
|
|
||||||
|
# Azure logout
|
||||||
|
- name: logout
|
||||||
|
run: |
|
||||||
|
az logout
|
||||||
|
if: always()
|
29
.github/workflows/demoDeploy.yml
vendored
29
.github/workflows/demoDeploy.yml
vendored
|
@ -1,29 +0,0 @@
|
||||||
|
|
||||||
name: Deploy to demo
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- 'demo'
|
|
||||||
paths:
|
|
||||||
- 'src/**'
|
|
||||||
repository_dispatch:
|
|
||||||
types: deploy-to-demo
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Install SSH key
|
|
||||||
uses: shimataro/ssh-key-action@v2
|
|
||||||
with:
|
|
||||||
key: ${{ secrets.SSH_KEY }}
|
|
||||||
known_hosts: ${{ secrets.KNOWN_HOSTS }}
|
|
||||||
- name: Use Node.js 12.x
|
|
||||||
uses: actions/setup-node@v1
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
ref: demo
|
|
||||||
- run: npm install
|
|
||||||
- run: npm run build:demo:prod
|
|
||||||
- run: rsync -r --delete-after dist/. "${{ secrets.REMOTE_URL }}":"${{ secrets.ADDRESS }}"
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,5 +1,6 @@
|
||||||
# compiled output
|
# compiled output
|
||||||
/dist
|
/dist
|
||||||
|
/docs/dist
|
||||||
/tmp
|
/tmp
|
||||||
/out-tsc
|
/out-tsc
|
||||||
|
|
||||||
|
@ -30,7 +31,6 @@
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
testem.log
|
testem.log
|
||||||
/typings
|
/typings
|
||||||
/docs
|
|
||||||
|
|
||||||
# e2e
|
# e2e
|
||||||
/e2e/*.js
|
/e2e/*.js
|
||||||
|
|
130
angular.json
130
angular.json
|
@ -21,6 +21,7 @@
|
||||||
"src/assets",
|
"src/assets",
|
||||||
"src/favicon.ico",
|
"src/favicon.ico",
|
||||||
"src/favicon.png",
|
"src/favicon.png",
|
||||||
|
"src/google46533d2e7a851062.html",
|
||||||
{
|
{
|
||||||
"glob": "**/*",
|
"glob": "**/*",
|
||||||
"input": "node_modules/leaflet/dist/images",
|
"input": "node_modules/leaflet/dist/images",
|
||||||
|
@ -139,6 +140,7 @@
|
||||||
"src/assets",
|
"src/assets",
|
||||||
"src/favicon.ico",
|
"src/favicon.ico",
|
||||||
"src/favicon.png",
|
"src/favicon.png",
|
||||||
|
"src/google46533d2e7a851062.html",
|
||||||
{
|
{
|
||||||
"glob": "**/*",
|
"glob": "**/*",
|
||||||
"input": "node_modules/leaflet/dist/images",
|
"input": "node_modules/leaflet/dist/images",
|
||||||
|
@ -182,6 +184,134 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"docs": {
|
||||||
|
"root": "",
|
||||||
|
"sourceRoot": "docs",
|
||||||
|
"projectType": "application",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-angular:browser",
|
||||||
|
"options": {
|
||||||
|
"outputPath": "docs/dist",
|
||||||
|
"index": "docs/index.html",
|
||||||
|
"main": "docs/main.ts",
|
||||||
|
"tsConfig": "docs/tsconfig.app.json",
|
||||||
|
"polyfills": "docs/polyfills.ts",
|
||||||
|
"assets": [
|
||||||
|
"docs/assets",
|
||||||
|
"docs/404.html",
|
||||||
|
"docs/favicon.png",
|
||||||
|
"docs/google85b6c09017edfbcb.html"
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
"node_modules/bootstrap/dist/css/bootstrap.css",
|
||||||
|
"node_modules/nebular-icons/scss/nebular-icons.scss",
|
||||||
|
"node_modules/swiper/css/swiper.min.css",
|
||||||
|
"node_modules/highlight.js/styles/dracula.css",
|
||||||
|
"docs/app/@theme/styles/styles.scss"
|
||||||
|
],
|
||||||
|
"allowedCommonJsDependencies": [
|
||||||
|
"highlight.js"
|
||||||
|
],
|
||||||
|
"vendorChunk": true,
|
||||||
|
"extractLicenses": false,
|
||||||
|
"buildOptimizer": false,
|
||||||
|
"sourceMap": true,
|
||||||
|
"optimization": false,
|
||||||
|
"namedChunks": true
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"optimization": true,
|
||||||
|
"outputHashing": "all",
|
||||||
|
"sourceMap": false,
|
||||||
|
"extractCss": true,
|
||||||
|
"namedChunks": false,
|
||||||
|
"extractLicenses": true,
|
||||||
|
"vendorChunk": false,
|
||||||
|
"buildOptimizer": true,
|
||||||
|
"fileReplacements": [
|
||||||
|
{
|
||||||
|
"replace": "docs/environments/environment.ts",
|
||||||
|
"with": "docs/environments/environment.prod.ts"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": ""
|
||||||
|
},
|
||||||
|
"serve": {
|
||||||
|
"builder": "@angular-devkit/build-angular:dev-server",
|
||||||
|
"options": {
|
||||||
|
"browserTarget": "docs:build"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"browserTarget": "docs:build:production"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extract-i18n": {
|
||||||
|
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||||
|
"options": {
|
||||||
|
"browserTarget": "docs:build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
|
"options": {
|
||||||
|
"main": "docs/test.ts",
|
||||||
|
"karmaConfig": "./karma.conf.js",
|
||||||
|
"polyfills": "docs/polyfills.ts",
|
||||||
|
"tsConfig": "docs/tsconfig.spec.json",
|
||||||
|
"scripts": [
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
"node_modules/nebular-icons/scss/nebular-icons.scss",
|
||||||
|
"docs/app/@theme/styles/styles.scss"
|
||||||
|
],
|
||||||
|
"assets": [
|
||||||
|
"docs/assets",
|
||||||
|
"docs/favicon.ico",
|
||||||
|
"docs/favicon.png",
|
||||||
|
"docs/google85b6c09017edfbcb.html"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": [
|
||||||
|
"docs/tsconfig.spec.json",
|
||||||
|
"docs/tsconfig.app.json"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"docs-e2e": {
|
||||||
|
"root": "",
|
||||||
|
"sourceRoot": "",
|
||||||
|
"projectType": "application",
|
||||||
|
"architect": {
|
||||||
|
"e2e": {
|
||||||
|
"builder": "@angular-devkit/build-angular:protractor",
|
||||||
|
"options": {
|
||||||
|
"protractorConfig": "./protractor.conf.js",
|
||||||
|
"devServerTarget": "docs:serve"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": [
|
||||||
|
"e2e/tsconfig.e2e.json"],
|
||||||
|
"exclude": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"defaultProject": "ngx-admin-demo",
|
"defaultProject": "ngx-admin-demo",
|
||||||
|
|
20
docs/404.html
Normal file
20
docs/404.html
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>404</title>
|
||||||
|
|
||||||
|
<base href="/ngx-admin/">
|
||||||
|
|
||||||
|
<script type="text/javascript" src="assets/ghspa.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
40
docs/app/@core/core.module.ts
Normal file
40
docs/app/@core/core.module.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
import { throwIfAlreadyLoaded } from './module-import-guard';
|
||||||
|
import { DataModule } from './data/data.module';
|
||||||
|
|
||||||
|
const PIPES = [
|
||||||
|
];
|
||||||
|
|
||||||
|
const NB_CORE_PROVIDERS = [
|
||||||
|
...DataModule.forRoot().providers,
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
],
|
||||||
|
exports: [...PIPES],
|
||||||
|
declarations: [...PIPES],
|
||||||
|
})
|
||||||
|
export class CoreModule {
|
||||||
|
constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
|
||||||
|
throwIfAlreadyLoaded(parentModule, 'CoreModule');
|
||||||
|
}
|
||||||
|
|
||||||
|
static forRoot(): ModuleWithProviders<CoreModule> {
|
||||||
|
return {
|
||||||
|
ngModule: CoreModule,
|
||||||
|
providers: [
|
||||||
|
...NB_CORE_PROVIDERS,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
39
docs/app/@core/data/data.module.ts
Normal file
39
docs/app/@core/data/data.module.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
import { HeaderMenuService } from './service/header-menu.service';
|
||||||
|
import { ReviewsService } from './service/reviews.service';
|
||||||
|
import { DescriptionsService } from './service/descriptions.service';
|
||||||
|
import { BundlesService } from './service/bundles.service';
|
||||||
|
|
||||||
|
const SERVICES = [
|
||||||
|
HeaderMenuService,
|
||||||
|
ReviewsService,
|
||||||
|
DescriptionsService,
|
||||||
|
BundlesService,
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
...SERVICES,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class DataModule {
|
||||||
|
static forRoot(): ModuleWithProviders<DataModule> {
|
||||||
|
return {
|
||||||
|
ngModule: DataModule,
|
||||||
|
providers: [
|
||||||
|
...SERVICES,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
125
docs/app/@core/data/service/bundles.service.ts
Normal file
125
docs/app/@core/data/service/bundles.service.ts
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { of as observableOf, Observable } from 'rxjs';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
|
export interface Product {
|
||||||
|
id: string;
|
||||||
|
imageUrl: string;
|
||||||
|
storeUrl: string;
|
||||||
|
tags: string[];
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
variants: ProductVariant[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProductVariant {
|
||||||
|
available: boolean;
|
||||||
|
compare_at_price: string;
|
||||||
|
price: string;
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BUNDLE_LICENSE = {
|
||||||
|
personal: 'personal',
|
||||||
|
developer: 'developer',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const STORE_PRODUCTS_URL = {
|
||||||
|
base: 'https://store.akveo.com/collections/collection-for-ngx-admin-landing/products.json',
|
||||||
|
material: 'https://store.akveo.com/collections/collection-for-ngx-admin-landing/products.json',
|
||||||
|
};
|
||||||
|
|
||||||
|
export class Feature {
|
||||||
|
text: string;
|
||||||
|
availableInPersonalLicence: boolean;
|
||||||
|
availableInCommercialLicence: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BundlesService {
|
||||||
|
|
||||||
|
private readonly STORE_COLLECTION: string = 'https://store.akveo.com/collections';
|
||||||
|
|
||||||
|
private features: Feature[] = [
|
||||||
|
{
|
||||||
|
text: 'ngx-admin template with 100+ UI components integrated with Backend Services',
|
||||||
|
availableInPersonalLicence: true,
|
||||||
|
availableInCommercialLicence: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Backend Services and Repository layers with data access',
|
||||||
|
availableInPersonalLicence: true,
|
||||||
|
availableInCommercialLicence: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'JWT Authentication setup for UI and Backend',
|
||||||
|
availableInPersonalLicence: true,
|
||||||
|
availableInCommercialLicence: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Running instructions and code documentation',
|
||||||
|
availableInPersonalLicence: true,
|
||||||
|
availableInCommercialLicence: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Commercial Usage',
|
||||||
|
availableInPersonalLicence: true,
|
||||||
|
availableInCommercialLicence: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Create multiple end products using bundle',
|
||||||
|
availableInPersonalLicence: false,
|
||||||
|
availableInCommercialLicence: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Bug fixes and questions according to license terms',
|
||||||
|
availableInPersonalLicence: false,
|
||||||
|
availableInCommercialLicence: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
|
getFeatures(): Observable<Feature[]> {
|
||||||
|
return observableOf(this.features);
|
||||||
|
}
|
||||||
|
|
||||||
|
getProducts(url: string): Observable<Product[]> {
|
||||||
|
return this.http.get(url)
|
||||||
|
.pipe(map((result: any) => {
|
||||||
|
return result.products.map((item: any) => {
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
imageUrl: this.getDefaultImage(item.images),
|
||||||
|
storeUrl: `${this.STORE_COLLECTION}/${item.handle}`,
|
||||||
|
tags: item.tags,
|
||||||
|
title: item.title,
|
||||||
|
description: (item.body_html as string).trim().replace(/<(?:.|\n)*?>/gm, ' ').replace(/ +/gm, ' '),
|
||||||
|
variants: item.variants.map(variant => {
|
||||||
|
return {
|
||||||
|
available: variant.available,
|
||||||
|
compare_at_price: variant.compare_at_price,
|
||||||
|
price: variant.price,
|
||||||
|
title: variant.title,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
getDefaultImage(images: any[]): any {
|
||||||
|
const defaultImage = images.reduce((value, current) => {
|
||||||
|
if (!value) {
|
||||||
|
value = current;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
return defaultImage ? this.trimImageUrl(defaultImage.src) : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
trimImageUrl(url: string): string {
|
||||||
|
return url.substring(0, url.indexOf('?'));
|
||||||
|
}
|
||||||
|
}
|
68
docs/app/@core/data/service/descriptions.service.ts
Normal file
68
docs/app/@core/data/service/descriptions.service.ts
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { of as observableOf, Observable } from 'rxjs';
|
||||||
|
|
||||||
|
export class Descriptions {
|
||||||
|
icon: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DescriptionsService {
|
||||||
|
|
||||||
|
/* tslint:disable:max-line-length */
|
||||||
|
private descriptions: Descriptions[] = [
|
||||||
|
{
|
||||||
|
icon: 'layout-outline',
|
||||||
|
title: 'Efficient',
|
||||||
|
description: 'Packed with a huge number of handcrafted UI components, charts, maps, editors, tables, and much more, so that developers can focus on business needs',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'smartphone-outline',
|
||||||
|
title: 'Mobile first',
|
||||||
|
description: 'Looks stunning on every screen size and is optimized to bring the large-screen experience from desktop to mobile',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'color-palette-outline',
|
||||||
|
title: 'Сustomizable',
|
||||||
|
description: 'With 4 themes, 2 dashboards, and outstanding UI architecture, it’s easy to change the themes and find the right fit for your company',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'heart-outline',
|
||||||
|
title: 'Updated and supported',
|
||||||
|
description: 'Continuous updates and fixes from the development team to keep your tech up to date. The friendly and active community support team are ready to guide you through your challenges',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
private bundleDescriptions: Descriptions[] = [
|
||||||
|
{
|
||||||
|
icon: 'umbrella-outline',
|
||||||
|
title: 'Convenient',
|
||||||
|
description: 'Complete pack of well known Angular based ngx-admin template, integrated with Backend Solution of your choice. Finally, you can get fully integrated solution out of the box.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'settings-2-outline',
|
||||||
|
title: 'Functional',
|
||||||
|
description: 'Deploy it as ready to use solution for a particular case, or give it to your development team to incrementally add functionality. It provides a significant boost and solid development structure.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'clock-outline',
|
||||||
|
title: 'Efficient',
|
||||||
|
description: 'Save more than $21,000 using Backend Bundle. According to our research ready Backend Bundle optimizes around 300 hours of development time.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'checkmark-circle-2-outline',
|
||||||
|
title: 'Ready to use',
|
||||||
|
description: 'We prepared this Backend pack as development basement which lets your team concentrate on business logic and data models.',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
/* tslint:disable:max-line-length */
|
||||||
|
|
||||||
|
getDescriptions(): Observable<Descriptions[]> {
|
||||||
|
return observableOf(this.descriptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
getBundleDescriptions(): Observable<Descriptions[]> {
|
||||||
|
return observableOf(this.bundleDescriptions);
|
||||||
|
}
|
||||||
|
}
|
27
docs/app/@core/data/service/header-menu.service.ts
Normal file
27
docs/app/@core/data/service/header-menu.service.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { of as observableOf, Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import { NbMenuItem } from '@nebular/theme';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class HeaderMenuService {
|
||||||
|
|
||||||
|
private headerMenu: NbMenuItem[] = [
|
||||||
|
{
|
||||||
|
title: 'Home',
|
||||||
|
link: '/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Docs',
|
||||||
|
link: '/docs',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Demo',
|
||||||
|
url: 'https://www.akveo.com/ngx-admin?utm_campaign=ngx_admin%20-%20demo%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=landing_main_section',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
getHeaderMenu(): Observable<NbMenuItem[]> {
|
||||||
|
return observableOf(this.headerMenu);
|
||||||
|
}
|
||||||
|
}
|
72
docs/app/@core/data/service/reviews.service.ts
Normal file
72
docs/app/@core/data/service/reviews.service.ts
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { of as observableOf, Observable } from 'rxjs';
|
||||||
|
|
||||||
|
export class Review {
|
||||||
|
avatar: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
socialIcon: string;
|
||||||
|
review: string;
|
||||||
|
link: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ReviewsService {
|
||||||
|
|
||||||
|
/* tslint:disable:max-line-length */
|
||||||
|
private reviews: Review[] = [
|
||||||
|
{
|
||||||
|
avatar: 'assets/img/avatars/1.png',
|
||||||
|
firstName: 'Marcin',
|
||||||
|
lastName: 'Masiorski',
|
||||||
|
socialIcon: 'facebook',
|
||||||
|
review: 'Awesome template! You are doing great job! Regards.',
|
||||||
|
link: 'https://www.facebook.com/pg/akveo/reviews/?ref=page_internal',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
avatar: 'assets/img/avatars/2.png',
|
||||||
|
firstName: 'Rashid',
|
||||||
|
lastName: 'Thompson',
|
||||||
|
socialIcon: 'facebook',
|
||||||
|
review: 'I just want to say you have the best admin template I have seen so far as a new developer (Trust me I have searched).',
|
||||||
|
link: 'https://www.facebook.com/pg/akveo/reviews/?ref=page_internal',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
avatar: 'assets/img/avatars/3.png',
|
||||||
|
firstName: 'Yuriy',
|
||||||
|
lastName: 'Marshall',
|
||||||
|
socialIcon: 'facebook',
|
||||||
|
review: 'Thanks for free angular theme! Design and file/system structure is on high level! Love you, Akveo!)',
|
||||||
|
link: 'https://www.facebook.com/pg/akveo/reviews/?ref=page_internal',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
avatar: 'assets/img/avatars/4.png',
|
||||||
|
firstName: 'Kenneth',
|
||||||
|
lastName: 'Reis',
|
||||||
|
socialIcon: 'facebook',
|
||||||
|
review: 'Nice people working hard for high quality projects. Love you guys!',
|
||||||
|
link: 'https://www.facebook.com/pg/akveo/reviews/?ref=page_internal',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
avatar: 'assets/img/avatars/5.png',
|
||||||
|
firstName: 'Renato',
|
||||||
|
lastName: 'Oliveira Silva',
|
||||||
|
socialIcon: 'facebook',
|
||||||
|
review: 'Great company and great projects',
|
||||||
|
link: 'https://www.facebook.com/pg/akveo/reviews/?ref=page_internal',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
avatar: 'assets/img/avatars/6.png',
|
||||||
|
firstName: 'Mohammed',
|
||||||
|
lastName: 'Benyakoub',
|
||||||
|
socialIcon: 'facebook',
|
||||||
|
review: 'That one of the best open source software - Product I have ever seen',
|
||||||
|
link: 'https://www.facebook.com/pg/akveo/reviews/?ref=page_internal',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
/* tslint:enable:max-line-length */
|
||||||
|
|
||||||
|
getReviews(): Observable<Review[]> {
|
||||||
|
return observableOf(this.reviews);
|
||||||
|
}
|
||||||
|
}
|
11
docs/app/@core/module-import-guard.ts
Normal file
11
docs/app/@core/module-import-guard.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function throwIfAlreadyLoaded(parentModule: any, moduleName: string) {
|
||||||
|
if (parentModule) {
|
||||||
|
throw new Error(`${moduleName} has already been loaded. Import Core modules in the AppModule only.`);
|
||||||
|
}
|
||||||
|
}
|
45
docs/app/@theme/components/docs-footer/footer.component.html
Normal file
45
docs/app/@theme/components/docs-footer/footer.component.html
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<div class="logo">
|
||||||
|
<a href="https://www.akveo.com?utm_campaign=services%20-%20homepage%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_docs_footer_link_logo" target="_blank"><img src="assets/img/akveo-logo.png" alt="Akveo logo"></a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<ul>
|
||||||
|
<li><strong class="title">More from Akveo</strong></li>
|
||||||
|
<li><a href="https://www.akveo.com?utm_campaign=services%20-%20homepage%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_docs_footer_link_homepage" target="_blank">Homepage</a></li>
|
||||||
|
<li><a href="https://akveo.github.io/eva-icons?utm_campaign=eva_icons%20-%20home%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=docs_footer">Eva Icons</a></li>
|
||||||
|
<li><a href="https://akveo.github.io/react-native-ui-kitten?utm_campaign=ui_kitten%20-%20home%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=docs_footer">React Native UI Kitten</a></li>
|
||||||
|
<li><a href="https://www.akveo.com/ngx-admin?utm_campaign=ngx_admin%20-%20demo%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=docs_footer_link"
|
||||||
|
target="_blank">ngx-admin</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<ul>
|
||||||
|
<li><strong class="title">Follow Us</strong></li>
|
||||||
|
<li class="social">
|
||||||
|
<a href="https://github.com/akveo/ngx-admin"
|
||||||
|
aria-label="github"
|
||||||
|
target="_blank">
|
||||||
|
<i [innerHTML]="'github-outline' | eva: { width: 30, height: 30, fill: '#f7f8fa' }"></i>
|
||||||
|
</a>
|
||||||
|
<a href="https://twitter.com/akveo_inc"
|
||||||
|
aria-label="twitter"
|
||||||
|
target="_blank">
|
||||||
|
<i [innerHTML]="'twitter' | eva: { width: 30, height: 30, fill: '#f7f8fa' }"></i>
|
||||||
|
</a>
|
||||||
|
<a href="https://www.facebook.com/akveo"
|
||||||
|
aria-label="facebook"
|
||||||
|
target="_blank">
|
||||||
|
<i [innerHTML]="'facebook' | eva: { width: 35, height: 35, fill: '#f7f8fa' }"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="copy">
|
||||||
|
© 2015-2019 <a href="https://www.akveo.com?utm_campaign=services%20-%20homepage%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_docs_footer_link_akveo_llc" target="_blank">Akveo LLC</a><br>
|
||||||
|
Documentation licensed under CC BY 4.0.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="contact">
|
||||||
|
<ul>
|
||||||
|
<li><strong class="title">Contact Us</strong></li>
|
||||||
|
<li><a href="mailto:contact@akveo.com">contact@akveo.com</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
119
docs/app/@theme/components/docs-footer/footer.component.scss
Normal file
119
docs/app/@theme/components/docs-footer/footer.component.scss
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
@import '~@nebular/theme/styles/global/breakpoints';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
|
||||||
|
$text-fg: nb-theme(footer-text-color);
|
||||||
|
$social-fg: nb-theme(text-hint-color);
|
||||||
|
$title-fg: nb-theme(text-basic-color);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding-top: 1.25rem;
|
||||||
|
justify-content: space-around;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
display: flex;
|
||||||
|
margin-right: 0;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $text-fg;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.logo {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: $title-fg;
|
||||||
|
font-size: 1.125rem;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 1.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy {
|
||||||
|
color: $text-fg;
|
||||||
|
display: list-item;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 2.5rem;
|
||||||
|
height: 2.5rem;
|
||||||
|
background-color: $social-fg;
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
text-decoration: none;
|
||||||
|
margin-right: 1.5rem;
|
||||||
|
line-height: 0.5;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> div.logo {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
> div {
|
||||||
|
justify-content: flex-start;
|
||||||
|
margin-right: 2rem;
|
||||||
|
width: auto;
|
||||||
|
|
||||||
|
li {
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(lg) {
|
||||||
|
> div.logo {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: -2.5rem;
|
||||||
|
text-align: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 9rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
docs/app/@theme/components/docs-footer/footer.component.ts
Normal file
10
docs/app/@theme/components/docs-footer/footer.component.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-docs-footer',
|
||||||
|
styleUrls: ['./footer.component.scss'],
|
||||||
|
templateUrl: './footer.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxDocsFooterComponent {
|
||||||
|
}
|
51
docs/app/@theme/components/footer/footer.component.html
Normal file
51
docs/app/@theme/components/footer/footer.component.html
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
<div class="logo">
|
||||||
|
<a href="https://www.akveo.com?utm_campaign=services%20-%20homepage%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_landing_footer_link_logo" target="_blank"><img src="assets/img/akveo-logo.png" alt="Akveo logo"></a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<ul>
|
||||||
|
<li><span class="h6">More from Akveo</span></li>
|
||||||
|
<li><a href="https://www.akveo.com?utm_campaign=services%20-%20homepage%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_landing_footer_link_homepage" target="_blank">Homepage</a></li>
|
||||||
|
<li><a href="https://akveo.github.io/nebular?utm_campaign=nebular%20-%20home%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=landing_footer_link">Nebular</a></li>
|
||||||
|
<li><a href="https://akveo.github.io/eva-icons?utm_campaign=eva_icons%20-%20home%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=landing_footer">Eva Icons</a></li>
|
||||||
|
<li><a href="https://akveo.github.io/react-native-ui-kitten?utm_campaign=ui_kitten%20-%20home%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=landing_footer">React Native UI Kitten</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="social-container">
|
||||||
|
<ul>
|
||||||
|
<li><span class="h6">Follow Us</span></li>
|
||||||
|
<li class="social">
|
||||||
|
<a href="https://github.com/akveo/ngx-admin"
|
||||||
|
aria-label="github"
|
||||||
|
target="_blank">
|
||||||
|
<i [innerHTML]="'github-outline' | eva: { width: 30, height: 30, fill: '#f7f8fa' }"></i>
|
||||||
|
</a>
|
||||||
|
<a href="https://twitter.com/akveo_inc"
|
||||||
|
aria-label="twitter"
|
||||||
|
target="_blank">
|
||||||
|
<i [innerHTML]="'twitter' | eva: { width: 30, height: 30, fill: '#f7f8fa' }"></i>
|
||||||
|
</a>
|
||||||
|
<a href="https://www.facebook.com/akveo"
|
||||||
|
aria-label="facebook"
|
||||||
|
target="_blank">
|
||||||
|
<i [innerHTML]="'facebook' | eva: { width: 35, height: 35, fill: '#f7f8fa' }"></i>
|
||||||
|
</a>
|
||||||
|
<a href="https://www.linkedin.com/company/akveo"
|
||||||
|
aria-label="linkedIn"
|
||||||
|
target="_blank">
|
||||||
|
<i [innerHTML]="'linkedin' | eva: { width: 35, height: 35, fill: '#f7f8fa' }"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="copy">
|
||||||
|
© 2015-{{currentYear}} <a href="https://www.akveo.com?utm_campaign=services%20-%20homepage%20-%20ngx_admin%20docs&utm_source=ngx_admin&utm_medium=referral&utm_content=ngx_admin_landing_footer_link_akveo_llc" target="_blank">Akveo LLC</a><br>
|
||||||
|
Documentation licensed under CC BY 4.0.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="contact">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<span class="h6">Contact Us</span>
|
||||||
|
</li>
|
||||||
|
<li><a href="mailto:contact@akveo.com">contact@akveo.com</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
182
docs/app/@theme/components/footer/footer.component.scss
Normal file
182
docs/app/@theme/components/footer/footer.component.scss
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
@import '~@nebular/theme/styles/global/breakpoints';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
$text-fg: nb-theme(footer-text-color);
|
||||||
|
$social-fg: nb-theme(text-hint-color);
|
||||||
|
$title-fg: nb-theme(text-basic-color);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding-top: 2.75rem;
|
||||||
|
justify-content: flex-start;
|
||||||
|
margin: 0.375rem 10.25rem 0;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
display: flex;
|
||||||
|
margin-right: 0;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
margin-top: 0.375rem;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-size: nb-theme(font-size);
|
||||||
|
color: $text-fg;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
font-weight: normal;
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-bottom: 1.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy {
|
||||||
|
$copy-color: #535b6c;
|
||||||
|
|
||||||
|
color: $copy-color;
|
||||||
|
display: list-item;
|
||||||
|
font-size: 0.66rem;
|
||||||
|
line-height: 1.75;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-size: 0.65rem;
|
||||||
|
color: $copy-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.social {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 2.5rem;
|
||||||
|
height: 2.5rem;
|
||||||
|
background-color: $social-fg;
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
text-decoration: none;
|
||||||
|
margin-right: 1.5rem;
|
||||||
|
line-height: 0.5;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> div.logo {
|
||||||
|
margin-bottom: 3.125rem;
|
||||||
|
|
||||||
|
a {
|
||||||
|
width: 10rem;
|
||||||
|
height: 10rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
justify-content: space-around;
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
|
||||||
|
> div.logo {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
justify-content: flex-start;
|
||||||
|
margin-right: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
width: auto;
|
||||||
|
|
||||||
|
li {
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(lg) {
|
||||||
|
margin-right: 2rem;
|
||||||
|
margin-left: 2rem;
|
||||||
|
|
||||||
|
> div.logo {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(xxl) {
|
||||||
|
justify-content: flex-start;
|
||||||
|
margin: 0.375rem 10.25rem 0;
|
||||||
|
|
||||||
|
> div.logo {
|
||||||
|
margin-right: 7.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
margin-right: 8.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.company-info {
|
||||||
|
margin-right: 12.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-container {
|
||||||
|
margin-right: 6.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-down(md) {
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
margin-right: 0;
|
||||||
|
|
||||||
|
&.logo {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-container {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
docs/app/@theme/components/footer/footer.component.ts
Normal file
18
docs/app/@theme/components/footer/footer.component.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-landing-footer',
|
||||||
|
styleUrls: ['./footer.component.scss'],
|
||||||
|
templateUrl: './footer.component.html',
|
||||||
|
})
|
||||||
|
export class NgxLandingFooterComponent {
|
||||||
|
get currentYear() {
|
||||||
|
return new Date().getFullYear();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { Directive, ElementRef, Inject, Input, OnDestroy, OnInit, Renderer2 } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { NB_WINDOW } from '@nebular/theme';
|
||||||
|
import { delay, takeWhile, publish, refCount } from 'rxjs/operators';
|
||||||
|
import { NgxTocElement, NgxTocStateService } from '../../services/toc-state.service';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
// tslint:disable-next-line
|
||||||
|
selector: '[ngxFragment]',
|
||||||
|
})
|
||||||
|
export class NgxFragmentTargetDirective implements OnInit, OnDestroy, NgxTocElement {
|
||||||
|
@Input() ngxFragment: string;
|
||||||
|
@Input() ngxFragmentClass: string;
|
||||||
|
@Input() ngxFragmentSync: boolean = true;
|
||||||
|
|
||||||
|
private inView = false;
|
||||||
|
private alive = true;
|
||||||
|
private readonly marginFromTop = 120;
|
||||||
|
|
||||||
|
get fragment(): string {
|
||||||
|
return this.ngxFragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
get element(): any {
|
||||||
|
return this.el.nativeElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
get y(): number {
|
||||||
|
return this.element.getBoundingClientRect().y;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private activatedRoute: ActivatedRoute,
|
||||||
|
@Inject(NB_WINDOW) private window,
|
||||||
|
private tocState: NgxTocStateService,
|
||||||
|
private el: ElementRef,
|
||||||
|
private renderer: Renderer2,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.ngxFragmentSync && this.tocState.add(this);
|
||||||
|
|
||||||
|
this.activatedRoute.fragment
|
||||||
|
.pipe(publish(null), refCount(), takeWhile(() => this.alive), delay(10))
|
||||||
|
.subscribe((fragment: string) => {
|
||||||
|
if (fragment && this.fragment === fragment && !this.inView) {
|
||||||
|
this.selectFragment();
|
||||||
|
} else {
|
||||||
|
this.deselectFragment();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
selectFragment() {
|
||||||
|
this.ngxFragmentClass && this.renderer.addClass(this.el.nativeElement, this.ngxFragmentClass);
|
||||||
|
this.setInView(true);
|
||||||
|
this.window.scrollTo(0, this.el.nativeElement.offsetTop - this.marginFromTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
deselectFragment() {
|
||||||
|
this.renderer.removeClass(this.el.nativeElement, this.ngxFragmentClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
setInView(val: boolean) {
|
||||||
|
this.inView = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.alive = false;
|
||||||
|
this.ngxFragmentSync && this.tocState.remove(this);
|
||||||
|
}
|
||||||
|
}
|
28
docs/app/@theme/components/header/header.component.html
Normal file
28
docs/app/@theme/components/header/header.component.html
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<div class="section left">
|
||||||
|
<button *ngIf="sidebarTag" class="sidebar-toggle" (click)="toggleSidebar()">
|
||||||
|
<i class="nb-menu"></i>
|
||||||
|
</button>
|
||||||
|
<div class="logo">
|
||||||
|
<a routerLink="/">ngx-admin</a>
|
||||||
|
<span class="version">v{{ currentVersion }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section middle">
|
||||||
|
<div class="first-section">
|
||||||
|
<nb-menu [items]="headerMenu"></nb-menu>
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="section right">
|
||||||
|
|
||||||
|
<iframe *ngIf="isDocs"
|
||||||
|
class="stars"
|
||||||
|
src="https://ghbtns.com/github-btn.html?user=akveo&repo=ngx-admin&type=star&count=true"
|
||||||
|
frameborder="0"
|
||||||
|
scrolling="0">
|
||||||
|
</iframe>
|
||||||
|
</div>
|
332
docs/app/@theme/components/header/header.component.scss
Normal file
332
docs/app/@theme/components/header/header.component.scss
Normal file
|
@ -0,0 +1,332 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
@import '~@nebular/theme/styles/global/breakpoints';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
$left-section-width: nb-theme(sidebar-width);
|
||||||
|
$right-section-width: nb-theme(settings-col-width);
|
||||||
|
$logo-fg: nb-theme(header-text-color);
|
||||||
|
$version-fg: nb-theme(text-hint-color);
|
||||||
|
$menu-item-fg: nb-theme(color-fg-heading-light);
|
||||||
|
$menu-item-fg-active: nb-theme(header-menu-fg-active);
|
||||||
|
$contacts-fg: nb-theme(color-fg-heading-light);
|
||||||
|
$contacts-active-fg: nb-theme(header-menu-fg-active);
|
||||||
|
$menu-sm-padding: 0.675rem 0.375rem;
|
||||||
|
$menu-md-padding: 0.675rem 1.375rem;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.section {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.875rem 0.5rem;
|
||||||
|
|
||||||
|
.first-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.left {
|
||||||
|
width: $left-section-width;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.middle {
|
||||||
|
flex: 1;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
display: flex;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-size: 1.275rem;
|
||||||
|
color: $logo-fg;
|
||||||
|
text-decoration: none !important;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: $version-fg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.backend-bundles {
|
||||||
|
display: none;
|
||||||
|
align-items: center;
|
||||||
|
padding-right: 2rem;
|
||||||
|
margin-left: auto;
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep nb-menu {
|
||||||
|
|
||||||
|
.menu-items {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.menu-item {
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
a {
|
||||||
|
padding: $menu-sm-padding;
|
||||||
|
color: $menu-item-fg;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
&:hover, &.active, &:focus {
|
||||||
|
color: $menu-item-fg-active;
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
li:first-child {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.section.right {
|
||||||
|
color: $contacts-fg;
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-family: nb-theme(font-main), sans-serif;
|
||||||
|
color: $contacts-active-fg;
|
||||||
|
margin-left: 0.375rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep ngx-material-theme-link a.material-theme-link {
|
||||||
|
padding: $menu-sm-padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(is) {
|
||||||
|
.section.left,
|
||||||
|
.section.right {
|
||||||
|
padding: 0.875rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section.middle {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(sm) {
|
||||||
|
.logo {
|
||||||
|
align-items: baseline;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #000000;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep {
|
||||||
|
nb-menu .menu-items .menu-item a,
|
||||||
|
ngx-material-theme-link a.material-theme-link {
|
||||||
|
padding: $menu-md-padding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
.logo {
|
||||||
|
flex: 1 0 auto;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
.version {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep nb-menu .menu-items li:nth-child(2) {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
.backend-bundles {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(lg) {
|
||||||
|
::ng-deep nb-menu .menu-items {
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
li:not(:first-child) {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.section.right {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(xl) {
|
||||||
|
.sidebar-toggle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@include media-breakpoint-down(sm) {
|
||||||
|
::ng-deep nb-menu {
|
||||||
|
.menu-items {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-down(is) {
|
||||||
|
padding: 0 0 0 1rem;
|
||||||
|
|
||||||
|
.section {
|
||||||
|
&.left {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
flex: 1 0 auto;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.docs-page {
|
||||||
|
|
||||||
|
.section {
|
||||||
|
|
||||||
|
.first-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.left {
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 0;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.middle {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
display: none;
|
||||||
|
margin-left: 0;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-toggle {
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
line-height: 1rem;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
|
||||||
|
.nb-menu {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep nb-menu {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 1;
|
||||||
|
flex-basis: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep ngx-material-theme-link {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(is) {
|
||||||
|
::ng-deep ngx-material-theme-link {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(sm) {
|
||||||
|
::ng-deep nb-menu .menu-items li:first-child {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section.middle {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stars {
|
||||||
|
width: 7.5rem;
|
||||||
|
height: 1.25rem;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(lg) {
|
||||||
|
.section.middle {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
::ng-deep nb-menu {
|
||||||
|
.menu-items li {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.section.right {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(xl) {
|
||||||
|
.section.left {
|
||||||
|
padding-left: 1.125rem;
|
||||||
|
width: nb-theme(sidebar-width);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-toggle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep nb-menu {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(macpro) {
|
||||||
|
.section.right {
|
||||||
|
margin-left: 1.875rem;
|
||||||
|
width: $right-section-width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
docs/app/@theme/components/header/header.component.ts
Normal file
52
docs/app/@theme/components/header/header.component.ts
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { OnInit, Component, HostBinding, Input, OnDestroy } from '@angular/core';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
import { NbSidebarService } from '@nebular/theme';
|
||||||
|
|
||||||
|
import { NgxVersionService } from '../../services/version.service';
|
||||||
|
import { HeaderMenuService } from '../../../@core/data/service/header-menu.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-landing-header',
|
||||||
|
styleUrls: ['./header.component.scss'],
|
||||||
|
templateUrl: './header.component.html',
|
||||||
|
})
|
||||||
|
export class NgxLandingHeaderComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
private destroy$ = new Subject<void>();
|
||||||
|
|
||||||
|
@HostBinding('class.docs-page') @Input() isDocs = false;
|
||||||
|
|
||||||
|
@Input() sidebarTag: string = '';
|
||||||
|
|
||||||
|
currentVersion: string;
|
||||||
|
headerMenu = [];
|
||||||
|
|
||||||
|
constructor(private sidebarService: NbSidebarService,
|
||||||
|
private versionService: NgxVersionService,
|
||||||
|
private headerMenuService: HeaderMenuService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.currentVersion = this.versionService.getNgxVersion();
|
||||||
|
|
||||||
|
this.headerMenuService.getHeaderMenu()
|
||||||
|
.pipe(takeUntil(this.destroy$))
|
||||||
|
.subscribe((headerMenu) => this.headerMenu = headerMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleSidebar() {
|
||||||
|
this.sidebarService.toggle(false, this.sidebarTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
}
|
23
docs/app/@theme/components/index.ts
Normal file
23
docs/app/@theme/components/index.ts
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { NgxLandingFooterComponent } from './footer/footer.component';
|
||||||
|
import { NgxLandingHeaderComponent } from './header/header.component';
|
||||||
|
import { NgxSectionTitleComponent } from './section-title/section-title.component';
|
||||||
|
import { NgxPageTabsComponent } from './page-tabs/page-tabs.component';
|
||||||
|
import { NgxPageTocComponent } from './page-toc/page-toc.component';
|
||||||
|
import { NgxFragmentTargetDirective } from './fragment-target/fragment-target.directive';
|
||||||
|
import { NgxDocsFooterComponent } from './docs-footer/footer.component';
|
||||||
|
|
||||||
|
export {
|
||||||
|
NgxLandingHeaderComponent,
|
||||||
|
NgxLandingFooterComponent,
|
||||||
|
NgxSectionTitleComponent,
|
||||||
|
NgxPageTabsComponent,
|
||||||
|
NgxPageTocComponent,
|
||||||
|
NgxFragmentTargetDirective,
|
||||||
|
NgxDocsFooterComponent,
|
||||||
|
};
|
101
docs/app/@theme/components/page-tabs/page-tabs.component.scss
Normal file
101
docs/app/@theme/components/page-tabs/page-tabs.component.scss
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
$tabs-fg: nb-theme(color-fg-heading-light);
|
||||||
|
$tabs-fg-active: nb-theme(color-fg-heading);
|
||||||
|
$tabs-bg-active: nb-theme(color-white);
|
||||||
|
$tabs-shadow: 0 8px 20px 0 rgba(218, 224, 235, 0.6);
|
||||||
|
$tabs-accent-line: nb-theme(color-fg-highlight);
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
padding: 1rem;
|
||||||
|
width: 50%;
|
||||||
|
height: 7.5rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
text-decoration: none;
|
||||||
|
color: $tabs-fg;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding-bottom: 0.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background: white;
|
||||||
|
color: $tabs-fg-active;
|
||||||
|
box-shadow: $tabs-shadow;
|
||||||
|
|
||||||
|
.line {
|
||||||
|
height: 0.1875rem;
|
||||||
|
width: 60%;
|
||||||
|
background: $tabs-accent-line;
|
||||||
|
border-radius: 1.5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon,
|
||||||
|
.title {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:host(.horizontal) {
|
||||||
|
a {
|
||||||
|
flex: 0 0 50%;
|
||||||
|
height: auto;
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding: 0 1rem;
|
||||||
|
|
||||||
|
.title,
|
||||||
|
.icon {
|
||||||
|
display: inline;
|
||||||
|
padding-bottom: 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-container {
|
||||||
|
padding-bottom: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
order: -1;
|
||||||
|
margin-bottom: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 40em) {
|
||||||
|
flex: 1 1 0;
|
||||||
|
|
||||||
|
a {
|
||||||
|
flex: 1 1 0;
|
||||||
|
|
||||||
|
&.selected::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
border-left: 1rem solid transparent;
|
||||||
|
border-right: 1rem solid transparent;
|
||||||
|
border-top: 1rem solid #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
87
docs/app/@theme/components/page-tabs/page-tabs.component.ts
Normal file
87
docs/app/@theme/components/page-tabs/page-tabs.component.ts
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ChangeDetectionStrategy, Component, Input, OnDestroy, HostBinding } from '@angular/core';
|
||||||
|
import { takeWhile, map, publishReplay, refCount } from 'rxjs/operators';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { Observable, of as observableOf, combineLatest } from 'rxjs';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-page-tabs',
|
||||||
|
styleUrls: ['./page-tabs.component.scss'],
|
||||||
|
template: `
|
||||||
|
<a *ngFor="let item of items$ | async" [class.selected]="item.selected" [routerLink]="['../', item.tab]">
|
||||||
|
<div class="text-container">
|
||||||
|
<i class="icon {{ item.icon }}"></i>
|
||||||
|
<span class="title">{{ item.title }}</span>
|
||||||
|
</div>
|
||||||
|
<i class="line"></i>
|
||||||
|
</a>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxPageTabsComponent implements OnDestroy {
|
||||||
|
|
||||||
|
items$: Observable<any[]> = observableOf([]);
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
set tabs(value) {
|
||||||
|
this.items$ = combineLatest(
|
||||||
|
observableOf(value || []).pipe(
|
||||||
|
map(tabs => this.availableTabs.filter(tab => tabs[tab.tab])),
|
||||||
|
),
|
||||||
|
this.activatedRoute.params.pipe(publishReplay(), refCount()),
|
||||||
|
)
|
||||||
|
.pipe(
|
||||||
|
takeWhile(() => this.alive),
|
||||||
|
map(([tabs, params]) => (tabs.map((item: any) => ({ ...item, selected: item.tab === params.tab })))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostBinding('class.horizontal')
|
||||||
|
isHorizontal = false;
|
||||||
|
@Input()
|
||||||
|
set horizontal(value) {
|
||||||
|
this.isHorizontal = value !== 'false' && value !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private availableTabs: {
|
||||||
|
tab: string;
|
||||||
|
title: string;
|
||||||
|
icon: string;
|
||||||
|
selected?: boolean;
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
tab: 'overview',
|
||||||
|
title: 'Overview',
|
||||||
|
icon: 'feather-eye',
|
||||||
|
selected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tab: 'api',
|
||||||
|
title: 'API',
|
||||||
|
icon: 'feather-settings',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tab: 'theme',
|
||||||
|
title: 'Theme',
|
||||||
|
icon: 'feather-droplet',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tab: 'examples',
|
||||||
|
title: 'Examples',
|
||||||
|
icon: 'feather-image',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
private alive = true;
|
||||||
|
|
||||||
|
constructor(private activatedRoute: ActivatedRoute) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.alive = false;
|
||||||
|
}
|
||||||
|
}
|
50
docs/app/@theme/components/page-toc/page-toc.component.scss
Normal file
50
docs/app/@theme/components/page-toc/page-toc.component.scss
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
|
||||||
|
$title-fg: nb-theme(color-fg-heading-light);
|
||||||
|
$item-fg: rgba(102, 110, 128, 0.87);
|
||||||
|
$item-fg-active: #202020;
|
||||||
|
$accent-line-bg: nb-theme(color-fg-highlight);
|
||||||
|
|
||||||
|
padding-left: 1rem;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
color: $title-fg;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 3.25rem;
|
||||||
|
font-size: 0.9375rem;
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-bottom: 0.9375rem;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: $item-fg;
|
||||||
|
}
|
||||||
|
|
||||||
|
li.selected a {
|
||||||
|
font-weight: 500;
|
||||||
|
color: $item-fg-active;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: -3.25rem;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
height: 0.1875rem;
|
||||||
|
width: 2rem;
|
||||||
|
background: $accent-line-bg;
|
||||||
|
border-radius: 1.5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
docs/app/@theme/components/page-toc/page-toc.component.ts
Normal file
67
docs/app/@theme/components/page-toc/page-toc.component.ts
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Component,
|
||||||
|
Input,
|
||||||
|
OnDestroy,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { takeWhile, map } from 'rxjs/operators';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { of as observableOf, combineLatest } from 'rxjs';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-page-toc',
|
||||||
|
styleUrls: ['./page-toc.component.scss'],
|
||||||
|
template: `
|
||||||
|
<ng-container *ngIf="items?.length > 0">
|
||||||
|
<h4>Overview</h4>
|
||||||
|
<ul>
|
||||||
|
<li *ngFor="let item of items" [class.selected]="item.selected">
|
||||||
|
<a [routerLink]="item.link" [fragment]="item.fragment">{{ item.title }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</ng-container>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxPageTocComponent implements OnDestroy {
|
||||||
|
|
||||||
|
items: any[];
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
set toc(value) {
|
||||||
|
combineLatest(
|
||||||
|
observableOf(value || []),
|
||||||
|
this.activatedRoute.fragment,
|
||||||
|
)
|
||||||
|
.pipe(
|
||||||
|
takeWhile(() => this.alive),
|
||||||
|
map(([toc, fragment]) => {
|
||||||
|
toc = toc.map((item: any) => ({ ...item, selected: fragment === item.fragment }));
|
||||||
|
if (toc.length && !toc.find(item => item.selected)) {
|
||||||
|
toc[0].selected = true;
|
||||||
|
}
|
||||||
|
return toc;
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.subscribe((toc) => {
|
||||||
|
this.items = toc;
|
||||||
|
this.cd.detectChanges();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private alive = true;
|
||||||
|
|
||||||
|
constructor(private activatedRoute: ActivatedRoute, private cd: ChangeDetectorRef) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.alive = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h2>
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</h2>
|
|
@ -0,0 +1,24 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
@import '~@nebular/theme/styles/global/breakpoints';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
h2 {
|
||||||
|
font-family: 'Helvetica Neue Bold', sans-serif;
|
||||||
|
font-size: 2rem;
|
||||||
|
color: #000000;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@include media-breakpoint-down(is) {
|
||||||
|
h2 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-landing-section-title',
|
||||||
|
templateUrl: './section-title.component.html',
|
||||||
|
styleUrls: ['./section-title.component.scss'],
|
||||||
|
})
|
||||||
|
export class NgxSectionTitleComponent {
|
||||||
|
|
||||||
|
}
|
28
docs/app/@theme/services/analytics.service.ts
Normal file
28
docs/app/@theme/services/analytics.service.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Injectable, Inject } from '@angular/core';
|
||||||
|
import { NB_WINDOW } from '@nebular/theme';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NgxAnalytics {
|
||||||
|
private enabled: boolean;
|
||||||
|
|
||||||
|
constructor(@Inject(NB_WINDOW) private window) {
|
||||||
|
this.enabled = this.window.location.href.indexOf('akveo.github.io') >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
trackEvent(eventName: string, eventVal: string = '') {
|
||||||
|
if (this.enabled) {
|
||||||
|
this.gtmPushToDataLayer({ event: eventName, eventValue: eventVal });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push to 'dataLayer' Google Tag Manager array
|
||||||
|
private gtmPushToDataLayer(params) {
|
||||||
|
this.window.dataLayer.push(params);
|
||||||
|
}
|
||||||
|
}
|
39
docs/app/@theme/services/code-loader.service.ts
Normal file
39
docs/app/@theme/services/code-loader.service.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { publishReplay , refCount } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NgxCodeLoaderService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains cached files by url.
|
||||||
|
* */
|
||||||
|
private cache: Map<string, Observable<string>> = new Map();
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {
|
||||||
|
}
|
||||||
|
|
||||||
|
load(path: string): Observable<string> {
|
||||||
|
const url = this.buildFilePath(path);
|
||||||
|
const cached = this.cache.get(url);
|
||||||
|
|
||||||
|
return cached ? cached : this.buildRequest(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildFilePath(path: string): string {
|
||||||
|
return `assets/examples/${path}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildRequest(url): Observable<string> {
|
||||||
|
const request = this.http.get(url, { responseType: 'text' })
|
||||||
|
.pipe(
|
||||||
|
publishReplay(1),
|
||||||
|
refCount(),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.cache.set(url, request);
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
}
|
23
docs/app/@theme/services/dialog-state.service.ts
Normal file
23
docs/app/@theme/services/dialog-state.service.ts
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable, ReplaySubject } from 'rxjs';
|
||||||
|
import { share } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DialogStateService {
|
||||||
|
|
||||||
|
protected dialogState$ = new ReplaySubject();
|
||||||
|
|
||||||
|
changeDialogState(state: string) {
|
||||||
|
this.dialogState$.next({state});
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangeDialogState(): Observable<any> {
|
||||||
|
return this.dialogState$.pipe(share());
|
||||||
|
}
|
||||||
|
}
|
10
docs/app/@theme/services/highlight.service.ts
Normal file
10
docs/app/@theme/services/highlight.service.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import * as hljs from 'highlight.js';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NgxHighlightService {
|
||||||
|
|
||||||
|
public highlight(code: string): string {
|
||||||
|
return hljs.highlightAuto(code, ['ts', 'html', 'scss', 'nginx']).value;
|
||||||
|
}
|
||||||
|
}
|
25
docs/app/@theme/services/iframe-communicator.service.ts
Normal file
25
docs/app/@theme/services/iframe-communicator.service.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { Inject, Injectable } from '@angular/core';
|
||||||
|
import { Observable, fromEvent as observableFromEvent } from 'rxjs';
|
||||||
|
import { filter, map } from 'rxjs/operators';
|
||||||
|
import { NB_WINDOW } from '@nebular/theme';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NgxIframeCommunicatorService {
|
||||||
|
|
||||||
|
constructor(@Inject(NB_WINDOW) private window) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public send(payload: any, target: Window = this.window.parent) {
|
||||||
|
if (target !== this.window) {
|
||||||
|
target.postMessage(payload, '*');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public receive(id: string): Observable<any> {
|
||||||
|
return observableFromEvent(this.window, 'message')
|
||||||
|
.pipe(
|
||||||
|
filter((msg: any) => msg.data && msg.data.id === id),
|
||||||
|
map((msg: any) => msg.data),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
36
docs/app/@theme/services/index.ts
Normal file
36
docs/app/@theme/services/index.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { NgxVersionService } from './version.service';
|
||||||
|
import { DialogStateService } from './dialog-state.service';
|
||||||
|
import { NgxAnalytics } from './analytics.service';
|
||||||
|
import { NgxHighlightService } from './highlight.service';
|
||||||
|
import { NgxMenuService } from './menu.service';
|
||||||
|
import { NgxPaginationService } from './pagination.service';
|
||||||
|
import { NgxStructureService } from './structure.service';
|
||||||
|
import { NgxTabbedService } from './tabbed.service';
|
||||||
|
import { NgxTextService } from './text.service';
|
||||||
|
import { NgxTocStateService } from './toc-state.service';
|
||||||
|
import { NgxCodeLoaderService } from './code-loader.service';
|
||||||
|
import { NgxStylesService } from './styles.service';
|
||||||
|
import { NgxIframeCommunicatorService } from './iframe-communicator.service';
|
||||||
|
|
||||||
|
|
||||||
|
export const ngxLandingServices = [
|
||||||
|
NgxVersionService,
|
||||||
|
DialogStateService,
|
||||||
|
NgxAnalytics,
|
||||||
|
NgxHighlightService,
|
||||||
|
NgxMenuService,
|
||||||
|
NgxPaginationService,
|
||||||
|
NgxStructureService,
|
||||||
|
NgxTabbedService,
|
||||||
|
NgxTextService,
|
||||||
|
NgxTocStateService,
|
||||||
|
NgxCodeLoaderService,
|
||||||
|
NgxStylesService,
|
||||||
|
NgxIframeCommunicatorService,
|
||||||
|
];
|
86
docs/app/@theme/services/menu.service.ts
Normal file
86
docs/app/@theme/services/menu.service.ts
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { NbMenuItem } from '@nebular/theme';
|
||||||
|
|
||||||
|
import { NgxStructureService } from './structure.service';
|
||||||
|
import { NgxTextService } from './text.service';
|
||||||
|
|
||||||
|
interface IItemLink {
|
||||||
|
title: string;
|
||||||
|
parent?: {
|
||||||
|
link?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NgxMenuService {
|
||||||
|
|
||||||
|
constructor(private structureService: NgxStructureService,
|
||||||
|
private textService: NgxTextService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
getPreparedMenu(basePath: string): any {
|
||||||
|
return this.prepareMenu(this.structureService.getPreparedStructure(), { link: basePath });
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareMenu(structure, parent = null) {
|
||||||
|
return structure
|
||||||
|
.filter(item => item.name && item.type !== 'block')
|
||||||
|
.map((item: any) => {
|
||||||
|
const menuItem: NbMenuItem = {
|
||||||
|
title: item.name,
|
||||||
|
pathMatch: 'prefix',
|
||||||
|
parent: parent,
|
||||||
|
data: item,
|
||||||
|
group: item.type === 'group',
|
||||||
|
};
|
||||||
|
menuItem.link = this.createItemLink<NbMenuItem>(menuItem);
|
||||||
|
|
||||||
|
if (item.children && item.children.some(child => child.type === 'page' || child.type === 'tabs')) {
|
||||||
|
menuItem.expanded = true;
|
||||||
|
menuItem.children = this.prepareMenu(item.children, menuItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return menuItem;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected prepareToc(item: any) {
|
||||||
|
return item.children.reduce((acc: any[], child: any) => {
|
||||||
|
if (child.block === 'markdown') {
|
||||||
|
return acc.concat(this.getTocForMd(child));
|
||||||
|
} else if (child.block === 'tabbed') {
|
||||||
|
return acc.concat(this.getTocForTabbed(child));
|
||||||
|
}
|
||||||
|
acc.push(child.source.name);
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getTocForMd(block: any) {
|
||||||
|
return block.children.map((section: any) => ({
|
||||||
|
title: section.title,
|
||||||
|
fragment: section.fragment,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getTocForTabbed(block: any) {
|
||||||
|
return block.children.map((component: any) => (
|
||||||
|
{
|
||||||
|
title: component.name,
|
||||||
|
fragment: this.textService.createSlag(component.name),
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
createItemLink<T extends IItemLink>(item: T): string {
|
||||||
|
const url = this.textService.createSlag(item.title);
|
||||||
|
|
||||||
|
return item.parent ? `${item.parent.link}/${url}` : url;
|
||||||
|
}
|
||||||
|
}
|
97
docs/app/@theme/services/pagination.service.ts
Normal file
97
docs/app/@theme/services/pagination.service.ts
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { NgxStructureService } from './structure.service';
|
||||||
|
import { NgxMenuService } from './menu.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pagination Item options
|
||||||
|
*/
|
||||||
|
class NgxPaginationItem {
|
||||||
|
title: string;
|
||||||
|
slag: string;
|
||||||
|
link?: string;
|
||||||
|
prev?: {
|
||||||
|
title: string;
|
||||||
|
link: string;
|
||||||
|
};
|
||||||
|
next?: {
|
||||||
|
title: string;
|
||||||
|
link: string;
|
||||||
|
};
|
||||||
|
parent: NgxPaginationItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NgxPaginationService {
|
||||||
|
|
||||||
|
protected paginationItems;
|
||||||
|
|
||||||
|
constructor(private structureService: NgxStructureService,
|
||||||
|
private menuService: NgxMenuService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
setPaginationItems(basePath: string) {
|
||||||
|
this.paginationItems = this.addPrevNextPointers(
|
||||||
|
this.prepareItems(
|
||||||
|
this.structureService.getPreparedStructure(),
|
||||||
|
{ link: basePath },
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected prepareItems(structure, parent = null): NgxPaginationItem[] {
|
||||||
|
return structure
|
||||||
|
.filter(item => item.name)
|
||||||
|
.reduce((result, item: any) => {
|
||||||
|
const paginationItem: NgxPaginationItem = {
|
||||||
|
title: item.name,
|
||||||
|
parent: parent,
|
||||||
|
slag: item.slag,
|
||||||
|
};
|
||||||
|
paginationItem.link = this.menuService.createItemLink<NgxPaginationItem>(paginationItem);
|
||||||
|
|
||||||
|
if (item.name && item.type === 'page' || item.type === 'tabs') {
|
||||||
|
result.push(paginationItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.children) {
|
||||||
|
return result.concat(this.prepareItems(item.children, paginationItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}, [] as NgxPaginationItem[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected addPrevNextPointers(items): NgxPaginationItem[] {
|
||||||
|
return items
|
||||||
|
.map((paginationItem, index, paginationItems) => {
|
||||||
|
const prev = paginationItems[index - 1];
|
||||||
|
const next = paginationItems[index + 1];
|
||||||
|
|
||||||
|
if (prev) {
|
||||||
|
paginationItem.prev = {
|
||||||
|
link: prev.link,
|
||||||
|
title: prev.title,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next) {
|
||||||
|
paginationItem.next = {
|
||||||
|
link: next.link,
|
||||||
|
title: next.title,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return paginationItem;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getPaginationItem(slag: string): NgxPaginationItem {
|
||||||
|
return this.paginationItems.find(item => item.slag === slag);
|
||||||
|
}
|
||||||
|
}
|
151
docs/app/@theme/services/structure.service.ts
Normal file
151
docs/app/@theme/services/structure.service.ts
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Inject, Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { NgxTabbedService } from './tabbed.service';
|
||||||
|
import { NgxTextService } from './text.service';
|
||||||
|
import { DOCS, STRUCTURE } from '../../app.options';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NgxStructureService {
|
||||||
|
|
||||||
|
protected prepared;
|
||||||
|
|
||||||
|
constructor(private textService: NgxTextService,
|
||||||
|
private tabbedService: NgxTabbedService,
|
||||||
|
@Inject(STRUCTURE) structure,
|
||||||
|
@Inject(DOCS) docs) {
|
||||||
|
this.prepared = this.prepareStructure(structure, docs);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPreparedStructure(): any {
|
||||||
|
return this.prepared;
|
||||||
|
}
|
||||||
|
|
||||||
|
findPageBySlag(structure: any, slag: string): any {
|
||||||
|
for (const item of structure) {
|
||||||
|
if (item.slag === slag) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
if (item.type === 'section' && item.children) {
|
||||||
|
const deep = this.findPageBySlag(item.children, slag);
|
||||||
|
if (deep) {
|
||||||
|
return deep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected prepareStructure(structure: any, preparedDocs: any, parentSlag?: string): any {
|
||||||
|
return structure.map((item: any) => {
|
||||||
|
const slag = item.name ? this.textService.createSlag(item.name) : null;
|
||||||
|
|
||||||
|
if (item.type === 'block' && typeof item.source === 'string') {
|
||||||
|
|
||||||
|
if (item.block === 'theme') {
|
||||||
|
item.source = preparedDocs.themes[item.source];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.block === 'component') {
|
||||||
|
item.source = this.prepareComponent(preparedDocs.classes.find((data) => data.name === item.source));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.block === 'markdown') {
|
||||||
|
item.children = this.textService.mdToSectionsHTML(
|
||||||
|
require(`raw-loader!../../../articles/${item.source}`).default);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.children) {
|
||||||
|
item.children = this.prepareStructure(item.children, preparedDocs, slag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.type === 'tabs') {
|
||||||
|
item.source = this.getComponents(item, preparedDocs);
|
||||||
|
item.tabs = this.tabbedService.determineTabs(item);
|
||||||
|
|
||||||
|
// we emulate a block here
|
||||||
|
item.children = [
|
||||||
|
{
|
||||||
|
type: 'block',
|
||||||
|
block: 'tabbed',
|
||||||
|
children: item.source,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.type === 'page' || item.type === 'tabs') {
|
||||||
|
item.toc = this.prepareToc(item);
|
||||||
|
item.slag = parentSlag ? `${parentSlag}_${slag}` : slag;
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getComponents(item: any, preparedDocs) {
|
||||||
|
return item.source
|
||||||
|
.map(source => preparedDocs.classes.find((data) => data.name === source))
|
||||||
|
.map(component => this.prepareComponent(component));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected prepareComponent(component: any) {
|
||||||
|
const textNodes = component.overview.filter(node => node.type === 'text');
|
||||||
|
if (textNodes && textNodes.length) {
|
||||||
|
textNodes[0].content = `## ${component.name}\n\n${textNodes[0].content}`; // TODO: this is bad
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
... component,
|
||||||
|
slag: this.textService.createSlag(component.name),
|
||||||
|
overview: component.overview.map((node: any) => {
|
||||||
|
if (node.type === 'text') {
|
||||||
|
return {
|
||||||
|
type: node.type,
|
||||||
|
content: this.textService.mdToSectionsHTML(node.content),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected prepareToc(item: any) {
|
||||||
|
return item.children.reduce((acc: any[], child: any) => {
|
||||||
|
if (child.block === 'markdown') {
|
||||||
|
return acc.concat(this.getTocForMd(child));
|
||||||
|
} else if (child.block === 'tabbed') {
|
||||||
|
return acc.concat(this.getTocForTabbed(child));
|
||||||
|
} else if (child.block === 'component') {
|
||||||
|
acc.push(this.getTocForComponent(child));
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getTocForMd(block: any) {
|
||||||
|
return block.children.map((section: any) => ({
|
||||||
|
title: section.title,
|
||||||
|
fragment: section.fragment,
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getTocForComponent(block: any) {
|
||||||
|
return {
|
||||||
|
title: block.source.name,
|
||||||
|
fragment: block.source.slag,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getTocForTabbed(block: any) {
|
||||||
|
return block.children.map((component: any) => ({
|
||||||
|
title: component.name,
|
||||||
|
fragment: this.textService.createSlag(component.name),
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
33
docs/app/@theme/services/styles.service.ts
Normal file
33
docs/app/@theme/services/styles.service.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Inject, Injectable } from '@angular/core';
|
||||||
|
import { DOCS } from '../../app.options';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NgxStylesService {
|
||||||
|
|
||||||
|
constructor(@Inject(DOCS) private docs) {
|
||||||
|
}
|
||||||
|
|
||||||
|
mapThemedValues(classStyles: any): any {
|
||||||
|
return classStyles.map(item => {
|
||||||
|
item.styles.map(prop => {
|
||||||
|
prop.themedValues = [];
|
||||||
|
for (const themeName in this.docs.themes) {
|
||||||
|
if (this.docs.themes.hasOwnProperty(themeName)) {
|
||||||
|
prop.themedValues.push({
|
||||||
|
theme: this.docs.themes[themeName].name,
|
||||||
|
value: this.docs.themes[themeName].data[prop.name].value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prop;
|
||||||
|
});
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
56
docs/app/@theme/services/tabbed.service.ts
Normal file
56
docs/app/@theme/services/tabbed.service.ts
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NgxTabbedService {
|
||||||
|
|
||||||
|
determineTabs(tabs: any): { [tab: string]: boolean } {
|
||||||
|
return {
|
||||||
|
'overview': this.hasOverview(tabs),
|
||||||
|
'api': this.hasAPI(tabs),
|
||||||
|
'theme': this.hasTheme(tabs),
|
||||||
|
'examples': this.hasExample(tabs),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
hasOverview(tabs: any): boolean {
|
||||||
|
return tabs.source.some(source => this.componentHasOverview(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
hasExample(tabs: any): boolean {
|
||||||
|
return tabs.source.some(source => this.componentHasExamples(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
hasTheme(tabs: any): boolean {
|
||||||
|
return tabs.source.some(source => this.componentHasTheme(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
hasAPI(tabs: any): boolean {
|
||||||
|
return tabs.source.some(source => this.componentHasMethods(source) || this.componentHasProps(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
componentHasTheme(component): boolean {
|
||||||
|
return component.styles &&
|
||||||
|
component.styles.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentHasProps(component): boolean {
|
||||||
|
return component &&
|
||||||
|
component.props &&
|
||||||
|
component.props.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentHasMethods(component): boolean {
|
||||||
|
return component &&
|
||||||
|
component.methods &&
|
||||||
|
component.methods.length > 0 &&
|
||||||
|
component.methods.some(method => method.shortDescription || method.description);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentHasOverview(component): boolean {
|
||||||
|
return component && component.overview && component.overview.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentHasExamples(component): boolean {
|
||||||
|
return component.liveExamples && component.liveExamples.length > 0;
|
||||||
|
}
|
||||||
|
}
|
67
docs/app/@theme/services/text.service.ts
Normal file
67
docs/app/@theme/services/text.service.ts
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Location } from '@angular/common';
|
||||||
|
import * as marked from 'marked';
|
||||||
|
|
||||||
|
import { NgxHighlightService } from './highlight.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NgxTextService {
|
||||||
|
|
||||||
|
private readonly SECTION_SPLIT = '<hr>';
|
||||||
|
private readonly TITLE_MASK = '^#{1,6}[^#]?(.+)\n';
|
||||||
|
private readonly STRIP_HTML = '<\\/?[^>]+(>|$)';
|
||||||
|
|
||||||
|
constructor(private highlight: NgxHighlightService, private location: Location) {
|
||||||
|
}
|
||||||
|
|
||||||
|
mdToSectionsHTML(markdown: string) {
|
||||||
|
return this.splitIntoSections(markdown)
|
||||||
|
.map((section) => {
|
||||||
|
const html = this.mdToHTML(section);
|
||||||
|
const title = this.extractTitle(section) || this.extractFirstTwoWords(html);
|
||||||
|
const fragment = this.createSlag(title);
|
||||||
|
return {
|
||||||
|
source: section,
|
||||||
|
title: title,
|
||||||
|
fragment: fragment,
|
||||||
|
html: html,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
mdToHTML(markdown: string) {
|
||||||
|
return marked
|
||||||
|
.setOptions({
|
||||||
|
baseUrl: this.location.prepareExternalUrl(''),
|
||||||
|
langPrefix: 'hljs ',
|
||||||
|
highlight: (code) => this.highlight.highlight(code),
|
||||||
|
} as any)
|
||||||
|
.parse(markdown.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
splitIntoSections(markdown: string) {
|
||||||
|
return markdown.split(new RegExp(this.SECTION_SPLIT, 'g'))
|
||||||
|
.filter(section => section.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
extractTitle(section: string) {
|
||||||
|
const titleMatch = section.trim().match(new RegExp(this.TITLE_MASK, 'i'));
|
||||||
|
return titleMatch ? titleMatch[1] : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
extractFirstTwoWords(section: string) {
|
||||||
|
return section
|
||||||
|
.replace(new RegExp(this.STRIP_HTML, 'g'), '')
|
||||||
|
.trim()
|
||||||
|
.split(/\s+/g)
|
||||||
|
.slice(0, 2)
|
||||||
|
.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
createSlag(name: string) {
|
||||||
|
return name
|
||||||
|
.replace(/[^a-zA-Z0-9\s]+/g, '')
|
||||||
|
.replace(/\s/g, '-')
|
||||||
|
.toLowerCase();
|
||||||
|
}
|
||||||
|
}
|
29
docs/app/@theme/services/toc-state.service.ts
Normal file
29
docs/app/@theme/services/toc-state.service.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
export interface NgxTocElement {
|
||||||
|
fragment: string;
|
||||||
|
element: any;
|
||||||
|
y: number;
|
||||||
|
setInView(val: boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NgxTocStateService {
|
||||||
|
state: NgxTocElement[] = [];
|
||||||
|
|
||||||
|
add(el: NgxTocElement) {
|
||||||
|
this.state.push(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(el: NgxTocElement) {
|
||||||
|
this.state = this.state.filter(e => e !== el);
|
||||||
|
}
|
||||||
|
|
||||||
|
list(): NgxTocElement[] {
|
||||||
|
return this.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.state = [];
|
||||||
|
}
|
||||||
|
}
|
15
docs/app/@theme/services/version.service.ts
Normal file
15
docs/app/@theme/services/version.service.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NgxVersionService {
|
||||||
|
|
||||||
|
getNgxVersion() {
|
||||||
|
return require('../../../../package.json').version;
|
||||||
|
}
|
||||||
|
}
|
19
docs/app/@theme/styles/_helvetica-neue.scss
Normal file
19
docs/app/@theme/styles/_helvetica-neue.scss
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$helvetica-neue-font-path: '/ngx-admin/assets/fonts/helvetica-neue' !default;
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Helvetica Neue Bold';
|
||||||
|
font-display: swap;
|
||||||
|
src: url('#{$helvetica-neue-font-path}/HelveticaNeue-Bold.eot');
|
||||||
|
src: local('Helvetica Neue Bold'), local('HelveticaNeue-Bold'),
|
||||||
|
url('#{$helvetica-neue-font-path}/HelveticaNeue-Bold.eot?#iefix') format('embedded-opentype'),
|
||||||
|
url('#{$helvetica-neue-font-path}/HelveticaNeue-Bold.woff') format('woff'),
|
||||||
|
url('#{$helvetica-neue-font-path}/HelveticaNeue-Bold.ttf') format('truetype');
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
105
docs/app/@theme/styles/_hs-forms.scss
Normal file
105
docs/app/@theme/styles/_hs-forms.scss
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@mixin hs-custom-form() {
|
||||||
|
.hs-custom-form {
|
||||||
|
.modal-header {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-body {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.hs-input {
|
||||||
|
width: 100%;
|
||||||
|
color: nb-theme(input-basic-text-color);
|
||||||
|
font-size: nb-theme(input-medium-text-font-size);
|
||||||
|
font-weight: nb-theme(input-medium-text-font-weight);
|
||||||
|
line-height: nb-theme(input-medium-text-line-height);
|
||||||
|
padding: nb-theme(input-medium-padding) !important;
|
||||||
|
border: nb-theme(input-border-width) nb-theme(input-border-style) nb-theme(input-basic-border-color);
|
||||||
|
border-radius: nb-theme(input-rectangle-border-radius);
|
||||||
|
background-color: nb-theme(input-basic-background-color);
|
||||||
|
|
||||||
|
&.hover {
|
||||||
|
background-color: nb-theme(input-basic-hover-background-color);
|
||||||
|
border-color: nb-theme(input-basic-hover-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.invalid {
|
||||||
|
box-shadow: 0 0 1.25rem 0 rgba(210, 45, 45, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: nb-theme(input-basic-placeholder-text-color);
|
||||||
|
font-size: nb-theme(input-medium-placeholder-text-font-size);
|
||||||
|
font-weight: nb-theme(input-medium-placeholder-text-font-weight);
|
||||||
|
line-height: nb-theme(input-medium-placeholder-text-line-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
background-color: nb-theme(input-basic-focus-background-color);
|
||||||
|
border-color: nb-theme(input-basic-focus-border-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-richtext .modal-body {
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: 0;
|
||||||
|
text-align: left !important;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-recaptcha {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-error-msgs {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-form-required, .hs-error-msg {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
color: nb-theme(text-danger-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs_error_rollup {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-submit-btn {
|
||||||
|
font-family: nb-theme(font-main);
|
||||||
|
border-radius: 3px;
|
||||||
|
border: none;
|
||||||
|
background-color: nb-theme(color-active-fg);
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
box-shadow: nb-theme(shadow-btn);
|
||||||
|
cursor: pointer;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: nb-theme(shadow-hover-green-btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
box-shadow: nb-theme(shadow-active-green-btn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
81
docs/app/@theme/styles/_swiper_ngx-admin.scss
Normal file
81
docs/app/@theme/styles/_swiper_ngx-admin.scss
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@mixin swiper-navigation-arrows($config) {
|
||||||
|
$position: map-get($config, 'position');
|
||||||
|
$positionXl: map-get($config, 'positionXl');
|
||||||
|
|
||||||
|
.swiper-button-prev, .swiper-button-next {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background-image: none;
|
||||||
|
height: 5rem;
|
||||||
|
width: 5rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
box-shadow: nb-theme(shadow-default);
|
||||||
|
top: map-get($config, 'top');
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: nb-theme(shadow-hover-btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
box-shadow: nb-theme(shadow-active-btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-button-prev {
|
||||||
|
@if (type-of($position) == map) {
|
||||||
|
left: map-get($position, 'left');
|
||||||
|
} @else {
|
||||||
|
left: $position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-button-next {
|
||||||
|
@if (type-of($position) == map) {
|
||||||
|
right: map-get($position, 'right');
|
||||||
|
} @else {
|
||||||
|
right: $position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-down(xl) {
|
||||||
|
.swiper-button-prev {
|
||||||
|
@if (type-of($positionXl) == map) {
|
||||||
|
left: map-get($positionXl, 'left');
|
||||||
|
} @else {
|
||||||
|
left: $positionXl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-button-next {
|
||||||
|
@if (type-of($positionXl) == map) {
|
||||||
|
right: map-get($positionXl, 'right');
|
||||||
|
} @else {
|
||||||
|
right: $positionXl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-down(lg) {
|
||||||
|
.swiper-button-prev, .swiper-button-next {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-down(is) {
|
||||||
|
.swiper-button-prev, .swiper-button-next {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
docs/app/@theme/styles/styles.scss
Normal file
19
docs/app/@theme/styles/styles.scss
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import 'helvetica-neue';
|
||||||
|
@import 'themes';
|
||||||
|
|
||||||
|
@import '~@nebular/theme/styles/globals';
|
||||||
|
@import '~@nebular/bootstrap/styles/globals';
|
||||||
|
|
||||||
|
@import 'hs-forms';
|
||||||
|
|
||||||
|
@include nb-install() {
|
||||||
|
@include nb-theme-global();
|
||||||
|
@include nb-bootstrap-global();
|
||||||
|
@include hs-custom-form();
|
||||||
|
};
|
238
docs/app/@theme/styles/themes.scss
Normal file
238
docs/app/@theme/styles/themes.scss
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import '~@nebular/theme/styles/theming';
|
||||||
|
@import '~@nebular/theme/styles/themes/corporate';
|
||||||
|
@import '~@nebular/theme/styles/themes/default';
|
||||||
|
@import '~@nebular/theme/styles/global/breakpoints';
|
||||||
|
|
||||||
|
/*
|
||||||
|
We have to overwrite breakpoints because we need to add *macpro* breakpoint.
|
||||||
|
But if we add it using *map-merge* function we'll get the warning and *media-breakpoint-down* will stop working.
|
||||||
|
*/
|
||||||
|
$grid-breakpoints: (
|
||||||
|
xs: 0,
|
||||||
|
is: 400px,
|
||||||
|
sm: 576px,
|
||||||
|
md: 768px,
|
||||||
|
lg: 992px,
|
||||||
|
xl: 1200px,
|
||||||
|
macpro: 1280px,
|
||||||
|
xxl: 1400px,
|
||||||
|
xxxl: 1600px
|
||||||
|
);
|
||||||
|
|
||||||
|
$nb-enabled-themes: (ngx-landing, ngx-landing-material, docs-page);
|
||||||
|
|
||||||
|
/* stylelint-disable */
|
||||||
|
$nb-themes: nb-register-theme((
|
||||||
|
font-family-primary: unquote('-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"'),
|
||||||
|
|
||||||
|
link-text-decoration: none,
|
||||||
|
|
||||||
|
content-width: 1440px,
|
||||||
|
settings-col-width: 16rem,
|
||||||
|
settings-col-margin: 1.875rem,
|
||||||
|
|
||||||
|
color-primary: #3366ff,
|
||||||
|
|
||||||
|
separator: transparent,
|
||||||
|
color-success: #18cb90,
|
||||||
|
color-link: #18cb90,
|
||||||
|
color-bg: transparent,
|
||||||
|
color-fg: #405571,
|
||||||
|
color-fg-heading: #546d8d,
|
||||||
|
color-fg-text: #919fb1,
|
||||||
|
color-fg-icon: #c4c8d1,
|
||||||
|
color-gray-bg: #edf0f5,
|
||||||
|
color-fg-heading-light: #405571,
|
||||||
|
color-active-fg: color-success,
|
||||||
|
color-active-bg: color-success,
|
||||||
|
|
||||||
|
shadow: none,
|
||||||
|
|
||||||
|
layout-background-color: transparent,
|
||||||
|
layout-padding: 0,
|
||||||
|
layout-medium-padding: 0,
|
||||||
|
layout-small-padding: 0,
|
||||||
|
|
||||||
|
header-background-color: #fafafa,
|
||||||
|
header-padding: 0 0,
|
||||||
|
header-height: 4.25rem,
|
||||||
|
header-fg: color-fg,
|
||||||
|
header-menu-fg-active: color-active-fg,
|
||||||
|
header-section-border-color: #f5f5f5,
|
||||||
|
header-font-weight: 600,
|
||||||
|
|
||||||
|
header-button-border: #dce4f2,
|
||||||
|
|
||||||
|
sidebar-width: 11.25rem,
|
||||||
|
|
||||||
|
menu-bg: transparent,
|
||||||
|
menu-item-padding: 0.675rem 1rem,
|
||||||
|
menu-item-fg: #8992a3,
|
||||||
|
menu-active-fg: color-primary,
|
||||||
|
menu-font-size: 0.95rem,
|
||||||
|
menu-font-weight: font-weight-normal,
|
||||||
|
|
||||||
|
menu-active-bg: transparent,
|
||||||
|
|
||||||
|
footer-height: 18.75rem,
|
||||||
|
footer-padding: 1.25rem 0,
|
||||||
|
footer-fg: #8992a3,
|
||||||
|
footer-fg-highlight: footer-fg,
|
||||||
|
footer-separator: transparent,
|
||||||
|
footer-title-fg: #0d1c2e,
|
||||||
|
|
||||||
|
|
||||||
|
list-icon-item-bg: #ebf1fa,
|
||||||
|
list-icon-item-fg: #0d1c2e,
|
||||||
|
|
||||||
|
switcher-view-bg: #d8e1f0,
|
||||||
|
|
||||||
|
checkbox-size: 1.5rem,
|
||||||
|
checkbox-border-color: form-control-border-color,
|
||||||
|
checkbox-checkmark: transparent,
|
||||||
|
|
||||||
|
checkbox-checked-bg: color-active-fg,
|
||||||
|
checkbox-checked-size: 1.5rem,
|
||||||
|
checkbox-checked-border-color: checkbox-checked-bg,
|
||||||
|
checkbox-checked-checkmark: color-white,
|
||||||
|
|
||||||
|
format-name-fg: #6a7385,
|
||||||
|
|
||||||
|
popover-bg: #0d1c2e,
|
||||||
|
popover-fg: #ffffff,
|
||||||
|
popover-border: #0d1c2e,
|
||||||
|
popover-border-radius: 0.75rem,
|
||||||
|
popover-arrow-size: 6px,
|
||||||
|
|
||||||
|
info-bg: #fff2f2,
|
||||||
|
info-fg: #ff3d71,
|
||||||
|
|
||||||
|
custiom-radius: 0.625rem,
|
||||||
|
|
||||||
|
gray-section-bg: #fafafa,
|
||||||
|
|
||||||
|
shadow-default: 0 0.5rem 1.25rem 0 rgba(218, 224, 235, 0.6),
|
||||||
|
shadow-btn: 0 0.375rem 2.125rem 0 rgba(184, 255, 231, 0.5),
|
||||||
|
shadow-hover-btn: 0 0.5rem 2rem 0 #dae0eb,
|
||||||
|
shadow-active-btn: 0 0.5rem 1.25rem 0 rgba(218, 224, 235, 0.6),
|
||||||
|
shadow-hover-green-btn: 0 0.5rem 2rem 0 rgba(0, 219, 146, 0.25),
|
||||||
|
shadow-active-green-btn: 0 0.375rem 2.125rem 0 rgba(0, 219, 146, 0.32),
|
||||||
|
|
||||||
|
footer-text-highlight-color: text-basic-color,
|
||||||
|
link-text-color: color-success-default,
|
||||||
|
link-text-focus-color: color-success-focus,
|
||||||
|
link-text-hover-color: color-success-hover,
|
||||||
|
|
||||||
|
), ngx-landing, corporate);
|
||||||
|
|
||||||
|
$nb-themes: nb-register-theme((
|
||||||
|
font-family-primary: unquote('Roboto, sans-serif'),
|
||||||
|
|
||||||
|
link-text-decoration: none,
|
||||||
|
|
||||||
|
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-link: #6200ee,
|
||||||
|
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
|
||||||
|
font-family-primary: unquote('-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"'),
|
||||||
|
|
||||||
|
link-text-decoration: none,
|
||||||
|
|
||||||
|
content-width: 1440px,
|
||||||
|
settings-col-width: 16rem,
|
||||||
|
settings-col-margin: 1.875rem,
|
||||||
|
color-gray-light: #ced5dd,
|
||||||
|
color-fg-heading-light: #405571,
|
||||||
|
code-block-bg: linear-gradient(225deg, #333c66 0%, #1d2447 100%),
|
||||||
|
color-info: #5699f0,
|
||||||
|
color-warning: #f09301,
|
||||||
|
header-menu-fg-active: color-fg-highlight,
|
||||||
|
|
||||||
|
radius: 0.25rem,
|
||||||
|
separator: transparent,
|
||||||
|
color-bg: transparent,
|
||||||
|
color-fg: #494949,
|
||||||
|
color-fg-text: #494949,
|
||||||
|
color-fg-heading: rgba(0, 0, 0, 0.88),
|
||||||
|
color-fg-icon: #cdd6e3,
|
||||||
|
|
||||||
|
shadow: 0 8px 20px 0 rgba(218, 224, 235, 0.6),
|
||||||
|
|
||||||
|
layout-bg: #fafafa,
|
||||||
|
layout-padding: 3.25rem 1.25rem 3.25rem 1rem,
|
||||||
|
layout-medium-padding: 0,
|
||||||
|
layout-small-padding: 0,
|
||||||
|
|
||||||
|
header-background-color: #fafafa,
|
||||||
|
sidebar-padding: 2rem,
|
||||||
|
sidebar-shadow: none,
|
||||||
|
color-fg-highlight: #00db92,
|
||||||
|
link-color: color-fg-highlight,
|
||||||
|
link-color-hover: color-fg-highlight,
|
||||||
|
link-color-visited: color-fg-highlight,
|
||||||
|
|
||||||
|
header-height: 4.25rem,
|
||||||
|
header-padding: 0,
|
||||||
|
header-fg: black,
|
||||||
|
|
||||||
|
menu-fg: black,
|
||||||
|
menu-font-size: 0.95rem,
|
||||||
|
menu-font-weight: font-weight-normal,
|
||||||
|
menu-submenu-fg: color-fg-heading-light,
|
||||||
|
menu-active-fg: menu-fg,
|
||||||
|
menu-submenu-padding: 0,
|
||||||
|
menu-submenu-item-container-padding: 0 1rem,
|
||||||
|
menu-submenu-active-border-color: transparent,
|
||||||
|
menu-submenu-active-fg: color-fg-highlight,
|
||||||
|
menu-active-font-weight: bold,
|
||||||
|
|
||||||
|
card-bg: white,
|
||||||
|
card-header-font-size: 2rem,
|
||||||
|
card-header-font-weight: bold,
|
||||||
|
card-header-fg-heading: black,
|
||||||
|
card-margin: 2.5rem,
|
||||||
|
|
||||||
|
footer-background-color: transparent,
|
||||||
|
footer-height: 18.75rem,
|
||||||
|
footer-padding: 1.25rem 0,
|
||||||
|
footer-shadow: none,
|
||||||
|
footer-fg: color-fg-heading-light,
|
||||||
|
footer-menu-fg: color-fg-text,
|
||||||
|
footer-text-highlight-color: text-basic-color,
|
||||||
|
|
||||||
|
link-text-color: color-success-default,
|
||||||
|
link-text-focus-color: color-success-focus,
|
||||||
|
link-text-hover-color: color-success-hover,
|
||||||
|
|
||||||
|
sidebar-background-color: transparent,
|
||||||
|
|
||||||
|
menu-item-hover-text-color: text-success-hover-color,
|
||||||
|
menu-item-active-text-color: text-success-color,
|
||||||
|
), docs-page, default);
|
103
docs/app/@theme/theme.module.ts
Normal file
103
docs/app/@theme/theme.module.ts
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
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,
|
||||||
|
NbDialogModule,
|
||||||
|
} from '@nebular/theme';
|
||||||
|
|
||||||
|
import { LandingSharedModule } from '../shared/landing-shared.module';
|
||||||
|
|
||||||
|
// components
|
||||||
|
import {
|
||||||
|
NgxLandingFooterComponent,
|
||||||
|
NgxSectionTitleComponent,
|
||||||
|
NgxFragmentTargetDirective,
|
||||||
|
NgxPageTocComponent,
|
||||||
|
NgxPageTabsComponent,
|
||||||
|
NgxLandingHeaderComponent,
|
||||||
|
NgxDocsFooterComponent,
|
||||||
|
} from './components';
|
||||||
|
// components
|
||||||
|
|
||||||
|
// services
|
||||||
|
import { ngxLandingServices } from './services';
|
||||||
|
// services
|
||||||
|
|
||||||
|
const BASE_MODULES = [
|
||||||
|
CommonModule,
|
||||||
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
LazyLoadImageModule,
|
||||||
|
];
|
||||||
|
|
||||||
|
const NB_MODULES = [
|
||||||
|
NbLayoutModule,
|
||||||
|
NbCheckboxModule,
|
||||||
|
NbMenuModule,
|
||||||
|
NbCardModule,
|
||||||
|
NbSidebarModule,
|
||||||
|
NbTabsetModule,
|
||||||
|
];
|
||||||
|
|
||||||
|
const COMPONENTS = [
|
||||||
|
NgxLandingFooterComponent,
|
||||||
|
NgxSectionTitleComponent,
|
||||||
|
NgxFragmentTargetDirective,
|
||||||
|
NgxPageTocComponent,
|
||||||
|
NgxPageTabsComponent,
|
||||||
|
NgxLandingHeaderComponent,
|
||||||
|
NgxDocsFooterComponent,
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule,
|
||||||
|
LandingSharedModule,
|
||||||
|
|
||||||
|
...BASE_MODULES,
|
||||||
|
|
||||||
|
...NB_MODULES,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
...COMPONENTS,
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
RouterModule,
|
||||||
|
|
||||||
|
...BASE_MODULES,
|
||||||
|
|
||||||
|
...NB_MODULES,
|
||||||
|
|
||||||
|
...COMPONENTS,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class NgxLandingThemeModule {
|
||||||
|
static forRoot(): ModuleWithProviders<NgxLandingThemeModule> {
|
||||||
|
return {
|
||||||
|
ngModule: NgxLandingThemeModule,
|
||||||
|
providers: [
|
||||||
|
...NbThemeModule.forRoot({ name: 'ngx-landing' }).providers,
|
||||||
|
...NbMenuModule.forRoot().providers,
|
||||||
|
...NbSidebarModule.forRoot().providers,
|
||||||
|
...NbDialogModule.forRoot().providers,
|
||||||
|
|
||||||
|
...ngxLandingServices,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
28
docs/app/app-routing.module.ts
Normal file
28
docs/app/app-routing.module.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { ExtraOptions, RouterModule, Routes } from '@angular/router';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
loadChildren: () => import('./pages/pages.module')
|
||||||
|
.then(m => m.PagesModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '**',
|
||||||
|
redirectTo: '',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const config: ExtraOptions = {
|
||||||
|
useHash: false,
|
||||||
|
anchorScrolling: 'enabled',
|
||||||
|
onSameUrlNavigation: 'reload',
|
||||||
|
scrollPositionRestoration: 'enabled',
|
||||||
|
};
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forRoot(routes, config)],
|
||||||
|
exports: [RouterModule],
|
||||||
|
})
|
||||||
|
export class AppRoutingModule {
|
||||||
|
}
|
16
docs/app/app.component.ts
Normal file
16
docs/app/app.component.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-landing-app',
|
||||||
|
template: '<router-outlet></router-outlet>',
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
}
|
45
docs/app/app.module.ts
Normal file
45
docs/app/app.module.ts
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { BrowserModule, Title } from '@angular/platform-browser';
|
||||||
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
|
||||||
|
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');
|
||||||
|
import { structure } from '../structure';
|
||||||
|
import {MetadataService} from '../../src/app/@core/utils/metadata.service';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent,
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
HttpClientModule,
|
||||||
|
AppRoutingModule,
|
||||||
|
|
||||||
|
LandingSharedModule,
|
||||||
|
NgxLandingThemeModule.forRoot(),
|
||||||
|
CoreModule.forRoot(),
|
||||||
|
],
|
||||||
|
bootstrap: [AppComponent],
|
||||||
|
providers: [
|
||||||
|
Title,
|
||||||
|
MetadataService,
|
||||||
|
{ provide: STRUCTURE, useValue: structure },
|
||||||
|
{ provide: DOCS, useValue: docs },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
9
docs/app/app.options.ts
Normal file
9
docs/app/app.options.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
import { InjectionToken } from '@angular/core';
|
||||||
|
|
||||||
|
export const STRUCTURE = new InjectionToken<any>('Docs Structure');
|
||||||
|
export const DOCS = new InjectionToken<any>('Docs Structure');
|
74
docs/app/blocks/blocks.module.ts
Normal file
74
docs/app/blocks/blocks.module.ts
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { NgxLandingThemeModule } from '../@theme/theme.module';
|
||||||
|
|
||||||
|
import {
|
||||||
|
NgxMdBLockComponent,
|
||||||
|
NgxTabbedBlockComponent,
|
||||||
|
NgxOverviewBlockComponent,
|
||||||
|
NgxExampleBlockComponent,
|
||||||
|
NgxInlineExampleBlockComponent,
|
||||||
|
NgxTabbedExampleBlockComponent,
|
||||||
|
NgxLiveExampleBlockComponent,
|
||||||
|
NgxStackedExampleComponent,
|
||||||
|
NgxCodeBlockComponent,
|
||||||
|
NgxMethodsBlockComponent,
|
||||||
|
NgxPropsBlockComponent,
|
||||||
|
NgxPropBlockComponent,
|
||||||
|
NgxStylesBlockComponent,
|
||||||
|
NgxThemeComponent,
|
||||||
|
NgxComponentBlockComponent,
|
||||||
|
NgxApiBlockComponent,
|
||||||
|
NgxStylesTableBlockComponent,
|
||||||
|
NgxExamplesBlockComponent,
|
||||||
|
NgxPagerBlockComponent,
|
||||||
|
NgxComponentsOverviewBlockComponent,
|
||||||
|
} from './components/';
|
||||||
|
|
||||||
|
const blocks = [
|
||||||
|
NgxMdBLockComponent,
|
||||||
|
NgxTabbedBlockComponent,
|
||||||
|
NgxOverviewBlockComponent,
|
||||||
|
NgxExampleBlockComponent,
|
||||||
|
NgxInlineExampleBlockComponent,
|
||||||
|
NgxTabbedExampleBlockComponent,
|
||||||
|
NgxLiveExampleBlockComponent,
|
||||||
|
NgxStackedExampleComponent,
|
||||||
|
NgxCodeBlockComponent,
|
||||||
|
NgxMethodsBlockComponent,
|
||||||
|
NgxPropsBlockComponent,
|
||||||
|
NgxPropBlockComponent,
|
||||||
|
NgxStylesBlockComponent,
|
||||||
|
NgxThemeComponent,
|
||||||
|
NgxComponentBlockComponent,
|
||||||
|
NgxApiBlockComponent,
|
||||||
|
NgxStylesTableBlockComponent,
|
||||||
|
NgxExamplesBlockComponent,
|
||||||
|
NgxPagerBlockComponent,
|
||||||
|
NgxComponentsOverviewBlockComponent,
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
RouterModule,
|
||||||
|
NgxLandingThemeModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
...blocks,
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
CommonModule,
|
||||||
|
RouterModule,
|
||||||
|
...blocks,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class NgxBlocksModule {
|
||||||
|
}
|
38
docs/app/blocks/components/api-block/api-block.component.ts
Normal file
38
docs/app/blocks/components/api-block/api-block.component.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
|
import { NgxTabbedService } from '../../../@theme/services/tabbed.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-api-block',
|
||||||
|
template: `
|
||||||
|
<nb-card [ngxFragment]="source.slag">
|
||||||
|
<nb-card-body>
|
||||||
|
<h2>{{ source.name }}</h2>
|
||||||
|
<ngx-props-block [source]="source" *ngIf="hasProps(source)"></ngx-props-block>
|
||||||
|
<ngx-methods-block [source]="source" *ngIf="hasMethods(source)"></ngx-methods-block>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxApiBlockComponent {
|
||||||
|
|
||||||
|
@Input('source') source;
|
||||||
|
|
||||||
|
constructor(private tabbedService: NgxTabbedService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
hasMethods(component) {
|
||||||
|
return this.tabbedService.componentHasMethods(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasProps(component) {
|
||||||
|
return this.tabbedService.componentHasProps(component);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
|
||||||
|
$code-lines-fg: #515877;
|
||||||
|
$code-block-bg: nb-theme(code-block-bg);
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 1rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
background: $code-block-bg;
|
||||||
|
overflow-x: auto;
|
||||||
|
|
||||||
|
.lines {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: end;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
padding: 2rem 0.5rem 0.5rem;
|
||||||
|
border-radius: 0.5rem 0 0 0.5rem;
|
||||||
|
color: $code-lines-fg;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin-bottom: 0;
|
||||||
|
background: transparent;
|
||||||
|
overflow: visible;
|
||||||
|
|
||||||
|
code.hljs {
|
||||||
|
background: transparent;
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
|
import { SafeHtml } from '@angular/platform-browser';
|
||||||
|
import { NgxHighlightService } from '../../../@theme/services/highlight.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-code-block',
|
||||||
|
styleUrls: ['./code-block.component.scss'],
|
||||||
|
template: `
|
||||||
|
<div class="container">
|
||||||
|
<div class="lines">
|
||||||
|
<span *ngFor="let line of lines">{{ line }}</span>
|
||||||
|
</div>
|
||||||
|
<pre><code class="hljs" [innerHTML]="code"></code></pre>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxCodeBlockComponent {
|
||||||
|
|
||||||
|
@Input() path = '';
|
||||||
|
@Input() firstLine: number;
|
||||||
|
@Input() lastLine: number;
|
||||||
|
|
||||||
|
@Input('code')
|
||||||
|
set rawCode(value) {
|
||||||
|
const highlighted = this.highlightService.highlight(value);
|
||||||
|
this.code = this.getVisible(highlighted);
|
||||||
|
this.lines = this.createLines(this.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
code: SafeHtml;
|
||||||
|
lines: number[] = [];
|
||||||
|
|
||||||
|
constructor(private highlightService: NgxHighlightService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
getVisible(code): string {
|
||||||
|
return code
|
||||||
|
.split('\n')
|
||||||
|
.slice(this.firstLine - 1, this.lastLine)
|
||||||
|
.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
createLines(code): number[] {
|
||||||
|
const length = code.split('\n').length;
|
||||||
|
return Array(length).fill(0).map((_, i) => i + (this.firstLine || 1));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
|
import { NgxTabbedService } from '../../../@theme/services/tabbed.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-component-block',
|
||||||
|
template: `
|
||||||
|
<nb-card [ngxFragment]="source.slag">
|
||||||
|
<nb-card-body>
|
||||||
|
<ng-container class="description" *ngFor="let node of overview">
|
||||||
|
<ng-container *ngIf="node.type === 'text'">
|
||||||
|
<div *ngFor="let section of node.content" [innerHtml]="section.html"></div>
|
||||||
|
</ng-container>
|
||||||
|
<ngx-live-example-block *ngIf="node.type === 'live-example'" [id]="node.content" [title]="'example'"
|
||||||
|
class="widget-block">
|
||||||
|
</ngx-live-example-block>
|
||||||
|
<ngx-inline-example-block *ngIf="node.type === 'inline-example'" [content]="node.content"
|
||||||
|
class="widget-block">
|
||||||
|
</ngx-inline-example-block>
|
||||||
|
<ngx-stacked-example-block *ngIf="node.type === 'example'" [content]="node.content"
|
||||||
|
class="widget-block">
|
||||||
|
</ngx-stacked-example-block>
|
||||||
|
</ng-container>
|
||||||
|
<ngx-props-block [source]="source" *ngIf="hasProps(source)"></ngx-props-block>
|
||||||
|
<ngx-methods-block [source]="source" *ngIf="hasMethods(source)"></ngx-methods-block>
|
||||||
|
<ng-container *ngIf="hasTheme(source)">
|
||||||
|
<h3>Theme</h3>
|
||||||
|
<ngx-styles-table-block [source]="source"></ngx-styles-table-block>
|
||||||
|
</ng-container>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxComponentBlockComponent {
|
||||||
|
|
||||||
|
source: any;
|
||||||
|
overview: any[] = [];
|
||||||
|
|
||||||
|
@Input('source')
|
||||||
|
set setSource(source: any) {
|
||||||
|
this.source = source;
|
||||||
|
this.overview = source.overview;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private tabbedService: NgxTabbedService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
hasTheme(component) {
|
||||||
|
return this.tabbedService.componentHasTheme(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasMethods(component) {
|
||||||
|
return this.tabbedService.componentHasMethods(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasProps(component) {
|
||||||
|
return this.tabbedService.componentHasProps(component);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
<nb-card class="header-card">
|
||||||
|
<nb-card-header>Components Overview</nb-card-header>
|
||||||
|
</nb-card>
|
||||||
|
|
||||||
|
<div class="components-list">
|
||||||
|
<ng-container *ngFor="let component of components">
|
||||||
|
<h2 *ngIf="component.group">{{ component.name }}</h2>
|
||||||
|
<div *ngIf="!component.group" class="component-card-wrapper">
|
||||||
|
<a class="component-navigate-link" [routerLink]="component.link">
|
||||||
|
<nb-card [attr.title]="component.name">
|
||||||
|
<nb-card-body>
|
||||||
|
<img class="component-icon" src="assets/images/components/{{ component.icon }}"
|
||||||
|
[attr.alt]="component.name">
|
||||||
|
<label class="component-name">{{ component.name }}</label>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
|
@ -0,0 +1,81 @@
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
@import '~@nebular/theme/styles/global/breakpoints';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
|
||||||
|
.components-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
flex: 1 1 100%;
|
||||||
|
color: nb-theme(color-fg-heading-light);
|
||||||
|
margin: 1rem 0 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.component-card-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.component-icon {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.component-name {
|
||||||
|
color: nb-theme(color-fg-heading-light);
|
||||||
|
font-weight: nb-theme(font-weight-bolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
.component-navigate-link {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nb-card {
|
||||||
|
box-shadow: 0 4px 27px 0 rgba(230, 234, 240, 0.2);
|
||||||
|
transition: transform 0.25s ease;
|
||||||
|
|
||||||
|
> nb-card-body {
|
||||||
|
height: 12.5rem;
|
||||||
|
padding: 2rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 15px 37px 0 #dbe2eb;
|
||||||
|
transform: translateY(-1rem);
|
||||||
|
.component-name {
|
||||||
|
color: nb-theme(color-fg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(is) {
|
||||||
|
.components-list {
|
||||||
|
|
||||||
|
.component-card-wrapper {
|
||||||
|
flex: 1 0 auto;
|
||||||
|
width: 50%;
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
.components-list {
|
||||||
|
|
||||||
|
.component-card-wrapper {
|
||||||
|
flex: 1 0 auto;
|
||||||
|
max-width: 33.3%;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
import { NgxMenuService } from '../../../@theme/services/menu.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-components-overview-block',
|
||||||
|
styleUrls: ['./components-overview-block.component.scss'],
|
||||||
|
templateUrl: './components-overview-block.component.html',
|
||||||
|
})
|
||||||
|
export class NgxComponentsOverviewBlockComponent implements OnInit {
|
||||||
|
components: { name: string; icon: string; link: string }[];
|
||||||
|
|
||||||
|
constructor(private menu: NgxMenuService) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.components = this.menu
|
||||||
|
.getPreparedMenu('/docs')
|
||||||
|
.find(({ title }) => title === 'Components')
|
||||||
|
.children
|
||||||
|
.slice(1)
|
||||||
|
.map(({ data: { name, icon, type }, link }) => ({ name, icon, link, group: type === 'group' }));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
import {
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Component,
|
||||||
|
Input,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { NgxCodeLoaderService } from '../../../@theme/services/code-loader.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-example-block',
|
||||||
|
template: `
|
||||||
|
<ngx-code-block *ngIf="code"
|
||||||
|
[firstLine]="firstLine"
|
||||||
|
[lastLine]="lastLine"
|
||||||
|
[code]="code">
|
||||||
|
</ngx-code-block>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxExampleBlockComponent {
|
||||||
|
|
||||||
|
code: string;
|
||||||
|
firstLine: number;
|
||||||
|
lastLine: number;
|
||||||
|
|
||||||
|
@Input('content')
|
||||||
|
set setContent(content) {
|
||||||
|
this.loadCode(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private codeLoader: NgxCodeLoaderService, private cd: ChangeDetectorRef) {
|
||||||
|
}
|
||||||
|
|
||||||
|
loadCode(content) {
|
||||||
|
this.codeLoader.load(content.files[0])
|
||||||
|
.subscribe((code: string) => {
|
||||||
|
this.code = code;
|
||||||
|
this.firstLine = content.firstLine || 1;
|
||||||
|
this.lastLine = content.lastLine || code.split('\n').length;
|
||||||
|
this.cd.detectChanges();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-examples-block',
|
||||||
|
template: `
|
||||||
|
<nb-card [ngxFragment]="source.slag">
|
||||||
|
<nb-card-body>
|
||||||
|
<h2>{{ source.name }}</h2>
|
||||||
|
<ngx-stacked-example-block *ngFor="let example of source.liveExamples" [content]="example.content"
|
||||||
|
class="widget-block">
|
||||||
|
</ngx-stacked-example-block>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxExamplesBlockComponent {
|
||||||
|
|
||||||
|
@Input('source') source;
|
||||||
|
|
||||||
|
}
|
20
docs/app/blocks/components/index.ts
Normal file
20
docs/app/blocks/components/index.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
export * from './md-block/md-block.component';
|
||||||
|
export * from './tabbed-block/tabbed-block.component';
|
||||||
|
export * from './overview-block/overview-block.component';
|
||||||
|
export * from './code-block/code-block.component';
|
||||||
|
export * from './tabbed-example-block/tabbed-example-block.component';
|
||||||
|
export * from './example-block/example-block.component';
|
||||||
|
export * from './inline-example-block/inline-example-block.component';
|
||||||
|
export * from './live-example-block/live-example-block.component';
|
||||||
|
export * from './stacked-example-block/stacked-examples.component';
|
||||||
|
export * from './methods-block/methods-block.component';
|
||||||
|
export * from './props-block/props-block.component';
|
||||||
|
export * from './prop-block/prop-block.component';
|
||||||
|
export * from './styles-block/styles-block.component';
|
||||||
|
export * from './theme-block/theme-block.component';
|
||||||
|
export * from './component-block/component-block.component';
|
||||||
|
export * from './api-block/api-block.component';
|
||||||
|
export * from './styles-table-block/styles-table-block.component';
|
||||||
|
export * from './examples-block/examples-block.component';
|
||||||
|
export * from './pager-block/pager-block.component';
|
||||||
|
export * from './components-overview-block/components-overview-block.component';
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-inline-example-block',
|
||||||
|
template: `
|
||||||
|
<ngx-example-block *ngIf="isOneFile" [content]="content"></ngx-example-block>
|
||||||
|
<ngx-tabbed-example-block *ngIf="isTabbed" [content]="content"></ngx-tabbed-example-block>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxInlineExampleBlockComponent {
|
||||||
|
|
||||||
|
@Input() content;
|
||||||
|
|
||||||
|
get isOneFile(): boolean {
|
||||||
|
return !this.isTabbed;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isTabbed(): boolean {
|
||||||
|
return this.content.files.length > 1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
<section class="header" >
|
||||||
|
<strong class="title">{{ content.name }}</strong>
|
||||||
|
<div class="actions">
|
||||||
|
|
||||||
|
<div class="action-selector">
|
||||||
|
<select class="action-item" [(ngModel)]="currentTheme" (change)="switchTheme($event.target.value)">
|
||||||
|
<option *ngFor="let theme of themes" [value]="theme.value">{{theme.label}}</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon feather-aperture"></i>
|
||||||
|
</div>
|
||||||
|
<a class="btn action-item action-button" target="_blank" [href]="url">
|
||||||
|
<i class="icon feather-external-link"></i>
|
||||||
|
</a>
|
||||||
|
<button type="button"
|
||||||
|
*ngIf="hasViewSwitch"
|
||||||
|
class="btn action-item action-button"
|
||||||
|
(click)="switchToInlineVew()">
|
||||||
|
<i class="icon feather-code"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<div class="iframe-container">
|
||||||
|
<iframe #iframe *ngIf="content.id" [style.height.px]="iframeHeight" [class.loading]="loading"></iframe>
|
||||||
|
</div>
|
||||||
|
<span class="icon-loading feather-more-vertical" *ngIf="loading"></span>
|
|
@ -0,0 +1,170 @@
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
|
||||||
|
// TODO: move some variables in Nebular themes
|
||||||
|
// colors
|
||||||
|
$action-bg: white;
|
||||||
|
$action-fg: nb-theme(color-fg-heading-light);
|
||||||
|
$block-bg-default: #ebeff5;
|
||||||
|
$block-bg-cosmic: #2f296b;
|
||||||
|
$block-fg-cosmic: #7d838b;
|
||||||
|
$block-bg-corporate: #f1f5f8;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 0.5rem 1rem 2.5rem 1.5rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 1.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title,
|
||||||
|
.actions {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-right: 1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-item {
|
||||||
|
background-color: $action-bg;
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
height: 100%;
|
||||||
|
line-height: 1;
|
||||||
|
border: none;
|
||||||
|
color: $action-fg;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
margin-left: 0.625rem;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover, &:focus {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-selector {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.action-item {
|
||||||
|
padding: 0;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
color: $action-fg;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Target IE9 - IE11 */
|
||||||
|
select::-ms-expand {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.theme-default {
|
||||||
|
background-color: $block-bg-default;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.theme-cosmic {
|
||||||
|
background-color: $block-bg-cosmic;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.action-item {
|
||||||
|
color: $block-fg-cosmic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.theme-corporate {
|
||||||
|
background-color: $block-bg-corporate;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iframe-container {
|
||||||
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe {
|
||||||
|
width: 100%;
|
||||||
|
border: none;
|
||||||
|
transform: translateZ(0);
|
||||||
|
|
||||||
|
&.loading {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-loading {
|
||||||
|
animation: rotation 2s infinite linear;
|
||||||
|
color: $action-fg;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: normal;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes rotation {
|
||||||
|
from {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
-webkit-transform: rotate(359deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 23em) {
|
||||||
|
.action-selector {
|
||||||
|
.action-item {
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
color: $action-fg;
|
||||||
|
}
|
||||||
|
select.action-item {
|
||||||
|
padding: 0 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
left: 1.25rem;
|
||||||
|
transform: translate(0, -50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
ElementRef,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
OnDestroy,
|
||||||
|
ViewChild,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
HostBinding,
|
||||||
|
Output,
|
||||||
|
EventEmitter,
|
||||||
|
AfterViewInit,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { Location } from '@angular/common';
|
||||||
|
import { takeWhile } from 'rxjs/operators';
|
||||||
|
import { NgxExampleView } from '../../enum.example-view';
|
||||||
|
import { NgxIframeCommunicatorService } from '../../../@theme/services/iframe-communicator.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-live-example-block',
|
||||||
|
styleUrls: ['./live-example-block.component.scss'],
|
||||||
|
templateUrl: './live-example-block.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxLiveExampleBlockComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||||
|
|
||||||
|
@ViewChild('iframe', { static: false }) iframe: ElementRef;
|
||||||
|
@Input() content: any;
|
||||||
|
@Input() hasViewSwitch: boolean = false;
|
||||||
|
@Output() changeView = new EventEmitter<NgxExampleView>();
|
||||||
|
|
||||||
|
/* tslint:disable:no-unused-variable */
|
||||||
|
@HostBinding('class.theme-default')
|
||||||
|
private get isDefault() {
|
||||||
|
return this.currentTheme === 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostBinding('class.theme-cosmic')
|
||||||
|
private get isCosmic() {
|
||||||
|
return this.currentTheme === 'cosmic';
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostBinding('class.theme-corporate')
|
||||||
|
private get isCorporate() {
|
||||||
|
return this.currentTheme === 'corporate';
|
||||||
|
}
|
||||||
|
/* tslint:enable:no-unused-variable */
|
||||||
|
|
||||||
|
iframeHeight = 0;
|
||||||
|
alive: boolean = true;
|
||||||
|
|
||||||
|
themes: {label: string; value: string}[] = [
|
||||||
|
{ label: 'Default', value: 'default' },
|
||||||
|
{ label: 'Cosmic', value: 'cosmic' },
|
||||||
|
{ label: 'Corporate', value: 'corporate' },
|
||||||
|
];
|
||||||
|
|
||||||
|
currentTheme: string = 'default';
|
||||||
|
loading = true;
|
||||||
|
|
||||||
|
get url(): string {
|
||||||
|
return this.location.prepareExternalUrl(`example/${this.content.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
get iframeWindow(): Window {
|
||||||
|
return this.iframe.nativeElement.contentWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private changeDetection: ChangeDetectorRef,
|
||||||
|
private location: Location,
|
||||||
|
private communicator: NgxIframeCommunicatorService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.communicator.receive(this.content.id)
|
||||||
|
.pipe(takeWhile(() => this.alive))
|
||||||
|
.subscribe(it => {
|
||||||
|
this.iframeHeight = it.height;
|
||||||
|
this.loading = false;
|
||||||
|
this.changeDetection.detectChanges();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
// we cannot set src using angular binding
|
||||||
|
// as it will trigger change detection and reload iframe
|
||||||
|
// which in its turn will send a new height
|
||||||
|
// and we would need to set the height and trigger change detection again
|
||||||
|
// resulting in infinite loop
|
||||||
|
this.iframe.nativeElement.src = this.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.alive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switchTheme(theme: string) {
|
||||||
|
this.communicator.send({ id: this.content.id, theme }, this.iframeWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
switchToInlineVew() {
|
||||||
|
this.changeView.emit(NgxExampleView.INLINE);
|
||||||
|
}
|
||||||
|
}
|
23
docs/app/blocks/components/md-block/md-block.component.ts
Normal file
23
docs/app/blocks/components/md-block/md-block.component.ts
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-md-block',
|
||||||
|
template: `
|
||||||
|
<nb-card *ngFor="let section of source;" [ngxFragment]="section.fragment">
|
||||||
|
<nb-card-body>
|
||||||
|
<div [innerHtml]="section.html"></div>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxMdBLockComponent {
|
||||||
|
|
||||||
|
@Input() source: string;
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-methods-block',
|
||||||
|
template: `
|
||||||
|
<h3>Methods</h3>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td width="25%">Name</td>
|
||||||
|
<td>Description</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<ng-container *ngFor="let method of methods">
|
||||||
|
<tr *ngIf="method.shortDescription || method.description">
|
||||||
|
<td>{{ method.name }}() <br><i *ngIf="method.isStatic">static method</i></td>
|
||||||
|
<td>
|
||||||
|
<div class="method-signature">
|
||||||
|
<div *ngIf="method.params.length > 0">
|
||||||
|
<i>parameters:</i>
|
||||||
|
<span *ngFor="let param of method.params; let last = last">
|
||||||
|
{{ param.name }}: <code>{{ param.type }}</code><span *ngIf="!last">,</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<i>returns:</i>
|
||||||
|
<code>{{ method.type.join(",\\n") }}</code>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="method.shortDescription || method.description" class="method-description" ngxDescription>
|
||||||
|
{{ method.shortDescription }} <br> {{ method.description }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</ng-container>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxMethodsBlockComponent {
|
||||||
|
|
||||||
|
methods: any;
|
||||||
|
|
||||||
|
@Input('source')
|
||||||
|
set setSource(source: any) {
|
||||||
|
this.methods = source.methods;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-overview-block',
|
||||||
|
template: `
|
||||||
|
<nb-card [ngxFragment]="source.slag">
|
||||||
|
<nb-card-body>
|
||||||
|
<ng-container class="description" *ngFor="let node of overview">
|
||||||
|
<ng-container *ngIf="node.type === 'text'">
|
||||||
|
<div *ngFor="let section of node.content" [innerHtml]="section.html"></div>
|
||||||
|
</ng-container>
|
||||||
|
<ngx-live-example-block *ngIf="node.type === 'live-example'" [content]="node.content"
|
||||||
|
class="widget-block">
|
||||||
|
</ngx-live-example-block>
|
||||||
|
<ngx-inline-example-block *ngIf="node.type === 'inline-example'" [content]="node.content"
|
||||||
|
class="widget-block">
|
||||||
|
</ngx-inline-example-block>
|
||||||
|
<ngx-stacked-example-block *ngIf="node.type === 'stacked-example'" [content]="node.content"
|
||||||
|
class="widget-block">
|
||||||
|
</ngx-stacked-example-block>
|
||||||
|
</ng-container>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxOverviewBlockComponent {
|
||||||
|
|
||||||
|
source: any;
|
||||||
|
overview: any[] = [];
|
||||||
|
|
||||||
|
@Input('source')
|
||||||
|
set setSource(source: any) {
|
||||||
|
this.source = source;
|
||||||
|
this.overview = source.overview;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
@import '~@nebular/theme/styles/global/breakpoints';
|
||||||
|
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
|
||||||
|
$title-fg: nb-theme(color-fg-heading);
|
||||||
|
$text-fg: nb-theme(color-fg-text);
|
||||||
|
$arrow-fg: nb-theme(color-fg-highlight);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
::ng-deep nb-card {
|
||||||
|
font-weight: 300;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
&.invisible {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
padding: 2rem;
|
||||||
|
text-decoration: none;
|
||||||
|
color: $text-fg;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
color: $title-fg;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: $arrow-fg;
|
||||||
|
margin-top: 0.3rem;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.7rem;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
word-wrap: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.left-block {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(sm) {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
::ng-deep nb-card {
|
||||||
|
margin-left: 1rem;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
padding: 2rem 3rem 2rem 2rem;
|
||||||
|
}
|
||||||
|
.page-title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-bottom: 0.6rem;
|
||||||
|
}
|
||||||
|
.description {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
import {Component, ChangeDetectionStrategy, Input} from '@angular/core';
|
||||||
|
import { NgxPaginationService } from '../../../@theme/services/pagination.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-pager-block',
|
||||||
|
styleUrls: ['./pager-block.component.scss'],
|
||||||
|
template: `
|
||||||
|
<ng-container *ngIf="paginationItem">
|
||||||
|
<nb-card [class.invisible]="!paginationItem.prev" class="left-block">
|
||||||
|
<a *ngIf="paginationItem.prev" [routerLink]="paginationItem.prev.link"
|
||||||
|
[attr.title]="paginationItem.prev.title">
|
||||||
|
<div class="page-title">
|
||||||
|
<i class="icon nb-arrow-thin-left"></i>
|
||||||
|
<span>{{ paginationItem.prev.title }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="description">Previous page</div>
|
||||||
|
</a>
|
||||||
|
</nb-card>
|
||||||
|
|
||||||
|
<nb-card [class.invisible]="!paginationItem.next" class="right-block">
|
||||||
|
<a *ngIf="paginationItem.next" [routerLink]="paginationItem.next.link"
|
||||||
|
[attr.title]="paginationItem.next.title">
|
||||||
|
<div class="page-title">
|
||||||
|
<span>{{ paginationItem.next.title }}</span>
|
||||||
|
<i class="icon nb-arrow-thin-right"></i>
|
||||||
|
</div>
|
||||||
|
<div class="description">Next page</div>
|
||||||
|
</a>
|
||||||
|
</nb-card>
|
||||||
|
</ng-container>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxPagerBlockComponent {
|
||||||
|
paginationItem;
|
||||||
|
|
||||||
|
@Input('currentItemSlag')
|
||||||
|
set setPaginationItem(currentItemSlag: string) {
|
||||||
|
this.paginationItem = this.getPaginationItem(currentItemSlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private paginationService: NgxPaginationService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
getPaginationItem(currentItemSlag) {
|
||||||
|
return this.paginationService.getPaginationItem(currentItemSlag);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-prop-block',
|
||||||
|
template: `
|
||||||
|
<h3>{{ name }}</h3>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td width="25%">Name</td>
|
||||||
|
<td width="20%">Type</td>
|
||||||
|
<td>Description</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let prop of properties">
|
||||||
|
<td>{{ prop.name }}</td>
|
||||||
|
<td><code *ngIf="prop.type">{{ prop.type }}</code></td>
|
||||||
|
<td>
|
||||||
|
<div *ngIf="prop.shortDescription" ngxDescription>{{ prop.shortDescription }}</div>
|
||||||
|
<div *ngIf="prop.description" ngxDescription>{{ prop.description }}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxPropBlockComponent {
|
||||||
|
|
||||||
|
@Input() properties = [];
|
||||||
|
@Input() name;
|
||||||
|
@Input() slag;
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-props-block',
|
||||||
|
template: `
|
||||||
|
<ngx-prop-block *ngIf="inputs.length > 0"
|
||||||
|
[properties]="inputs"
|
||||||
|
name="Inputs"
|
||||||
|
[slag]="slag"
|
||||||
|
class="widget-block">
|
||||||
|
</ngx-prop-block>
|
||||||
|
|
||||||
|
<ngx-prop-block *ngIf="outputs.length > 0"
|
||||||
|
[properties]="outputs"
|
||||||
|
name="Outputs"
|
||||||
|
[slag]="slag"
|
||||||
|
class="widget-block">
|
||||||
|
</ngx-prop-block>
|
||||||
|
|
||||||
|
<ngx-prop-block *ngIf="props.length > 0"
|
||||||
|
[properties]="props"
|
||||||
|
name="Properties"
|
||||||
|
[slag]="slag"
|
||||||
|
class="widget-block">
|
||||||
|
</ngx-prop-block>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxPropsBlockComponent {
|
||||||
|
outputs: any = [];
|
||||||
|
inputs: any = [];
|
||||||
|
props: any = [];
|
||||||
|
name: string;
|
||||||
|
slag: string;
|
||||||
|
|
||||||
|
@Input('source')
|
||||||
|
set setSource(source: any) {
|
||||||
|
this.inputs = source.props.filter(item => item.kind === 'input');
|
||||||
|
this.outputs = source.props.filter(item => item.kind === 'output');
|
||||||
|
this.props = source.props.filter(item => item.kind === 'property');
|
||||||
|
this.name = source.name;
|
||||||
|
this.slag = source.slag;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
import { NgxExampleView } from '../../enum.example-view';
|
||||||
|
import { animate, animation, keyframes, style, transition, trigger, useAnimation } from '@angular/animations';
|
||||||
|
|
||||||
|
export const pulse = animation(
|
||||||
|
animate(
|
||||||
|
'{{ timing }}s {{ delay }}s',
|
||||||
|
keyframes([
|
||||||
|
style({ transform: 'scale3d(1, 1, 1)' }),
|
||||||
|
style({ transform: 'scale3d({{ scale }}, {{ scale }}, {{ scale }})' }),
|
||||||
|
style({ transform: 'scale3d(1, 1, 1)' }),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
{ params: { scale: 1.02, timing: 0.5, delay: 0 } },
|
||||||
|
);
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-stacked-example-block',
|
||||||
|
template: `
|
||||||
|
<div>
|
||||||
|
<ngx-live-example-block [hidden]="!isLive"
|
||||||
|
[@exampleState]="isLive ? 'live': 'code'"
|
||||||
|
[content]="content"
|
||||||
|
hasViewSwitch="true"
|
||||||
|
(changeView)="changeView($event)">
|
||||||
|
</ngx-live-example-block>
|
||||||
|
|
||||||
|
<ngx-tabbed-example-block [hidden]="isLive"
|
||||||
|
[@exampleState]="isLive ? 'live': 'code'"
|
||||||
|
[content]="content"
|
||||||
|
hasViewSwitch="true"
|
||||||
|
(changeView)="changeView($event)">
|
||||||
|
</ngx-tabbed-example-block>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
animations: [
|
||||||
|
trigger('exampleState', [
|
||||||
|
transition('live => code', [
|
||||||
|
useAnimation(pulse),
|
||||||
|
]),
|
||||||
|
transition('code => live', [
|
||||||
|
useAnimation(pulse),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class NgxStackedExampleComponent {
|
||||||
|
|
||||||
|
@Input() content: any;
|
||||||
|
isLive = true;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
changeView(view: NgxExampleView) {
|
||||||
|
this.isLive = view === NgxExampleView.LIVE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-styles-block',
|
||||||
|
template: `
|
||||||
|
<nb-card [ngxFragment]="source.slag">
|
||||||
|
<nb-card-body>
|
||||||
|
<h2>{{ source.name }}</h2>
|
||||||
|
<ngx-styles-table-block [source]="source"></ngx-styles-table-block>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxStylesBlockComponent {
|
||||||
|
|
||||||
|
@Input() source;
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
|
import { NgxStylesService } from '../../../@theme/services/styles.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-styles-table-block',
|
||||||
|
template: `
|
||||||
|
<table class="striped" *ngFor="let style of classStyles">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>Name</td>
|
||||||
|
<td *ngFor="let themedValue of style.styles[0].themedValues">{{ themedValue.theme }}</td>
|
||||||
|
<td>Description</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let item of style.styles">
|
||||||
|
<td>{{ item.name }}</td>
|
||||||
|
<td *ngFor="let themedValue of item.themedValues" ngxColorSwatch>{{ themedValue.value }}</td>
|
||||||
|
<td>
|
||||||
|
<p *ngIf="item.shortDescription" ngxDescription>{{ item.shortDescription}}</p>
|
||||||
|
<p *ngIf="item.description" ngxDescription>{{ item.description }}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxStylesTableBlockComponent {
|
||||||
|
|
||||||
|
classStyles: any;
|
||||||
|
|
||||||
|
@Input('source')
|
||||||
|
set setSource(source: any) {
|
||||||
|
this.classStyles = this.stylesService.mapThemedValues(source.styles);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private stylesService: NgxStylesService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
<ng-container [ngSwitch]="currentTab?.tab">
|
||||||
|
<ng-container *ngFor="let component of source">
|
||||||
|
|
||||||
|
<ng-container *ngSwitchCase="'overview'">
|
||||||
|
<ngx-overview-block *ngIf="hasOverview(component)" [source]="component"></ngx-overview-block>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngSwitchCase="'theme'">
|
||||||
|
<ngx-styles-block *ngIf="hasTheme(component)" [source]="component"></ngx-styles-block>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngSwitchCase="'api'">
|
||||||
|
<ngx-api-block *ngIf="hasAPI(component)" [source]="component" ></ngx-api-block>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngSwitchCase="'examples'">
|
||||||
|
<ngx-examples-block *ngIf="hasExamples(component)" [source]="component" ></ngx-examples-block>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
|
@ -0,0 +1,96 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy } from '@angular/core';
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
import { Title } from '@angular/platform-browser';
|
||||||
|
import { BehaviorSubject, combineLatest } from 'rxjs';
|
||||||
|
import { filter, takeWhile } from 'rxjs/operators';
|
||||||
|
import { NgxTabbedService } from '../../../@theme/services/tabbed.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-tabbed-block',
|
||||||
|
templateUrl: './tabbed-block.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxTabbedBlockComponent implements OnDestroy {
|
||||||
|
|
||||||
|
currentTab;
|
||||||
|
|
||||||
|
@Input() source;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
set tabs(value) {
|
||||||
|
if (value) {
|
||||||
|
value = Object
|
||||||
|
.entries(value)
|
||||||
|
.filter(([key, val]) => val)
|
||||||
|
.map(([key, val]) => ({ tab: key }));
|
||||||
|
|
||||||
|
this.tabs$.next(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private tabs$ = new BehaviorSubject(null);
|
||||||
|
private alive = true;
|
||||||
|
|
||||||
|
constructor(private activatedRoute: ActivatedRoute,
|
||||||
|
private router: Router,
|
||||||
|
private cd: ChangeDetectorRef,
|
||||||
|
private titleService: Title,
|
||||||
|
private tabbedService: NgxTabbedService) {
|
||||||
|
|
||||||
|
combineLatest([
|
||||||
|
this.activatedRoute.params.pipe(filter((params) => !params.tab)),
|
||||||
|
this.tabs$.pipe(filter((tabs) => tabs && tabs.length)),
|
||||||
|
])
|
||||||
|
.pipe(takeWhile(() => this.alive))
|
||||||
|
.subscribe(([params, tabs]) => {
|
||||||
|
this.router.navigate([tabs[0].tab], { relativeTo: activatedRoute, replaceUrl: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
combineLatest([
|
||||||
|
this.activatedRoute.params.pipe(filter((params) => params.tab)),
|
||||||
|
this.tabs$.pipe(filter((tabs) => tabs && tabs.length)),
|
||||||
|
])
|
||||||
|
.pipe(takeWhile(() => this.alive))
|
||||||
|
.subscribe(([params, tabs]) => {
|
||||||
|
this.currentTab = tabs.find(tab => tab.tab === params.tab);
|
||||||
|
if (this.currentTab) {
|
||||||
|
this.titleService.setTitle(`${this.titleService.getTitle()} - component ${this.currentTab.tab}`);
|
||||||
|
}
|
||||||
|
this.cd.detectChanges();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
hasOverview(component) {
|
||||||
|
return this.tabbedService.componentHasOverview(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasExamples(component) {
|
||||||
|
return this.tabbedService.componentHasExamples(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasTheme(component) {
|
||||||
|
return this.tabbedService.componentHasTheme(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasMethods(component) {
|
||||||
|
return this.tabbedService.componentHasMethods(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasProps(component) {
|
||||||
|
return this.tabbedService.componentHasProps(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasAPI(component) {
|
||||||
|
return this.hasMethods(component) || this.hasProps(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.alive = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
<button type="button"
|
||||||
|
*ngIf="hasViewSwitch"
|
||||||
|
class="btn action-item action-button"
|
||||||
|
(click)="switchToLiveView()">
|
||||||
|
<i class="icon feather-image"></i>
|
||||||
|
<span class="text">Live view</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<nb-tabset class="tabs-container">
|
||||||
|
<nb-tab *ngFor="let example of examples" tabTitle="{{ example.extension }}" [active]="example.active">
|
||||||
|
<ngx-code-block [path]="example.path" [code]="example.code"></ngx-code-block>
|
||||||
|
</nb-tab>
|
||||||
|
</nb-tabset>
|
|
@ -0,0 +1,84 @@
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
@import '~@nebular/theme/styles/global/breakpoints';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
|
||||||
|
$tab-fg: nb-theme(color-fg-heading-light);
|
||||||
|
$tab-active-fg: #ffffff;
|
||||||
|
$tab-active-bg: linear-gradient(225deg, #333c66 0%, #1d2447 100%);
|
||||||
|
$tabs-bb: #ebeff5;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: transparent;
|
||||||
|
color: $tab-fg;
|
||||||
|
text-transform: inherit;
|
||||||
|
padding: 0.45rem 1.5rem;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus, &:active, &:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
color: $tab-fg;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep nb-tabset.tabs-container {
|
||||||
|
border-radius: 0.5rem 0.5rem 0 0;
|
||||||
|
|
||||||
|
> ul {
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: 0!important; // TODO: check selectors
|
||||||
|
border-radius: 0.5rem 0.5rem 0 0;
|
||||||
|
background-color: $tabs-bb;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
li {
|
||||||
|
padding: 0.4rem;
|
||||||
|
width: 20%;
|
||||||
|
margin-bottom: 0!important; // TODO: check selectors
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $tab-fg;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: $tab-active-bg;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $tab-active-fg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
border-radius: 0 0 0.5rem 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(is) {
|
||||||
|
button .text {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
import {
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Component,
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
EventEmitter,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { forkJoin, of as observableOf, Observable } from 'rxjs';
|
||||||
|
import { map, catchError } from 'rxjs/operators';
|
||||||
|
import { NgxExampleView } from '../../enum.example-view';
|
||||||
|
import { NgxCodeLoaderService } from '../../../@theme/services/code-loader.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-tabbed-example-block',
|
||||||
|
styleUrls: ['./tabbed-example-block.component.scss'],
|
||||||
|
templateUrl: './tabbed-example-block.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxTabbedExampleBlockComponent {
|
||||||
|
|
||||||
|
|
||||||
|
@Input() hasViewSwitch = false;
|
||||||
|
@Output() changeView = new EventEmitter<NgxExampleView>();
|
||||||
|
examples = [];
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
set content({ files }) {
|
||||||
|
forkJoin(files.map(file => this.load(file)))
|
||||||
|
.subscribe(loadedFiles => {
|
||||||
|
(loadedFiles[0] as any).active = true;
|
||||||
|
this.examples = loadedFiles;
|
||||||
|
this.cd.detectChanges();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private codeLoader: NgxCodeLoaderService, private cd: ChangeDetectorRef) {
|
||||||
|
}
|
||||||
|
|
||||||
|
switchToLiveView() {
|
||||||
|
this.changeView.emit(NgxExampleView.LIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private load(path): Observable<any> {
|
||||||
|
const extension = path.split('.').pop();
|
||||||
|
return this.codeLoader.load(path)
|
||||||
|
.pipe(
|
||||||
|
map(code => ({ code, path, extension })),
|
||||||
|
catchError(e => observableOf('')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
<nb-card>
|
||||||
|
<nb-card-body>
|
||||||
|
<h2>{{ vm.themeTitle }} Theme</h2>
|
||||||
|
<p *ngIf="vm.parentTheme">inherited from {{ vm.parentTheme }} theme</p>
|
||||||
|
|
||||||
|
<div class="search-wrapper">
|
||||||
|
<input class="search-control" placeholder="Search for..." [formControl]="searchControl">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>Name</td>
|
||||||
|
<td>Value</td>
|
||||||
|
<td>Parent</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let prop of vm.filteredThemeProperties | async"
|
||||||
|
[ngxFragment]="prop.name"
|
||||||
|
[ngxFragmentSync]="false"
|
||||||
|
ngxFragmentClass="highlighted-row">
|
||||||
|
<td>
|
||||||
|
<a [routerLink]="" fragment="{{ prop.name }}">{{ prop.name }}</a>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td ngxColorSwatch>{{ prop.value }}</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<a [routerLink]="['/docs/themes', parent.theme]" fragment="{{ parent.prop }}"
|
||||||
|
[class.inheritance-property]="index > 0"
|
||||||
|
*ngFor="let parent of prop.parents; let index = index">
|
||||||
|
<i *ngIf="index > 0" class="inheritance-icon feather-arrow-left"></i>
|
||||||
|
<span>{{ parent.prop }}</span>
|
||||||
|
<span *ngIf="parent.theme !== vm.themeName" class="parent-theme-name">({{ parent.theme }})</span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
|
@ -0,0 +1,40 @@
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
|
||||||
|
$inherited-fg: nb-theme(color-fg);
|
||||||
|
$search-fg: nb-theme(color-fg);
|
||||||
|
$search-bg: nb-theme(color-white);
|
||||||
|
$search-border: 1px solid nb-theme(color-gray-light);
|
||||||
|
$selected-row-bg: nb-theme(color-gray-light);
|
||||||
|
|
||||||
|
.inheritance-icon {
|
||||||
|
margin: 0 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inheritance-property {
|
||||||
|
color: $inherited-fg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parent-theme-name {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlighted-row {
|
||||||
|
background-color: $selected-row-bg !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-control {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.375rem 0.75rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: $search-fg;
|
||||||
|
background-color: $search-bg;
|
||||||
|
background-clip: padding-box;
|
||||||
|
border: $search-border;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
OnDestroy,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { FormControl } from '@angular/forms';
|
||||||
|
import { takeWhile, skip, distinctUntilChanged, debounceTime } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { ThemeBlockModel } from './theme-block.model';
|
||||||
|
import { ThemeBlockViewModel } from './theme-block.viewmodel';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-theme-block',
|
||||||
|
styleUrls: ['./theme-block.component.scss'],
|
||||||
|
templateUrl: './theme-block.component.html',
|
||||||
|
providers: [ThemeBlockModel, ThemeBlockViewModel],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class NgxThemeComponent implements OnInit, OnDestroy {
|
||||||
|
searchControl = new FormControl();
|
||||||
|
|
||||||
|
private alive: boolean = true;
|
||||||
|
|
||||||
|
@Input('block')
|
||||||
|
set setBlock(block: any) {
|
||||||
|
this.vm.themeTitle = block.name;
|
||||||
|
this.vm.themeName = block.source.name;
|
||||||
|
this.vm.parentTheme = block.source.parent;
|
||||||
|
this.vm.themeProperties = block.source.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(public vm: ThemeBlockViewModel) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.searchControl.valueChanges
|
||||||
|
.pipe(skip(1), distinctUntilChanged(), debounceTime(300), takeWhile(() => this.alive))
|
||||||
|
.subscribe(value => this.vm.changeSearch(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.alive = false;
|
||||||
|
}
|
||||||
|
}
|
25
docs/app/blocks/components/theme-block/theme-block.model.ts
Normal file
25
docs/app/blocks/components/theme-block/theme-block.model.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ThemeBlockModel {
|
||||||
|
themeTitle: string;
|
||||||
|
themeName: string;
|
||||||
|
parentTheme: string;
|
||||||
|
themeProperties: any[];
|
||||||
|
|
||||||
|
setThemeTitle(value) {
|
||||||
|
this.themeTitle = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setThemeName(value) {
|
||||||
|
this.themeName = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setParentTheme(value) {
|
||||||
|
this.parentTheme = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setThemeProperties(value) {
|
||||||
|
this.themeProperties = value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable, BehaviorSubject, of as observableOf } from 'rxjs';
|
||||||
|
import { switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { ThemeBlockModel } from './theme-block.model';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ThemeBlockViewModel {
|
||||||
|
private searchChanges$ = new BehaviorSubject<string>(null);
|
||||||
|
|
||||||
|
constructor(private model: ThemeBlockModel) {}
|
||||||
|
|
||||||
|
changeSearch(value) {
|
||||||
|
this.searchChanges$.next(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get themeTitle(): string {
|
||||||
|
return this.model.themeTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
set themeTitle(value) {
|
||||||
|
this.model.setThemeTitle(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get themeName(): string {
|
||||||
|
return this.model.themeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
set themeName(value) {
|
||||||
|
this.model.setThemeName(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get parentTheme(): string {
|
||||||
|
return this.model.parentTheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
set parentTheme(value) {
|
||||||
|
this.model.setParentTheme(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get themeProperties(): any[] {
|
||||||
|
return this.model.themeProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
set themeProperties(value) {
|
||||||
|
const result = Object.entries(value).map(([key, data]) => {
|
||||||
|
const propertyValue = data['value'];
|
||||||
|
return {
|
||||||
|
name: key,
|
||||||
|
value: Array.isArray(propertyValue) ? propertyValue.join(' ') : propertyValue,
|
||||||
|
parents: data['parents'],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
this.model.setThemeProperties(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
get filteredThemeProperties(): Observable<any[]> {
|
||||||
|
return this.searchChanges$.asObservable().pipe(
|
||||||
|
switchMap(value => {
|
||||||
|
if (value) {
|
||||||
|
return observableOf(
|
||||||
|
this.themeProperties.filter(({ name }) => name.toLowerCase().includes(value.toLowerCase())),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return observableOf(this.themeProperties);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
4
docs/app/blocks/enum.example-view.ts
Normal file
4
docs/app/blocks/enum.example-view.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export enum NgxExampleView {
|
||||||
|
LIVE = 'live',
|
||||||
|
INLINE = 'inline',
|
||||||
|
}
|
39
docs/app/pages/docs/landing-docs-routing.module.ts
Normal file
39
docs/app/pages/docs/landing-docs-routing.module.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
import { LandingDocsComponent } from './landing-docs.component';
|
||||||
|
import { NgxAdminLandingPageComponent } from './page/ngx-admin-landing-page.component';
|
||||||
|
|
||||||
|
|
||||||
|
export const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: LandingDocsComponent,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: ':page',
|
||||||
|
component: NgxAdminLandingPageComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ':page/:subPage',
|
||||||
|
component: NgxAdminLandingPageComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ':page/:subPage/:tab',
|
||||||
|
component: NgxAdminLandingPageComponent,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule],
|
||||||
|
})
|
||||||
|
export class LandingDocsRoutingModule {
|
||||||
|
}
|
27
docs/app/pages/docs/landing-docs.component.html
Normal file
27
docs/app/pages/docs/landing-docs.component.html
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<nb-layout>
|
||||||
|
<nb-layout-header fixed>
|
||||||
|
<div class="content-center">
|
||||||
|
<ngx-landing-header class="docs-header" [sidebarTag]="sidebarTag" [isDocs]="true">
|
||||||
|
<ngx-material-theme-link withPopover></ngx-material-theme-link>
|
||||||
|
</ngx-landing-header>
|
||||||
|
</div>
|
||||||
|
</nb-layout-header>
|
||||||
|
<nb-sidebar class="menu-sidebar" [tag]="sidebarTag" [responsive]="true" [compactedBreakpoints]="[]" [collapsedBreakpoints]="collapsedBreakpoints">
|
||||||
|
<nb-menu [items]="menuItems" tag="leftMenu"></nb-menu>
|
||||||
|
</nb-sidebar>
|
||||||
|
<nb-layout-column>
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
|
||||||
|
<div class="contact-us">
|
||||||
|
<h2>Need some help or found an issue?</h2>
|
||||||
|
<p>
|
||||||
|
Ask on <a href="https://stackoverflow.com/questions/ask">Stack Overflow</a> with tag `ngx-admin` or
|
||||||
|
post an issue on <a href="https://github.com/akveo/ngx-admin/issues/new">GitHub</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</nb-layout-column>
|
||||||
|
<nb-layout-footer>
|
||||||
|
<ngx-docs-footer></ngx-docs-footer>
|
||||||
|
</nb-layout-footer>
|
||||||
|
</nb-layout>
|
||||||
|
|
80
docs/app/pages/docs/landing-docs.component.scss
Normal file
80
docs/app/pages/docs/landing-docs.component.scss
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import '../../@theme/styles/themes';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
$content-width: nb-theme(content-width);
|
||||||
|
$settings-width: nb-theme(settings-col-width);
|
||||||
|
$settings-margin: nb-theme(settings-col-margin);
|
||||||
|
$color-heading: nb-theme(color-fg-heading-light);
|
||||||
|
|
||||||
|
.menu-sidebar.fixed {
|
||||||
|
box-shadow: 8px 0 20px 0 rgba(218, 224, 235, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
nb-layout-header {
|
||||||
|
background-color: nb-theme(header-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-center {
|
||||||
|
max-width: $content-width;
|
||||||
|
width: 100%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-us {
|
||||||
|
padding: 5rem 1rem;
|
||||||
|
h2 {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse-all {
|
||||||
|
position: absolute;
|
||||||
|
right: 1px;
|
||||||
|
top: 0.75rem;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: $color-heading;
|
||||||
|
appearance: none;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep nb-layout .main-container {
|
||||||
|
padding-top: 3rem;
|
||||||
|
|
||||||
|
.scrollable {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep nb-layout .layout-container {
|
||||||
|
max-width: $content-width;
|
||||||
|
width: 100%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep nb-layout-footer ngx-docs-footer .contact {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(xl) {
|
||||||
|
.contact-us {
|
||||||
|
padding: 5rem 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(macpro) {
|
||||||
|
::ng-deep nb-layout-footer {
|
||||||
|
margin-right: $settings-width + $settings-margin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
70
docs/app/pages/docs/landing-docs.component.ts
Normal file
70
docs/app/pages/docs/landing-docs.component.ts
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Component, OnDestroy} from '@angular/core';
|
||||||
|
import {Router} from '@angular/router';
|
||||||
|
import {map, takeWhile, withLatestFrom} from 'rxjs/operators';
|
||||||
|
import {
|
||||||
|
NbMediaBreakpoint,
|
||||||
|
NbMenuItem,
|
||||||
|
NbSidebarService,
|
||||||
|
NbThemeService} from '@nebular/theme';
|
||||||
|
|
||||||
|
import {NgxMenuService} from '../../@theme/services/menu.service';
|
||||||
|
import {NgxPaginationService} from '../../@theme/services/pagination.service';
|
||||||
|
import {MetadataService} from '../../../../src/app/@core/utils/metadata.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-landing-docs',
|
||||||
|
templateUrl: './landing-docs.component.html',
|
||||||
|
styleUrls: ['./landing-docs.component.scss'],
|
||||||
|
})
|
||||||
|
export class LandingDocsComponent implements OnDestroy {
|
||||||
|
menuItems: NbMenuItem[] = [];
|
||||||
|
collapsedBreakpoints = ['xs', 'is', 'sm', 'md', 'lg'];
|
||||||
|
sidebarTag = 'menuSidebar';
|
||||||
|
|
||||||
|
private alive = true;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private service: NgxMenuService,
|
||||||
|
private router: Router,
|
||||||
|
private themeService: NbThemeService,
|
||||||
|
private sidebarService: NbSidebarService,
|
||||||
|
private paginationService: NgxPaginationService,
|
||||||
|
private metadataService: MetadataService) {
|
||||||
|
|
||||||
|
this.metadataService.updateDescription('Free and Open Source ngx-admin to bootstrap the development of ' +
|
||||||
|
'your product or to learn Angular. Over 40+ Angular Components and 60+ Usage Examples.');
|
||||||
|
this.metadataService.updateTitle('A front-end admin dashboard on Angular 9+, Bootstrap 4+ and Nebular.');
|
||||||
|
|
||||||
|
this.themeService.changeTheme('docs-page');
|
||||||
|
this.paginationService.setPaginationItems('/docs');
|
||||||
|
this.menuItems = this.service.getPreparedMenu('/docs');
|
||||||
|
|
||||||
|
// TODO: can we do any better?
|
||||||
|
this.router.events
|
||||||
|
.pipe(
|
||||||
|
withLatestFrom(this.themeService.onMediaQueryChange().pipe(map((changes: any[]) => changes[1]))),
|
||||||
|
takeWhile(() => this.alive),
|
||||||
|
)
|
||||||
|
.subscribe(([event, mediaQuery]: [any, NbMediaBreakpoint]) => {
|
||||||
|
if (event.url === '/docs') {
|
||||||
|
const firstMenuItem = this.menuItems[0].children[0];
|
||||||
|
// angular bug with replaceUrl, temp fix with setTimeout
|
||||||
|
setTimeout(() => this.router.navigateByUrl(firstMenuItem.link, { replaceUrl: true }));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.collapsedBreakpoints.includes(mediaQuery.name)) {
|
||||||
|
this.sidebarService.collapse(this.sidebarTag);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.alive = false;
|
||||||
|
}
|
||||||
|
}
|
42
docs/app/pages/docs/landing-docs.module.ts
Normal file
42
docs/app/pages/docs/landing-docs.module.ts
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
|
||||||
|
// modules
|
||||||
|
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
|
||||||
|
import { LandingDocsComponent } from './landing-docs.component';
|
||||||
|
import { NgxAdminLandingPageComponent } from './page/ngx-admin-landing-page.component';
|
||||||
|
// components
|
||||||
|
|
||||||
|
/*import { NgxMenuService } from '../@theme/services/menu.service';*/
|
||||||
|
|
||||||
|
const COMPONENTS = [
|
||||||
|
LandingDocsComponent,
|
||||||
|
NgxAdminLandingPageComponent,
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
...COMPONENTS,
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
NgxLandingThemeModule,
|
||||||
|
SwiperModule,
|
||||||
|
LandingSharedModule,
|
||||||
|
LandingDocsRoutingModule,
|
||||||
|
NgxBlocksModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class LandingDocsModule {
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<div class="middle-column">
|
||||||
|
|
||||||
|
<nb-card *ngIf="currentItem?.tabs" class="horizontal-nav">
|
||||||
|
<nb-card-header>
|
||||||
|
{{ currentItem?.name }}
|
||||||
|
</nb-card-header>
|
||||||
|
<nb-card-body>
|
||||||
|
<ngx-page-tabs [tabs]="currentItem?.tabs" horizontal></ngx-page-tabs>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
|
||||||
|
<ng-container *ngFor="let block of currentItem?.children">
|
||||||
|
<ng-container [ngSwitch]="block.block">
|
||||||
|
<ngx-md-block *ngSwitchCase="'markdown'" [source]="block.children"></ngx-md-block>
|
||||||
|
<ngx-component-block *ngSwitchCase="'component'" [source]="block.source"></ngx-component-block>
|
||||||
|
<ngx-tabbed-block *ngSwitchCase="'tabbed'" [source]="block.children" [tabs]="currentItem.tabs"></ngx-tabbed-block>
|
||||||
|
<ngx-theme-block *ngSwitchCase="'theme'" [block]="block"></ngx-theme-block>
|
||||||
|
<ngx-components-overview-block *ngSwitchCase="'components-overview'"></ngx-components-overview-block>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<p class="not-found" *ngIf="!currentItem">Page does not exist.</p>
|
||||||
|
|
||||||
|
<ngx-pager-block [currentItemSlag]="currentItem?.slag"></ngx-pager-block>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="settings-column" *ngIf="showSettings">
|
||||||
|
<div class="fixed-panel">
|
||||||
|
<ngx-page-tabs [tabs]="currentItem?.tabs"></ngx-page-tabs>
|
||||||
|
<ngx-page-toc [toc]="currentItem?.toc"></ngx-page-toc>
|
||||||
|
</div>
|
||||||
|
</div>
|
243
docs/app/pages/docs/page/ngx-admin-landing-page.component.scss
Normal file
243
docs/app/pages/docs/page/ngx-admin-landing-page.component.scss
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
$note-fg-info: nb-theme(color-info);
|
||||||
|
$note-bg-info: #f0f6ff;
|
||||||
|
$note-fg-warning: nb-theme(color-warning);
|
||||||
|
$note-bg-warning: #fffae4;
|
||||||
|
$settings-width: nb-theme(settings-col-width);
|
||||||
|
$settings-margin: nb-theme(settings-col-margin);
|
||||||
|
$heading-light: nb-theme(color-fg-heading-light);
|
||||||
|
$code-bg: #f1f2f3;
|
||||||
|
$code-fg: nb-theme(color-info);
|
||||||
|
$code-block-bg: nb-theme(code-block-bg);
|
||||||
|
$table-head-fg: #8994a3;
|
||||||
|
$table-border: 1px solid #f1f2f3;
|
||||||
|
$table-stripe-bg: #f5f6f7;
|
||||||
|
|
||||||
|
.not-found {
|
||||||
|
color: $heading-light;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.middle-column {
|
||||||
|
flex: 3;
|
||||||
|
min-width: 0;
|
||||||
|
|
||||||
|
::ng-deep nb-card {
|
||||||
|
|
||||||
|
nb-card-body {
|
||||||
|
padding: 2rem 1rem;
|
||||||
|
|
||||||
|
> *:last-child {
|
||||||
|
margin-bottom: 0!important;
|
||||||
|
|
||||||
|
*:last-child {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
line-height: 1.25;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: $heading-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 0.9375rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: $code-bg;
|
||||||
|
color: $code-fg;
|
||||||
|
padding: 0.125rem 0.5rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
code.hljs {
|
||||||
|
color: #f8f8f2;
|
||||||
|
padding: 2rem 2.5rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
background: $code-block-bg;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep {
|
||||||
|
.widget-block {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx-styles-table-block table {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
font-size: 0.9375rem;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
thead {
|
||||||
|
color: $table-head-fg;
|
||||||
|
border-bottom: $table-border;
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 1rem 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tr {
|
||||||
|
border-bottom: $table-border;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 1rem 0.5rem;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.striped {
|
||||||
|
tbody tr:nth-child(odd) {
|
||||||
|
background: $table-stripe-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 1rem 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
ul {
|
||||||
|
padding-left: 2.5rem;
|
||||||
|
list-style-type: none;
|
||||||
|
& > li {
|
||||||
|
list-style: circle;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
font-size: 0.9375rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.note {
|
||||||
|
padding: 1.25rem 3rem 1.5rem 1.25rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
|
||||||
|
.note-title {
|
||||||
|
font-weight: 500;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-body {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.note-info {
|
||||||
|
color: $note-fg-info;
|
||||||
|
background-color: $note-bg-info;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.note-warning {
|
||||||
|
color: $note-fg-warning;
|
||||||
|
background-color: $note-bg-warning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-swatch {
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid black;
|
||||||
|
width: 0.875rem;
|
||||||
|
height: 0.875rem;
|
||||||
|
margin-left: 7px;
|
||||||
|
margin-bottom: -2px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal-nav {
|
||||||
|
margin-top: 1rem;
|
||||||
|
|
||||||
|
nb-card-body {
|
||||||
|
background-color: nb-theme(layout-bg);
|
||||||
|
padding: 0;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.settings-column {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
.middle-column ::ng-deep nb-card nb-card-body {
|
||||||
|
padding: 2rem 3rem 2rem 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(lg) {
|
||||||
|
.horizontal-nav {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(macpro) {
|
||||||
|
.horizontal-nav nb-card-body {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-column {
|
||||||
|
display: block;
|
||||||
|
margin-left: $settings-margin;
|
||||||
|
width: $settings-width;
|
||||||
|
|
||||||
|
ngx-page-tabs {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-panel {
|
||||||
|
position: fixed;
|
||||||
|
width: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
105
docs/app/pages/docs/page/ngx-admin-landing-page.component.ts
Normal file
105
docs/app/pages/docs/page/ngx-admin-landing-page.component.ts
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component, Inject, NgZone, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
import {
|
||||||
|
filter,
|
||||||
|
map,
|
||||||
|
publishBehavior,
|
||||||
|
publishReplay,
|
||||||
|
refCount,
|
||||||
|
tap,
|
||||||
|
takeWhile,
|
||||||
|
} from 'rxjs/operators';
|
||||||
|
import { NB_WINDOW } from '@nebular/theme';
|
||||||
|
import { fromEvent } from 'rxjs';
|
||||||
|
|
||||||
|
import { NgxStructureService } from '../../../@theme/services/structure.service';
|
||||||
|
import { NgxTocStateService } from '../../../@theme/services/toc-state.service';
|
||||||
|
import {MetadataService} from '../../../../../src/app/@core/utils/metadata.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-admin-landing-page',
|
||||||
|
templateUrl: './ngx-admin-landing-page.component.html',
|
||||||
|
styleUrls: ['./ngx-admin-landing-page.component.scss'],
|
||||||
|
})
|
||||||
|
export class NgxAdminLandingPageComponent implements OnDestroy, OnInit {
|
||||||
|
|
||||||
|
currentItem;
|
||||||
|
private alive = true;
|
||||||
|
|
||||||
|
constructor(@Inject(NB_WINDOW) private window,
|
||||||
|
private ngZone: NgZone,
|
||||||
|
private router: Router,
|
||||||
|
private activatedRoute: ActivatedRoute,
|
||||||
|
private structureService: NgxStructureService,
|
||||||
|
private tocState: NgxTocStateService,
|
||||||
|
private metaDataService: MetadataService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
get showSettings() {
|
||||||
|
return this.currentItem && this.currentItem.children
|
||||||
|
.some((item) => ['markdown', 'component', 'tabbed'].includes(item.block));
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.handlePageNavigation();
|
||||||
|
this.handleTocScroll();
|
||||||
|
this.window.history.scrollRestoration = 'manual';
|
||||||
|
}
|
||||||
|
|
||||||
|
handlePageNavigation() {
|
||||||
|
this.activatedRoute.params
|
||||||
|
.pipe(
|
||||||
|
takeWhile(() => this.alive),
|
||||||
|
filter((params: any) => params.subPage),
|
||||||
|
map((params: any) => {
|
||||||
|
const slag = `${params.page}_${params.subPage}`;
|
||||||
|
return this.structureService.findPageBySlag(this.structureService.getPreparedStructure(), slag);
|
||||||
|
}),
|
||||||
|
filter(item => item),
|
||||||
|
tap((item: any) => {
|
||||||
|
this.metaDataService.updateTitle(item.title);
|
||||||
|
this.metaDataService.updateDescription(item.description);
|
||||||
|
this.metaDataService.updateKeywords(item.keywords);
|
||||||
|
}),
|
||||||
|
publishReplay(),
|
||||||
|
refCount(),
|
||||||
|
)
|
||||||
|
.subscribe((item) => {
|
||||||
|
this.currentItem = item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTocScroll() {
|
||||||
|
this.ngZone.runOutsideAngular(() => {
|
||||||
|
fromEvent(this.window, 'scroll')
|
||||||
|
.pipe(
|
||||||
|
publishBehavior(null),
|
||||||
|
refCount(),
|
||||||
|
takeWhile(() => this.alive),
|
||||||
|
filter(() => this.tocState.list().length > 0),
|
||||||
|
)
|
||||||
|
.subscribe(() => {
|
||||||
|
this.tocState.list().map(item => item.setInView(false));
|
||||||
|
|
||||||
|
const current: any = this.tocState.list().reduce((acc, item) => {
|
||||||
|
return item.y > 0 && item.y < acc.y ? item : acc;
|
||||||
|
}, { y: Number.POSITIVE_INFINITY, fake: true });
|
||||||
|
|
||||||
|
if (current && !current.fake) {
|
||||||
|
current.setInView(true);
|
||||||
|
this.router.navigate([], { fragment: current.fragment, replaceUrl: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.alive = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
<ngx-landing-section-title>
|
||||||
|
ngx-admin Dashboard with Backends
|
||||||
|
</ngx-landing-section-title>
|
||||||
|
|
||||||
|
<div class="section-container">
|
||||||
|
|
||||||
|
<p class="features__description">
|
||||||
|
Looking for a way to integrate Angular ngx-admin with .NET, Node.js, Ruby or PHP? We are here to save your time on painful setup, configuration and routing tasks.
|
||||||
|
Choose starter kit bundle based on a technology of your choice below.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="package-switcher">
|
||||||
|
<div class="package-switcher__btn-group btn-group btn-group-toggle btn-outline-toggle-group btn-group-full-width btn-toggle-radio-group">
|
||||||
|
<label *ngFor="let license of licenses"
|
||||||
|
class="package-switcher__btn btn btn-outline-secondary"
|
||||||
|
[class.active]="selectedLicenseType === license">
|
||||||
|
<input type="radio" [value]="license" name="licence-type" [(ngModel)]="selectedLicenseType"> {{ license | ngxCapitalize }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="packages">
|
||||||
|
<li class="packages__item" *ngFor="let product of products | async">
|
||||||
|
<nb-card class="package-card">
|
||||||
|
<nb-card-body>
|
||||||
|
<div class="package-card__image" [ngStyle]="product.imageUrl | backgroundImage"></div>
|
||||||
|
<h4 class="package-card__title">{{ product.title }}</h4>
|
||||||
|
<p class="package-card__description">
|
||||||
|
{{ product.description | slice:0:200 }}...
|
||||||
|
<a class="go-to-button"
|
||||||
|
href="{{ product.storeUrl }}?utm_source=ngx_admin&utm_medium=referral&utm_campaign=akveo_store%20-%20specific%20bundle%20-%20ngx_admin%20landing&utm_content=buy_bundle_{{ selectedLicenseType }}"
|
||||||
|
target="_blank">
|
||||||
|
read more
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<div class="package-card__price-wrapper">
|
||||||
|
<span class="package-card__price package-card__price--old" *ngIf="shouldShowOldPrice(product.variants, selectedLicenseType)">
|
||||||
|
${{ (product.variants | license:selectedLicenseType).compare_at_price }}
|
||||||
|
</span>
|
||||||
|
<span class="package-card__price">From ${{ (product.variants | license:selectedLicenseType).price }}</span>
|
||||||
|
</div>
|
||||||
|
<a href="{{ product.storeUrl }}?utm_source=ngx_admin&utm_medium=referral&utm_campaign=akveo_store%20-%20specific%20bundle%20-%20ngx_admin%20landing&utm_content=buy_bundle_{{ selectedLicenseType }}"
|
||||||
|
class="package-card__buy-link btn">
|
||||||
|
Buy now
|
||||||
|
</a>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="request-code-section">
|
||||||
|
<a href="https://github.com/akveo/ngx-admin-bundle-support/tree/master/codeSamples" target="_blank" class="package-card__buy-link btn">
|
||||||
|
CODE SAMPLE
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="https://store.akveo.com/collections/all?utm_campaign=akveo_store%20-%20all%20bundles%20-%20ngx_admin%20landing&utm_source=ngx_admin&utm_medium=referral&utm_content=browse_other_bundles" target="_blank" class="package-card__buy-link btn">
|
||||||
|
BROWSE OTHER BUNDLES
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="fleet-management-template-banner">
|
||||||
|
<a href="https://www.akveo.com/templates/fleet-management-dashboard?utm_campaign=services%20-%20templates%20-%20ngx-admin%20&utm_source=ngx-admin&utm_medium=referral&utm_content=landing_banner" target="_blank" aria-label="Template for Fleet Management Software">
|
||||||
|
<picture>
|
||||||
|
<source srcset="assets/img/fleet-management-banner.webp" type="image/webp">
|
||||||
|
<img src="assets/img/fleet-management-banner.jpg"
|
||||||
|
class="fleet-management-template-banner-image"
|
||||||
|
alt="Template for Fleet Management Software">
|
||||||
|
</picture>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="features-table">
|
||||||
|
<tr class="header">
|
||||||
|
<th class="left">FEATURES</th>
|
||||||
|
<th>PERSONAL APP</th>
|
||||||
|
<th>DEVELOPER APP</th>
|
||||||
|
</tr>
|
||||||
|
<tr *ngFor="let feature of features | async">
|
||||||
|
<td class="left">{{ feature.text }}</td>
|
||||||
|
<td>
|
||||||
|
<ng-container *ngTemplateOutlet="availabilityIcon; context: { $implicit: feature.availableInPersonalLicence }">
|
||||||
|
</ng-container>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ng-container *ngTemplateOutlet="availabilityIcon; context: { $implicit: feature.availableInCommercialLicence }">
|
||||||
|
</ng-container>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<ng-template #availabilityIcon let-isAvailable>
|
||||||
|
<i *ngIf="isAvailable; else unavailableIcon"
|
||||||
|
aria-label="available"
|
||||||
|
[innerHTML]="'checkmark-outline' | eva: { width: 24, height: 24, fill: '#00db92' }">
|
||||||
|
</i>
|
||||||
|
|
||||||
|
<ng-template #unavailableIcon>
|
||||||
|
<i aria-label="unavailable" [innerHTML]="'close-outline' | eva: { width: 24, height: 24, fill: '#ff8588' }"></i>
|
||||||
|
</ng-template>
|
||||||
|
</ng-template>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<ngx-landing-description-section *ngIf="descriptions | async" [descriptions]="descriptions | async"></ngx-landing-description-section>
|
||||||
|
|
||||||
|
<div class="bundles-architecture">
|
||||||
|
<ngx-landing-section-title>
|
||||||
|
Architecture Design
|
||||||
|
</ngx-landing-section-title>
|
||||||
|
|
||||||
|
<p class="features__description">The schema describes high-level solution architecture.</p>
|
||||||
|
|
||||||
|
<picture class="bundle-scheme">
|
||||||
|
<source type="image/webp" srcset="assets/img/bundle-scheme@1x.webp 1x, assets/img/bundle-scheme@2x.webp 2x">
|
||||||
|
<img class="bundle-scheme__image" src="assets/img/bundle-scheme@1x.png" srcset="assets/img/bundle-scheme@2x.png 2x" alt="Backend bundles">
|
||||||
|
</picture>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="features__description">Need more details or have a question?</p>
|
||||||
|
|
||||||
|
<div class="request-code-section">
|
||||||
|
<a href="mailto:support@akveo.com?subject=Custom bundle request" class="package-card__buy-link btn">
|
||||||
|
CONTACT US
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
|
@ -0,0 +1,403 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Akveo. All Rights Reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
@import '~@nebular/theme/styles/global/breakpoints';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
$content-width: nb-theme(content-width);
|
||||||
|
$left-right-offset: 8.125rem;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
padding-top: 5.125rem;
|
||||||
|
|
||||||
|
.section-container {
|
||||||
|
width: calc(#{$content-width} - #{$left-right-offset} * 2);
|
||||||
|
max-width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 0 11px;
|
||||||
|
margin-top: 5rem;
|
||||||
|
margin-left: -11px;
|
||||||
|
margin-right: -11px;
|
||||||
|
width: 100%;
|
||||||
|
width: calc(100% + 22px);
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
flex: 0 0 25%;
|
||||||
|
width: 25%;
|
||||||
|
max-width: 25%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 11px;
|
||||||
|
padding-right: 11px;
|
||||||
|
margin-bottom: 1.625rem;
|
||||||
|
}
|
||||||
|
&__title {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 60px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 30px;
|
||||||
|
text-align: center;
|
||||||
|
color: rgba(0, 0, 0, 0.87);
|
||||||
|
}
|
||||||
|
&__description {
|
||||||
|
font-family: nb-theme(font-secondary), sans-serif;
|
||||||
|
color: #8994a3;
|
||||||
|
font-size: nb-theme(font-size-lg);
|
||||||
|
line-height: 1.75;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bundles-architecture {
|
||||||
|
display: none;
|
||||||
|
margin-bottom: 5rem;
|
||||||
|
|
||||||
|
.bundle-scheme {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
margin: 2.5rem auto;
|
||||||
|
|
||||||
|
&__image {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-switcher {
|
||||||
|
margin: 2.375rem 0 5rem;
|
||||||
|
|
||||||
|
&__btn-group {
|
||||||
|
box-shadow: 0 8px 20px 0 rgba(218, 224, 235, 0.5);
|
||||||
|
border-radius: 1.5rem;
|
||||||
|
&:not(.btn-divided-group) > .package-switcher__btn:not(.dropdown-toggle):first-child {
|
||||||
|
border-top-left-radius: 1.5rem;
|
||||||
|
border-bottom-left-radius: 1.5rem;
|
||||||
|
}
|
||||||
|
&:not(.btn-divided-group) > .package-switcher__btn:not(.dropdown-toggle):last-child {
|
||||||
|
border-top-right-radius: 1.5rem;
|
||||||
|
border-bottom-right-radius: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__btn {
|
||||||
|
min-width: 10.625rem;
|
||||||
|
color: #bdc3cb;
|
||||||
|
border-color: #e6e8eb;
|
||||||
|
text-transform: none;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: #000000;
|
||||||
|
background-color: #fafafa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.packages {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 0;
|
||||||
|
margin-left: -11px;
|
||||||
|
margin-right: -11px;
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
width: 100%;
|
||||||
|
width: calc(100% + 22px);
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
flex: 0 0 25%;
|
||||||
|
width: 25%;
|
||||||
|
max-width: 25%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 11px;
|
||||||
|
padding-right: 11px;
|
||||||
|
margin-bottom: 22px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fleet-management-template-banner {
|
||||||
|
margin: -2.5rem 0 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fleet-management-template-banner-image {
|
||||||
|
height: auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb-flip-card {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep .flipcard-body {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep .front-container, .back-container {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb-card-front, nb-card-back {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb-card {
|
||||||
|
height: 100%;
|
||||||
|
border: 0;
|
||||||
|
background-color: #ffffff;
|
||||||
|
box-shadow: 0 7px 17px 0 rgba(218, 224, 235, 0.5);
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb-card-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-content: stretch;
|
||||||
|
align-items: stretch;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-card {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-content: stretch;
|
||||||
|
align-items: stretch;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&__header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin-bottom: 0.5625rem;
|
||||||
|
}
|
||||||
|
&__demo-link {
|
||||||
|
align-self: flex-end;
|
||||||
|
color: #ff8588;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
line-height: 1rem;
|
||||||
|
text-align: center;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 0.25rem 1rem;
|
||||||
|
border: 1px solid #ff8588;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
&--secondary {
|
||||||
|
color: #ad7efa;
|
||||||
|
border-color: #ad7efa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__image {
|
||||||
|
margin: 1rem -1rem;
|
||||||
|
display: flex;
|
||||||
|
flex: 0 0 14.125rem;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center center;
|
||||||
|
background-size: auto 100%;
|
||||||
|
}
|
||||||
|
&__price-wrapper {
|
||||||
|
flex: 0 0 2.5rem;
|
||||||
|
margin-top: auto;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
&__price {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.75rem;
|
||||||
|
line-height: 2.5rem;
|
||||||
|
color: rgba(0, 0, 0, 0.87);
|
||||||
|
vertical-align: middle;
|
||||||
|
&--old {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: #ff4d6b;
|
||||||
|
text-decoration: line-through;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.125rem;
|
||||||
|
color: rgba(0, 0, 0, 0.87);
|
||||||
|
line-height: 1.5rem;
|
||||||
|
}
|
||||||
|
&__description {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
font-family: nb-theme(font-secondary), sans-serif;
|
||||||
|
font-weight: lighter;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: rgba(0, 0, 0, 0.87);
|
||||||
|
margin-bottom: 1.675rem;
|
||||||
|
}
|
||||||
|
&__buy-link {
|
||||||
|
font-family: nb-theme(font-secondary), sans-serif;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: #ffffff;
|
||||||
|
text-transform: uppercase;
|
||||||
|
background-color: nb-theme(color-active-fg);
|
||||||
|
box-shadow: nb-theme(shadow-btn);
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: nb-theme(shadow-hover-green-btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
box-shadow: nb-theme(shadow-active-green-btn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__type {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
color: rgba(0, 0, 0, 0.87);
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.go-to-button {
|
||||||
|
font-family: nb-theme(font-main), sans-serif;
|
||||||
|
color: nb-theme(color-active-fg);
|
||||||
|
padding: 0.25rem;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request-code-section {
|
||||||
|
margin-bottom: 5rem;
|
||||||
|
|
||||||
|
a:not(:first-child) {
|
||||||
|
margin-left: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-down(xl) {
|
||||||
|
.section-container {
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bundle-scheme {
|
||||||
|
padding: 0 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features {
|
||||||
|
padding-left: 11px;
|
||||||
|
padding-right: 11px;
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
flex-basis: 50%;
|
||||||
|
width: 50%;
|
||||||
|
max-width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.packages {
|
||||||
|
padding-left: 11px;
|
||||||
|
padding-right: 11px;
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
flex-basis: 50%;
|
||||||
|
width: 50%;
|
||||||
|
max-width: 50%;
|
||||||
|
margin-bottom: 1.625rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.features-table {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 5rem;
|
||||||
|
|
||||||
|
box-shadow: 0 8px 20px 0 rgba(218, 224, 235, 0.5);
|
||||||
|
background-color: #fafafa;
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
padding: 0.5rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
td ul {
|
||||||
|
display: inline-block;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left {
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-down(sm) {
|
||||||
|
|
||||||
|
.packages__item {
|
||||||
|
flex-basis: 100%;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features-table {
|
||||||
|
.header {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-down(is) {
|
||||||
|
|
||||||
|
.features__item {
|
||||||
|
flex-basis: 100%;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
.package-switcher__btn {
|
||||||
|
min-width: 8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue