feat: demo version additions

This commit is contained in:
Sergey Andrievskiy 2021-08-06 18:48:35 +03:00
parent 0eec54695f
commit eee950248e
322 changed files with 23456 additions and 188 deletions

View file

@ -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>

View file

@ -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;
}
}
}

View 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 { AfterViewInit, Component, ElementRef, EventEmitter, Inject, Input, Output } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { delay, filter, take } from 'rxjs/operators';
import { NB_WINDOW } from '@nebular/theme';
import {
BUNDLE_LICENSE,
STORE_PRODUCTS_URL,
BundlesService,
Feature,
Product,
ProductVariant,
} from '../../../@core/data/service/bundles.service';
import { Descriptions, DescriptionsService } from '../../../@core/data/service/descriptions.service';
import { LicensePipe } from '../backend-bundles-section/license.pipe';
@Component({
selector: 'ngx-backend-bundles-section',
templateUrl: 'backend-bundles-section.component.html',
styleUrls: ['./backend-bundles-section.component.scss'],
})
export class BackendBundlesSectionComponent implements AfterViewInit {
@Output() loaded = new EventEmitter();
@Input()
set material(value: boolean | undefined) {
if (value) {
this.productUrl = STORE_PRODUCTS_URL.material;
this.getProducts();
}
}
selectedLicenseType = BUNDLE_LICENSE.personal;
productUrl = STORE_PRODUCTS_URL.base;
licenses = Object.values(BUNDLE_LICENSE);
descriptions: Observable<Descriptions[]> = this.descriptionService.getBundleDescriptions();
products: Observable<Product[]>;
features: Observable<Feature[]> = this.bundlesService.getFeatures();
constructor(private descriptionService: DescriptionsService,
private bundlesService: BundlesService,
private activatedRoute: ActivatedRoute,
private el: ElementRef<HTMLElement>,
@Inject(NB_WINDOW) private window,
private licensePipe: LicensePipe) {
this.getProducts();
}
ngAfterViewInit() {
this.activatedRoute.fragment
.pipe(
filter(fragment => fragment === 'backend-bundles'),
delay(500),
take(1),
)
.subscribe((fragment: string) => {
this.window.scrollTo(0, this.el.nativeElement.offsetTop);
});
}
getProducts() {
this.products = this.bundlesService.getProducts(this.productUrl);
}
shouldShowOldPrice(variants: ProductVariant[], selectedLicenseType: string): boolean {
const product = this.licensePipe.transform(variants, selectedLicenseType);
return !!parseFloat(product.compare_at_price);
}
}

View file

@ -0,0 +1,10 @@
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'backgroundImage' })
export class BackgroundImagePipe implements PipeTransform {
transform(url: string): any {
return {
'background-image': `url(\'${url}\')`,
};
}
}

View file

@ -0,0 +1,11 @@
import { Pipe, PipeTransform } from '@angular/core';
import { ProductVariant } from '../../../@core/data/service/bundles.service';
@Pipe({ name: 'license' })
export class LicensePipe implements PipeTransform {
transform(variants: ProductVariant[], license: string): ProductVariant {
const result = variants
.find(variant => variant.title.toLowerCase().includes(license.toLowerCase()));
return result ? result : variants[0];
}
}