mirror of
https://github.com/akveo/ngx-admin.git
synced 2025-12-16 15:40:11 +01:00
saving with admin and public base
This commit is contained in:
parent
06776d15c4
commit
dd1b2763d8
425 changed files with 21493 additions and 11663 deletions
29554
package-lock.json
generated
29554
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -40,6 +40,7 @@
|
||||||
"@angular/platform-browser": "^15.2.10",
|
"@angular/platform-browser": "^15.2.10",
|
||||||
"@angular/platform-browser-dynamic": "^15.2.10",
|
"@angular/platform-browser-dynamic": "^15.2.10",
|
||||||
"@angular/router": "^15.2.10",
|
"@angular/router": "^15.2.10",
|
||||||
|
"@apollo/client": "^3.11.4",
|
||||||
"@asymmetrik/ngx-leaflet": "3.0.1",
|
"@asymmetrik/ngx-leaflet": "3.0.1",
|
||||||
"@nebular/auth": "11.0.1",
|
"@nebular/auth": "11.0.1",
|
||||||
"@nebular/eva-icons": "11.0.1",
|
"@nebular/eva-icons": "11.0.1",
|
||||||
|
|
@ -47,6 +48,7 @@
|
||||||
"@nebular/theme": "11.0.1",
|
"@nebular/theme": "11.0.1",
|
||||||
"@swimlane/ngx-charts": "^14.0.0",
|
"@swimlane/ngx-charts": "^14.0.0",
|
||||||
"angular2-chartjs": "0.4.1",
|
"angular2-chartjs": "0.4.1",
|
||||||
|
"apollo-angular": "^7.0.2",
|
||||||
"bootstrap": "4.3.1",
|
"bootstrap": "4.3.1",
|
||||||
"chart.js": "2.7.1",
|
"chart.js": "2.7.1",
|
||||||
"ckeditor": "4.7.3",
|
"ckeditor": "4.7.3",
|
||||||
|
|
@ -54,6 +56,7 @@
|
||||||
"core-js": "2.5.1",
|
"core-js": "2.5.1",
|
||||||
"echarts": "^4.9.0",
|
"echarts": "^4.9.0",
|
||||||
"eva-icons": "^1.1.3",
|
"eva-icons": "^1.1.3",
|
||||||
|
"graphql": "^16.9.0",
|
||||||
"intl": "1.2.5",
|
"intl": "1.2.5",
|
||||||
"ionicons": "2.0.1",
|
"ionicons": "2.0.1",
|
||||||
"leaflet": "1.2.0",
|
"leaflet": "1.2.0",
|
||||||
|
|
@ -62,7 +65,6 @@
|
||||||
"ng2-completer": "^9.0.1",
|
"ng2-completer": "^9.0.1",
|
||||||
"ng2-smart-table": "^1.6.0",
|
"ng2-smart-table": "^1.6.0",
|
||||||
"ngx-echarts": "^4.2.2",
|
"ngx-echarts": "^4.2.2",
|
||||||
"node-sass": "^4.14.1",
|
|
||||||
"normalize.css": "6.0.0",
|
"normalize.css": "6.0.0",
|
||||||
"pace-js": "1.0.2",
|
"pace-js": "1.0.2",
|
||||||
"roboto-fontface": "0.8.0",
|
"roboto-fontface": "0.8.0",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
<nb-card>
|
||||||
|
<nb-card-header>Do you confirm your action?</nb-card-header>
|
||||||
|
<nb-card-footer>
|
||||||
|
<button class="cancel" nbButton status="danger" (click)="cancel()">Cancel</button>
|
||||||
|
<button nbButton status="success" (click)="submit()">Submit</button>
|
||||||
|
</nb-card-footer>
|
||||||
|
</nb-card>
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { NbDialogRef } from '@nebular/theme';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-dialog-prompt',
|
||||||
|
templateUrl: 'dialog-prompt.component.html',
|
||||||
|
styleUrls: ['dialog-prompt.component.scss'],
|
||||||
|
})
|
||||||
|
export class DialogPromptComponent {
|
||||||
|
|
||||||
|
constructor(protected ref: NbDialogRef<DialogPromptComponent>) {}
|
||||||
|
|
||||||
|
cancel() {
|
||||||
|
this.ref.close(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
submit() {
|
||||||
|
this.ref.close(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,28 +1,45 @@
|
||||||
<div class="header-container">
|
<div class="header-container">
|
||||||
<div class="logo-container">
|
<div class="logo-container">
|
||||||
<a (click)="toggleSidebar()" href="#" class="sidebar-toggle">
|
<a *ngIf="menu" (click)="toggleSidebar()" href="#" class="sidebar-toggle">
|
||||||
<nb-icon icon="menu-2-outline"></nb-icon>
|
<nb-icon icon="menu-2-outline"></nb-icon>
|
||||||
</a>
|
</a>
|
||||||
<a class="logo" href="#" (click)="navigateHome()">ngx-<span>admin</span></a>
|
<a class="logo" href="#" (click)="navigateHome()"
|
||||||
|
><span>Desapegrow</span></a
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<nb-select [selected]="currentTheme" (selectedChange)="changeTheme($event)" status="primary">
|
<nb-select
|
||||||
<nb-option *ngFor="let theme of themes" [value]="theme.value"> {{ theme.name }}</nb-option>
|
[selected]="currentTheme"
|
||||||
|
(selectedChange)="changeTheme($event)"
|
||||||
|
status="primary"
|
||||||
|
>
|
||||||
|
<nb-option *ngFor="let theme of themes" [value]="theme.value">
|
||||||
|
{{ theme.name }}</nb-option
|
||||||
|
>
|
||||||
</nb-select>
|
</nb-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="header-container">
|
<div class="header-container">
|
||||||
<nb-actions size="small">
|
<nb-actions size="small">
|
||||||
|
|
||||||
<nb-action class="control-item">
|
<nb-action class="control-item">
|
||||||
<nb-search type="rotate-layout"></nb-search>
|
<nb-search type="rotate-layout"></nb-search>
|
||||||
</nb-action>
|
</nb-action>
|
||||||
<nb-action class="control-item" icon="email-outline"></nb-action>
|
<nb-action class="control-item" icon="email-outline"></nb-action>
|
||||||
<nb-action class="control-item" icon="bell-outline"></nb-action>
|
<nb-action class="control-item" icon="bell-outline"></nb-action>
|
||||||
<nb-action class="user-action" *nbIsGranted="['view', 'user']" >
|
<nb-action
|
||||||
<nb-user [nbContextMenu]="userMenu"
|
class="control-item"
|
||||||
[onlyPicture]="userPictureOnly"
|
icon="message-circle-outline"
|
||||||
[name]="user?.name"
|
badgeDot
|
||||||
[picture]="user?.picture">
|
badgeStatus="danger"
|
||||||
|
badgePosition="top right"
|
||||||
|
(click)="goToChat()"
|
||||||
|
></nb-action>
|
||||||
|
<nb-action class="user-action" *nbIsGranted="['view', 'user']">
|
||||||
|
<nb-user
|
||||||
|
[nbContextMenu]="userMenu"
|
||||||
|
[onlyPicture]="userPictureOnly"
|
||||||
|
[name]="user?.name"
|
||||||
|
[picture]="user?.picture"
|
||||||
|
>
|
||||||
</nb-user>
|
</nb-user>
|
||||||
</nb-action>
|
</nb-action>
|
||||||
</nb-actions>
|
</nb-actions>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { NbMediaBreakpointsService, NbMenuService, NbSidebarService, NbThemeService } from '@nebular/theme';
|
import { NbMediaBreakpointsService, NbMenuService, NbSidebarService, NbThemeService } from '@nebular/theme';
|
||||||
|
|
||||||
import { UserData } from '../../../@core/data/users';
|
import { UserData } from '../../../@core/data/users';
|
||||||
import { LayoutService } from '../../../@core/utils';
|
import { LayoutService } from '../../../@core/utils';
|
||||||
import { map, takeUntil } from 'rxjs/operators';
|
import { map, takeUntil } from 'rxjs/operators';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ngx-header',
|
selector: 'ngx-header',
|
||||||
|
|
@ -12,7 +13,7 @@ import { Subject } from 'rxjs';
|
||||||
templateUrl: './header.component.html',
|
templateUrl: './header.component.html',
|
||||||
})
|
})
|
||||||
export class HeaderComponent implements OnInit, OnDestroy {
|
export class HeaderComponent implements OnInit, OnDestroy {
|
||||||
|
@Input() menu: boolean = true;
|
||||||
private destroy$: Subject<void> = new Subject<void>();
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
userPictureOnly: boolean = false;
|
userPictureOnly: boolean = false;
|
||||||
user: any;
|
user: any;
|
||||||
|
|
@ -45,7 +46,8 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
||||||
private themeService: NbThemeService,
|
private themeService: NbThemeService,
|
||||||
private userService: UserData,
|
private userService: UserData,
|
||||||
private layoutService: LayoutService,
|
private layoutService: LayoutService,
|
||||||
private breakpointService: NbMediaBreakpointsService) {
|
private breakpointService: NbMediaBreakpointsService,
|
||||||
|
private router: Router) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
|
@ -91,4 +93,11 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
||||||
this.menuService.navigateHome();
|
this.menuService.navigateHome();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goToChat() {
|
||||||
|
this.router.navigate([
|
||||||
|
"admin",
|
||||||
|
"chat"
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component, Input } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ngx-one-column-layout',
|
selector: 'ngx-one-column-layout',
|
||||||
|
|
@ -6,10 +6,10 @@ import { Component } from '@angular/core';
|
||||||
template: `
|
template: `
|
||||||
<nb-layout windowMode>
|
<nb-layout windowMode>
|
||||||
<nb-layout-header fixed>
|
<nb-layout-header fixed>
|
||||||
<ngx-header></ngx-header>
|
<ngx-header [menu]="menu"></ngx-header>
|
||||||
</nb-layout-header>
|
</nb-layout-header>
|
||||||
|
|
||||||
<nb-sidebar class="menu-sidebar" tag="menu-sidebar" responsive>
|
<nb-sidebar *ngIf="menu" class="menu-sidebar" tag="menu-sidebar" responsive>
|
||||||
<ng-content select="nb-menu"></ng-content>
|
<ng-content select="nb-menu"></ng-content>
|
||||||
</nb-sidebar>
|
</nb-sidebar>
|
||||||
|
|
||||||
|
|
@ -23,4 +23,6 @@ import { Component } from '@angular/core';
|
||||||
</nb-layout>
|
</nb-layout>
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
export class OneColumnLayoutComponent {}
|
export class OneColumnLayoutComponent {
|
||||||
|
@Input() menu: boolean = true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import {
|
||||||
NbSelectModule,
|
NbSelectModule,
|
||||||
NbIconModule,
|
NbIconModule,
|
||||||
NbThemeModule,
|
NbThemeModule,
|
||||||
|
NbCardModule,
|
||||||
} from '@nebular/theme';
|
} from '@nebular/theme';
|
||||||
import { NbEvaIconsModule } from '@nebular/eva-icons';
|
import { NbEvaIconsModule } from '@nebular/eva-icons';
|
||||||
import { NbSecurityModule } from '@nebular/security';
|
import { NbSecurityModule } from '@nebular/security';
|
||||||
|
|
@ -38,6 +39,7 @@ import { DEFAULT_THEME } from './styles/theme.default';
|
||||||
import { COSMIC_THEME } from './styles/theme.cosmic';
|
import { COSMIC_THEME } from './styles/theme.cosmic';
|
||||||
import { CORPORATE_THEME } from './styles/theme.corporate';
|
import { CORPORATE_THEME } from './styles/theme.corporate';
|
||||||
import { DARK_THEME } from './styles/theme.dark';
|
import { DARK_THEME } from './styles/theme.dark';
|
||||||
|
import { DialogPromptComponent } from './components/dialogs/dialog-name-prompt/dialog-prompt.component';
|
||||||
|
|
||||||
const NB_MODULES = [
|
const NB_MODULES = [
|
||||||
NbLayoutModule,
|
NbLayoutModule,
|
||||||
|
|
@ -52,6 +54,7 @@ const NB_MODULES = [
|
||||||
NbSelectModule,
|
NbSelectModule,
|
||||||
NbIconModule,
|
NbIconModule,
|
||||||
NbEvaIconsModule,
|
NbEvaIconsModule,
|
||||||
|
NbCardModule,
|
||||||
];
|
];
|
||||||
const COMPONENTS = [
|
const COMPONENTS = [
|
||||||
HeaderComponent,
|
HeaderComponent,
|
||||||
|
|
@ -61,6 +64,7 @@ const COMPONENTS = [
|
||||||
OneColumnLayoutComponent,
|
OneColumnLayoutComponent,
|
||||||
ThreeColumnsLayoutComponent,
|
ThreeColumnsLayoutComponent,
|
||||||
TwoColumnsLayoutComponent,
|
TwoColumnsLayoutComponent,
|
||||||
|
DialogPromptComponent
|
||||||
];
|
];
|
||||||
const PIPES = [
|
const PIPES = [
|
||||||
CapitalizePipe,
|
CapitalizePipe,
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,13 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
||||||
{
|
{
|
||||||
title: 'E-commerce',
|
title: 'E-commerce',
|
||||||
icon: 'shopping-cart-outline',
|
icon: 'shopping-cart-outline',
|
||||||
link: '/pages/dashboard',
|
link: '/admin/dashboard',
|
||||||
home: true,
|
home: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'IoT Dashboard',
|
title: 'IoT Dashboard',
|
||||||
icon: 'home-outline',
|
icon: 'home-outline',
|
||||||
link: '/pages/iot-dashboard',
|
link: '/admin/iot-dashboard',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'FEATURES',
|
title: 'FEATURES',
|
||||||
|
|
@ -22,24 +22,24 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: 'Stepper',
|
title: 'Stepper',
|
||||||
link: '/pages/layout/stepper',
|
link: '/admin/layout/stepper',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'List',
|
title: 'List',
|
||||||
link: '/pages/layout/list',
|
link: '/admin/layout/list',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Infinite List',
|
title: 'Infinite List',
|
||||||
link: '/pages/layout/infinite-list',
|
link: '/admin/layout/infinite-list',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Accordion',
|
title: 'Accordion',
|
||||||
link: '/pages/layout/accordion',
|
link: '/admin/layout/accordion',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Tabs',
|
title: 'Tabs',
|
||||||
pathMatch: 'prefix',
|
pathMatch: 'prefix',
|
||||||
link: '/pages/layout/tabs',
|
link: '/admin/layout/tabs',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -49,42 +49,98 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: 'Form Inputs',
|
title: 'Form Inputs',
|
||||||
link: '/pages/forms/inputs',
|
link: '/admin/forms/inputs',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Form Layouts',
|
title: 'Form Layouts',
|
||||||
link: '/pages/forms/layouts',
|
link: '/admin/forms/layouts',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Buttons',
|
title: 'Buttons',
|
||||||
link: '/pages/forms/buttons',
|
link: '/admin/forms/buttons',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Datepicker',
|
title: 'Datepicker',
|
||||||
link: '/pages/forms/datepicker',
|
link: '/admin/forms/datepicker',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Banner',
|
||||||
|
icon: 'edit-2-outline',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: 'Edit',
|
||||||
|
link: '/admin/banner/edit',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Create',
|
||||||
|
link: '/admin/banner/create',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Brand',
|
||||||
|
icon: 'edit-2-outline',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: 'Edit',
|
||||||
|
link: '/admin/brand/edit',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Create',
|
||||||
|
link: '/admin/brand/create',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Category',
|
||||||
|
icon: 'edit-2-outline',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: 'Edit',
|
||||||
|
link: '/admin/category/edit',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Create',
|
||||||
|
link: '/admin/category/create',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Sub Category',
|
||||||
|
icon: 'edit-2-outline',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: 'Edit',
|
||||||
|
link: '/admin/sub-category/edit',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Create',
|
||||||
|
link: '/admin/sub-category/create',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'UI Features',
|
title: 'UI Features',
|
||||||
icon: 'keypad-outline',
|
icon: 'keypad-outline',
|
||||||
link: '/pages/ui-features',
|
link: '/admin/ui-features',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: 'Grid',
|
title: 'Grid',
|
||||||
link: '/pages/ui-features/grid',
|
link: '/admin/ui-features/grid',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Icons',
|
title: 'Icons',
|
||||||
link: '/pages/ui-features/icons',
|
link: '/admin/ui-features/icons',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Typography',
|
title: 'Typography',
|
||||||
link: '/pages/ui-features/typography',
|
link: '/admin/ui-features/typography',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Animated Searches',
|
title: 'Animated Searches',
|
||||||
link: '/pages/ui-features/search-fields',
|
link: '/admin/ui-features/search-fields',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -94,23 +150,23 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: 'Dialog',
|
title: 'Dialog',
|
||||||
link: '/pages/modal-overlays/dialog',
|
link: '/admin/modal-overlays/dialog',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Window',
|
title: 'Window',
|
||||||
link: '/pages/modal-overlays/window',
|
link: '/admin/modal-overlays/window',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Popover',
|
title: 'Popover',
|
||||||
link: '/pages/modal-overlays/popover',
|
link: '/admin/modal-overlays/popover',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Toastr',
|
title: 'Toastr',
|
||||||
link: '/pages/modal-overlays/toastr',
|
link: '/admin/modal-overlays/toastr',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Tooltip',
|
title: 'Tooltip',
|
||||||
link: '/pages/modal-overlays/tooltip',
|
link: '/admin/modal-overlays/tooltip',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -120,27 +176,27 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: 'Calendar',
|
title: 'Calendar',
|
||||||
link: '/pages/extra-components/calendar',
|
link: '/admin/extra-components/calendar',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Progress Bar',
|
title: 'Progress Bar',
|
||||||
link: '/pages/extra-components/progress-bar',
|
link: '/admin/extra-components/progress-bar',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Spinner',
|
title: 'Spinner',
|
||||||
link: '/pages/extra-components/spinner',
|
link: '/admin/extra-components/spinner',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Alert',
|
title: 'Alert',
|
||||||
link: '/pages/extra-components/alert',
|
link: '/admin/extra-components/alert',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Calendar Kit',
|
title: 'Calendar Kit',
|
||||||
link: '/pages/extra-components/calendar-kit',
|
link: '/admin/extra-components/calendar-kit',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Chat',
|
title: 'Chat',
|
||||||
link: '/pages/extra-components/chat',
|
link: '/admin/extra-components/chat',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -150,19 +206,19 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: 'Google Maps',
|
title: 'Google Maps',
|
||||||
link: '/pages/maps/gmaps',
|
link: '/admin/maps/gmaps',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Leaflet Maps',
|
title: 'Leaflet Maps',
|
||||||
link: '/pages/maps/leaflet',
|
link: '/admin/maps/leaflet',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Bubble Maps',
|
title: 'Bubble Maps',
|
||||||
link: '/pages/maps/bubble',
|
link: '/admin/maps/bubble',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Search Maps',
|
title: 'Search Maps',
|
||||||
link: '/pages/maps/searchmap',
|
link: '/admin/maps/searchmap',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -172,15 +228,15 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: 'Echarts',
|
title: 'Echarts',
|
||||||
link: '/pages/charts/echarts',
|
link: '/admin/charts/echarts',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Charts.js',
|
title: 'Charts.js',
|
||||||
link: '/pages/charts/chartjs',
|
link: '/admin/charts/chartjs',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'D3',
|
title: 'D3',
|
||||||
link: '/pages/charts/d3',
|
link: '/admin/charts/d3',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -190,11 +246,11 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: 'TinyMCE',
|
title: 'TinyMCE',
|
||||||
link: '/pages/editors/tinymce',
|
link: '/admin/editors/tinymce',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'CKEditor',
|
title: 'CKEditor',
|
||||||
link: '/pages/editors/ckeditor',
|
link: '/admin/editors/ckeditor',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -204,11 +260,11 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: 'Smart Table',
|
title: 'Smart Table',
|
||||||
link: '/pages/tables/smart-table',
|
link: '/admin/tables/smart-table',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Tree Grid',
|
title: 'Tree Grid',
|
||||||
link: '/pages/tables/tree-grid',
|
link: '/admin/tables/tree-grid',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -218,7 +274,7 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: '404',
|
title: '404',
|
||||||
link: '/pages/miscellaneous/404',
|
link: '/admin/miscellaneous/404',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
|
|
||||||
import { PagesComponent } from './pages.component';
|
import { AdminComponent } from './admin.component';
|
||||||
import { DashboardComponent } from './dashboard/dashboard.component';
|
import { DashboardComponent } from './dashboard/dashboard.component';
|
||||||
import { ECommerceComponent } from './e-commerce/e-commerce.component';
|
import { ECommerceComponent } from './e-commerce/e-commerce.component';
|
||||||
import { NotFoundComponent } from './miscellaneous/not-found/not-found.component';
|
import { NotFoundComponent } from './miscellaneous/not-found/not-found.component';
|
||||||
|
|
||||||
const routes: Routes = [{
|
const routes: Routes = [{
|
||||||
path: '',
|
path: '',
|
||||||
component: PagesComponent,
|
component: AdminComponent,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'dashboard',
|
path: 'dashboard',
|
||||||
|
|
@ -63,6 +63,31 @@ const routes: Routes = [{
|
||||||
loadChildren: () => import('./tables/tables.module')
|
loadChildren: () => import('./tables/tables.module')
|
||||||
.then(m => m.TablesModule),
|
.then(m => m.TablesModule),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'banner',
|
||||||
|
loadChildren: () => import('./banner/banner.module')
|
||||||
|
.then(m => m.BannerModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'brand',
|
||||||
|
loadChildren: () => import('./brand/brand.module')
|
||||||
|
.then(m => m.BrandModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'chat',
|
||||||
|
loadChildren: () => import('./chat/chat.module')
|
||||||
|
.then(m => m.ChatModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'category',
|
||||||
|
loadChildren: () => import('./category/category.module')
|
||||||
|
.then(m => m.CategoryModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'sub-category',
|
||||||
|
loadChildren: () => import('./sub-category/sub-category.module')
|
||||||
|
.then(m => m.SubCategoryModule),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'miscellaneous',
|
path: 'miscellaneous',
|
||||||
loadChildren: () => import('./miscellaneous/miscellaneous.module')
|
loadChildren: () => import('./miscellaneous/miscellaneous.module')
|
||||||
|
|
@ -84,5 +109,5 @@ const routes: Routes = [{
|
||||||
imports: [RouterModule.forChild(routes)],
|
imports: [RouterModule.forChild(routes)],
|
||||||
exports: [RouterModule],
|
exports: [RouterModule],
|
||||||
})
|
})
|
||||||
export class PagesRoutingModule {
|
export class AdminRoutingModule {
|
||||||
}
|
}
|
||||||
0
src/app/pages/pages.component.scss → src/app/admin/admin.component.scss
Executable file → Normal file
0
src/app/pages/pages.component.scss → src/app/admin/admin.component.scss
Executable file → Normal file
|
|
@ -1,10 +1,10 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
import { MENU_ITEMS } from './pages-menu';
|
import { MENU_ITEMS } from './admin-menu';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ngx-pages',
|
selector: 'ngx-admin',
|
||||||
styleUrls: ['pages.component.scss'],
|
styleUrls: ['admin.component.scss'],
|
||||||
template: `
|
template: `
|
||||||
<ngx-one-column-layout>
|
<ngx-one-column-layout>
|
||||||
<nb-menu [items]="menu"></nb-menu>
|
<nb-menu [items]="menu"></nb-menu>
|
||||||
|
|
@ -12,7 +12,7 @@ import { MENU_ITEMS } from './pages-menu';
|
||||||
</ngx-one-column-layout>
|
</ngx-one-column-layout>
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
export class PagesComponent {
|
export class AdminComponent {
|
||||||
|
|
||||||
menu = MENU_ITEMS;
|
menu = MENU_ITEMS;
|
||||||
}
|
}
|
||||||
|
|
@ -2,24 +2,30 @@ import { NgModule } from '@angular/core';
|
||||||
import { NbMenuModule } from '@nebular/theme';
|
import { NbMenuModule } from '@nebular/theme';
|
||||||
|
|
||||||
import { ThemeModule } from '../@theme/theme.module';
|
import { ThemeModule } from '../@theme/theme.module';
|
||||||
import { PagesComponent } from './pages.component';
|
import { AdminComponent } from './admin.component';
|
||||||
import { DashboardModule } from './dashboard/dashboard.module';
|
import { DashboardModule } from './dashboard/dashboard.module';
|
||||||
import { ECommerceModule } from './e-commerce/e-commerce.module';
|
import { ECommerceModule } from './e-commerce/e-commerce.module';
|
||||||
import { PagesRoutingModule } from './pages-routing.module';
|
import { AdminRoutingModule } from './admin-routing.module';
|
||||||
import { MiscellaneousModule } from './miscellaneous/miscellaneous.module';
|
import { MiscellaneousModule } from './miscellaneous/miscellaneous.module';
|
||||||
|
import { CategoryModule } from './category/category.module';
|
||||||
|
import { SubCategoryModule } from './sub-category/sub-category.module';
|
||||||
|
import { BrandModule } from './brand/brand.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
PagesRoutingModule,
|
AdminRoutingModule,
|
||||||
ThemeModule,
|
ThemeModule,
|
||||||
NbMenuModule,
|
NbMenuModule,
|
||||||
DashboardModule,
|
DashboardModule,
|
||||||
ECommerceModule,
|
ECommerceModule,
|
||||||
MiscellaneousModule,
|
MiscellaneousModule,
|
||||||
|
CategoryModule,
|
||||||
|
SubCategoryModule,
|
||||||
|
BrandModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
PagesComponent,
|
AdminComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class PagesModule {
|
export class AdminModule {
|
||||||
}
|
}
|
||||||
10
src/app/admin/banner/banner-edit/banner-edit.component.html
Normal file
10
src/app/admin/banner/banner-edit/banner-edit.component.html
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<nb-card>
|
||||||
|
<nb-card-header>
|
||||||
|
Banners
|
||||||
|
</nb-card-header>
|
||||||
|
|
||||||
|
<nb-card-body>
|
||||||
|
<ng2-smart-table [settings]="settings" [source]="source" (edit)="onEdit($event)" (userRowSelect)="onEdit($event)">
|
||||||
|
</ng2-smart-table>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
92
src/app/admin/banner/banner-edit/banner-edit.component.ts
Normal file
92
src/app/admin/banner/banner-edit/banner-edit.component.ts
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
|
import { LocalDataSource } from "ng2-smart-table";
|
||||||
|
import { BannerService } from "../banner.service";
|
||||||
|
import { Router } from "@angular/router";
|
||||||
|
import { Banner } from "../banner.model";
|
||||||
|
import { Subject } from "rxjs";
|
||||||
|
import { takeUntil, tap } from "rxjs/operators";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "ngx-banner-edit",
|
||||||
|
templateUrl: "./banner-edit.component.html",
|
||||||
|
styleUrls: ["./banner-edit.component.scss"],
|
||||||
|
})
|
||||||
|
export class BannerEditComponent implements OnInit, OnDestroy {
|
||||||
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
mode: "external",
|
||||||
|
actions: {
|
||||||
|
add: false,
|
||||||
|
delete: false,
|
||||||
|
},
|
||||||
|
edit: {
|
||||||
|
editButtonContent: '<i class="nb-edit"></i>',
|
||||||
|
saveButtonContent: '<i class="nb-checkmark"></i>',
|
||||||
|
cancelButtonContent: '<i class="nb-close"></i>',
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
id: {
|
||||||
|
title: "ID",
|
||||||
|
type: "string",
|
||||||
|
editable: false,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
title: "Title",
|
||||||
|
type: "string",
|
||||||
|
editable: false,
|
||||||
|
},
|
||||||
|
sorting: {
|
||||||
|
title: "Sorting",
|
||||||
|
type: "number",
|
||||||
|
editable: false,
|
||||||
|
},
|
||||||
|
clickCount: {
|
||||||
|
title: "Click Count",
|
||||||
|
type: "number",
|
||||||
|
editable: false,
|
||||||
|
},
|
||||||
|
viewCount: {
|
||||||
|
title: "View Count",
|
||||||
|
type: "number",
|
||||||
|
editable: false,
|
||||||
|
},
|
||||||
|
isActive: {
|
||||||
|
title: "Is Active",
|
||||||
|
type: "boolean",
|
||||||
|
editable: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
source: LocalDataSource = new LocalDataSource();
|
||||||
|
loading: boolean = true;
|
||||||
|
banners: Banner[];
|
||||||
|
|
||||||
|
constructor(private bannerService: BannerService, private router: Router) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.bannerService
|
||||||
|
.listBanners()
|
||||||
|
.pipe(
|
||||||
|
tap(() => {
|
||||||
|
this.loading = true;
|
||||||
|
}),
|
||||||
|
takeUntil(this.destroy$)
|
||||||
|
)
|
||||||
|
.subscribe(({ data, loading }) => {
|
||||||
|
this.loading = loading;
|
||||||
|
this.banners = data.listBanners;
|
||||||
|
this.source.load(this.banners);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
onEdit(event): void {
|
||||||
|
this.router.navigate(["admin", "banner", "edit", event.data.id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/app/admin/banner/banner-routing.module.ts
Normal file
37
src/app/admin/banner/banner-routing.module.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
|
||||||
|
import { BannerComponent } from './banner.component';
|
||||||
|
import { BannerEditComponent } from './banner-edit/banner-edit.component';
|
||||||
|
import { BannerUpsertComponent } from './banner-upsert/banner-upsert.component';
|
||||||
|
|
||||||
|
const routes: Routes = [{
|
||||||
|
path: '',
|
||||||
|
component: BannerComponent,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'edit',
|
||||||
|
component: BannerEditComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'edit/:id',
|
||||||
|
component: BannerUpsertComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'create',
|
||||||
|
component: BannerUpsertComponent,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule],
|
||||||
|
})
|
||||||
|
export class BannerRoutingModule { }
|
||||||
|
|
||||||
|
export const routedComponents = [
|
||||||
|
BannerComponent,
|
||||||
|
BannerEditComponent,
|
||||||
|
BannerUpsertComponent
|
||||||
|
];
|
||||||
106
src/app/admin/banner/banner-upsert/banner-upsert.component.html
Normal file
106
src/app/admin/banner/banner-upsert/banner-upsert.component.html
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<nb-card *ngIf="!loading">
|
||||||
|
<nb-card-header>Banner {{ banner.id }}</nb-card-header>
|
||||||
|
<nb-card-body>
|
||||||
|
<div *ngIf="banner.id" class="summary-container">
|
||||||
|
<div>
|
||||||
|
<div>Created At</div>
|
||||||
|
<div class="h6">{{ banner.createdAt | date: 'dd:MM:YYYY HH:mm:ss' }}</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>Click Count</div>
|
||||||
|
<div class="h6">{{ banner.clickCount || 0 }}</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>View Count</div>
|
||||||
|
<div class="h6">{{ banner.viewCount || 0 }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form (ngSubmit)="onSubmit(bannerForm.form)" #bannerForm="ngForm">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="bannerTitle" class="label">Title</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
nbInput
|
||||||
|
fullWidth
|
||||||
|
id="bannerTitle"
|
||||||
|
placeholder="Title"
|
||||||
|
required
|
||||||
|
[(ngModel)]="banner.title"
|
||||||
|
name="title"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="bannerText" class="label">Text</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
nbInput
|
||||||
|
fullWidth
|
||||||
|
id="bannerText"
|
||||||
|
placeholder="Text"
|
||||||
|
required
|
||||||
|
[(ngModel)]="banner.text"
|
||||||
|
name="text"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="bannerSorting" class="label">Sorting</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
nbInput
|
||||||
|
fullWidth
|
||||||
|
id="bannerSorting"
|
||||||
|
placeholder="Sorting"
|
||||||
|
required
|
||||||
|
[(ngModel)]="banner.sorting"
|
||||||
|
name="sorting"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="bannerLink" class="label">Link</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
nbInput
|
||||||
|
fullWidth
|
||||||
|
id="bannerLink"
|
||||||
|
placeholder="Link"
|
||||||
|
required
|
||||||
|
[(ngModel)]="banner.link"
|
||||||
|
name="link"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="bannerImgUrl" class="label">ImgUrl</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
nbInput
|
||||||
|
fullWidth
|
||||||
|
id="bannerImgUrl"
|
||||||
|
placeholder="ImgUrl"
|
||||||
|
required
|
||||||
|
[(ngModel)]="banner.imgUrl"
|
||||||
|
name="imgUrl"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<nb-checkbox required [(ngModel)]="banner.isActive" name="isActive"
|
||||||
|
>Active</nb-checkbox
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="form-group ">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
nbButton
|
||||||
|
status="primary"
|
||||||
|
[disabled]="!bannerForm.form.valid"
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
|
||||||
|
nb-checkbox {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-inline [fullWidth] {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-inline > * {
|
||||||
|
margin: 0 1.5rem 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb-card.inline-form-card nb-card-body {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
.summary-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex: 1;
|
||||||
|
background-color: nb-theme(background-basic-color-2);
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 1.5rem 4rem 1rem;
|
||||||
|
border: 1px solid nb-theme(border-basic-color-3);
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
116
src/app/admin/banner/banner-upsert/banner-upsert.component.ts
Normal file
116
src/app/admin/banner/banner-upsert/banner-upsert.component.ts
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
|
import { ActivatedRoute, ParamMap, Router } from "@angular/router";
|
||||||
|
import { BannerService } from "../banner.service";
|
||||||
|
import { Banner } from "../banner.model";
|
||||||
|
import { NgForm } from "@angular/forms";
|
||||||
|
import { takeUntil, tap } from "rxjs/operators";
|
||||||
|
import {
|
||||||
|
NbToastrService,
|
||||||
|
NbComponentStatus,
|
||||||
|
NbGlobalPhysicalPosition,
|
||||||
|
} from "@nebular/theme";
|
||||||
|
import { Subject } from "rxjs";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "ngx-banner-upsert",
|
||||||
|
styleUrls: ["./banner-upsert.component.scss"],
|
||||||
|
templateUrl: "./banner-upsert.component.html",
|
||||||
|
})
|
||||||
|
export class BannerUpsertComponent implements OnInit, OnDestroy {
|
||||||
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
|
|
||||||
|
id: string;
|
||||||
|
loading: boolean = false;
|
||||||
|
banner: Banner;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private router: Router,
|
||||||
|
private toastrService: NbToastrService,
|
||||||
|
private bannerService: BannerService
|
||||||
|
) {
|
||||||
|
this.banner = new Banner();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.route.paramMap.subscribe((params: ParamMap) => {
|
||||||
|
this.id = params.get("id");
|
||||||
|
|
||||||
|
if (this.id) {
|
||||||
|
this.bannerService
|
||||||
|
.findUniqueBanner(this.id)
|
||||||
|
.pipe(
|
||||||
|
tap(() => {
|
||||||
|
this.loading = true;
|
||||||
|
}),
|
||||||
|
takeUntil(this.destroy$)
|
||||||
|
)
|
||||||
|
.subscribe(({ data, loading }) => {
|
||||||
|
this.loading = loading;
|
||||||
|
this.banner = Object.assign({}, data.findUniqueBanner);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit(form: NgForm) {
|
||||||
|
const banner = {
|
||||||
|
...form.value,
|
||||||
|
id: this.id,
|
||||||
|
} as Banner;
|
||||||
|
|
||||||
|
if (this.id) {
|
||||||
|
this.bannerService
|
||||||
|
.updateBanner(banner)
|
||||||
|
.pipe(takeUntil(this.destroy$))
|
||||||
|
.subscribe(
|
||||||
|
({ data }) => {
|
||||||
|
this.toastrService.show(
|
||||||
|
null,
|
||||||
|
`Banner has been successfully updated`,
|
||||||
|
{
|
||||||
|
status: "success",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
this.toastrService.show(error.toString(), `Something went wrong`, {
|
||||||
|
status: "danger",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.bannerService
|
||||||
|
.createBanner(banner)
|
||||||
|
.pipe(takeUntil(this.destroy$))
|
||||||
|
.subscribe(
|
||||||
|
({ data }) => {
|
||||||
|
this.toastrService.show(
|
||||||
|
null,
|
||||||
|
`Banner has been successfully created`,
|
||||||
|
{
|
||||||
|
status: "success",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.router.navigate([
|
||||||
|
"admin",
|
||||||
|
"banner",
|
||||||
|
"edit",
|
||||||
|
data.createBanner.id,
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
this.toastrService.show(error.toString(), `Something went wrong`, {
|
||||||
|
status: "danger",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/app/admin/banner/banner.component.ts
Normal file
8
src/app/admin/banner/banner.component.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-banner',
|
||||||
|
template: `<router-outlet></router-outlet>`,
|
||||||
|
})
|
||||||
|
export class BannerComponent {
|
||||||
|
}
|
||||||
16
src/app/admin/banner/banner.model.ts
Normal file
16
src/app/admin/banner/banner.model.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
export class Banner {
|
||||||
|
id!: string;
|
||||||
|
title!: string;
|
||||||
|
text!: string;
|
||||||
|
imgUrl!: string | null;
|
||||||
|
link!: string | null;
|
||||||
|
createdAt!: Date;
|
||||||
|
isActive!: boolean;
|
||||||
|
sorting!: number;
|
||||||
|
viewCount!: number | null;
|
||||||
|
clickCount!: number | null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.isActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
47
src/app/admin/banner/banner.module.ts
Normal file
47
src/app/admin/banner/banner.module.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import {
|
||||||
|
NbActionsModule,
|
||||||
|
NbButtonModule,
|
||||||
|
NbCardModule,
|
||||||
|
NbCheckboxModule,
|
||||||
|
NbDatepickerModule,
|
||||||
|
NbIconModule,
|
||||||
|
NbInputModule,
|
||||||
|
NbRadioModule,
|
||||||
|
NbSelectModule,
|
||||||
|
NbUserModule,
|
||||||
|
NbTreeGridModule
|
||||||
|
} from '@nebular/theme';
|
||||||
|
import { Ng2SmartTableModule } from 'ng2-smart-table';
|
||||||
|
|
||||||
|
import { ThemeModule } from '../../@theme/theme.module';
|
||||||
|
import { BannerRoutingModule, routedComponents } from './banner-routing.module';
|
||||||
|
import { BannerService } from './banner.service';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
NbCardModule,
|
||||||
|
NbTreeGridModule,
|
||||||
|
NbIconModule,
|
||||||
|
NbInputModule,
|
||||||
|
ThemeModule,
|
||||||
|
BannerRoutingModule,
|
||||||
|
Ng2SmartTableModule,
|
||||||
|
FormsModule,
|
||||||
|
NbButtonModule,
|
||||||
|
NbActionsModule,
|
||||||
|
NbUserModule,
|
||||||
|
NbCheckboxModule,
|
||||||
|
NbRadioModule,
|
||||||
|
NbDatepickerModule,
|
||||||
|
NbSelectModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
...routedComponents
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
BannerService,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class BannerModule { }
|
||||||
66
src/app/admin/banner/banner.service.ts
Normal file
66
src/app/admin/banner/banner.service.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { delay, map } from 'rxjs/operators';
|
||||||
|
import { Apollo } from 'apollo-angular';
|
||||||
|
import { FIND_UNIQUE_BANNER, LIST_BANNERS } from './graphql/queries';
|
||||||
|
import { Banner } from './banner.model';
|
||||||
|
import { CREATE_BANNER, UPDATE_BANNER } from './graphql/mutations';
|
||||||
|
|
||||||
|
const TOTAL_PAGES = 7;
|
||||||
|
|
||||||
|
export class NewsPost {
|
||||||
|
title: string;
|
||||||
|
link: string;
|
||||||
|
creator: string;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BannerService {
|
||||||
|
|
||||||
|
constructor(private http: HttpClient, private readonly apollo: Apollo) {}
|
||||||
|
|
||||||
|
load(page: number, pageSize: number): Observable<NewsPost[]> {
|
||||||
|
const startIndex = ((page - 1) % TOTAL_PAGES) * pageSize;
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.get<NewsPost[]>('assets/data/news.json')
|
||||||
|
.pipe(
|
||||||
|
map(news => news.splice(startIndex, pageSize)),
|
||||||
|
delay(1500),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
listBanners(): Observable<any> {
|
||||||
|
return this.apollo
|
||||||
|
.watchQuery<Banner>({
|
||||||
|
query: LIST_BANNERS(),
|
||||||
|
})
|
||||||
|
.valueChanges
|
||||||
|
}
|
||||||
|
|
||||||
|
findUniqueBanner(id: Banner["id"]): Observable<any> {
|
||||||
|
return this.apollo
|
||||||
|
.watchQuery<Banner>({
|
||||||
|
query: FIND_UNIQUE_BANNER(id),
|
||||||
|
})
|
||||||
|
.valueChanges
|
||||||
|
}
|
||||||
|
|
||||||
|
createBanner(banner: Banner) {
|
||||||
|
console.log(CREATE_BANNER(banner));
|
||||||
|
return this.apollo
|
||||||
|
.mutate<any>({
|
||||||
|
mutation: CREATE_BANNER(banner),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateBanner(banner: Banner) {
|
||||||
|
console.log(UPDATE_BANNER(banner));
|
||||||
|
return this.apollo
|
||||||
|
.mutate({
|
||||||
|
mutation: UPDATE_BANNER(banner),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
46
src/app/admin/banner/graphql/mutations.ts
Normal file
46
src/app/admin/banner/graphql/mutations.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { gql } from "apollo-angular";
|
||||||
|
import { Banner } from "../banner.model";
|
||||||
|
|
||||||
|
export const UPDATE_BANNER = (banner: Banner) => gql`
|
||||||
|
mutation UpdateBanner{
|
||||||
|
updateBanner(
|
||||||
|
data: {
|
||||||
|
title: { set: "${banner.title}" }
|
||||||
|
text: { set: "${banner.text}" }
|
||||||
|
sorting: { set: ${banner.sorting} }
|
||||||
|
link: { set: "${banner.link}" }
|
||||||
|
imgUrl: { set: "${banner.imgUrl}" }
|
||||||
|
isActive: { set: ${banner.isActive} }
|
||||||
|
}
|
||||||
|
where: { id: "${banner.id}" }
|
||||||
|
) {
|
||||||
|
clickCount
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
imgUrl
|
||||||
|
isActive
|
||||||
|
link
|
||||||
|
sorting
|
||||||
|
text
|
||||||
|
title
|
||||||
|
viewCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CREATE_BANNER = (banner: Banner) => gql`
|
||||||
|
mutation CreateBanner {
|
||||||
|
createBanner(
|
||||||
|
data: {
|
||||||
|
title: "${banner.title}"
|
||||||
|
text: "${banner.text}"
|
||||||
|
sorting: ${banner.sorting}
|
||||||
|
link: "${banner.link}"
|
||||||
|
isActive: ${banner.isActive}
|
||||||
|
imgUrl: "${banner.imgUrl}"
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
32
src/app/admin/banner/graphql/queries.ts
Normal file
32
src/app/admin/banner/graphql/queries.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { gql } from "apollo-angular";
|
||||||
|
|
||||||
|
export const LIST_BANNERS = () => gql`
|
||||||
|
query ListBanners {
|
||||||
|
listBanners {
|
||||||
|
clickCount
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
isActive
|
||||||
|
sorting
|
||||||
|
title
|
||||||
|
viewCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const FIND_UNIQUE_BANNER = (id: string) =>
|
||||||
|
gql`
|
||||||
|
query FindUniqueBanner {
|
||||||
|
findUniqueBanner(where: { id: "${id}" }) {
|
||||||
|
clickCount
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
imgUrl
|
||||||
|
isActive
|
||||||
|
link
|
||||||
|
sorting
|
||||||
|
text
|
||||||
|
title
|
||||||
|
viewCount
|
||||||
|
}
|
||||||
|
}`;
|
||||||
7
src/app/admin/brand/brand-count.model.ts
Normal file
7
src/app/admin/brand/brand-count.model.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
export class BrandCount {
|
||||||
|
products?: number;
|
||||||
|
|
||||||
|
constructor(){
|
||||||
|
this.products = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/app/admin/brand/brand-edit/brand-edit.component.html
Normal file
10
src/app/admin/brand/brand-edit/brand-edit.component.html
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<nb-card>
|
||||||
|
<nb-card-header>
|
||||||
|
Categories
|
||||||
|
</nb-card-header>
|
||||||
|
|
||||||
|
<nb-card-body>
|
||||||
|
<ng2-smart-table [settings]="settings" [source]="source" (edit)="onEdit($event)" (userRowSelect)="onEdit($event)">
|
||||||
|
</ng2-smart-table>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
7
src/app/admin/brand/brand-edit/brand-edit.component.scss
Normal file
7
src/app/admin/brand/brand-edit/brand-edit.component.scss
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
nb-card {
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
71
src/app/admin/brand/brand-edit/brand-edit.component.ts
Normal file
71
src/app/admin/brand/brand-edit/brand-edit.component.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
|
import { LocalDataSource } from "ng2-smart-table";
|
||||||
|
import { BrandService } from "../brand.service";
|
||||||
|
import { Router } from "@angular/router";
|
||||||
|
import { Brand } from "../brand.model";
|
||||||
|
import { Subject } from "rxjs";
|
||||||
|
import { takeUntil, tap } from "rxjs/operators";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "ngx-brand-edit",
|
||||||
|
templateUrl: "./brand-edit.component.html",
|
||||||
|
styleUrls: ["./brand-edit.component.scss"],
|
||||||
|
})
|
||||||
|
export class BrandEditComponent implements OnInit, OnDestroy {
|
||||||
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
mode: 'external',
|
||||||
|
actions: {
|
||||||
|
add: false,
|
||||||
|
delete: false,
|
||||||
|
},
|
||||||
|
edit: {
|
||||||
|
editButtonContent: '<i class="nb-edit"></i>',
|
||||||
|
saveButtonContent: '<i class="nb-checkmark"></i>',
|
||||||
|
cancelButtonContent: '<i class="nb-close"></i>',
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
id: {
|
||||||
|
title: "ID",
|
||||||
|
type: "string",
|
||||||
|
editable: false,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
title: "Name",
|
||||||
|
type: "string",
|
||||||
|
editable: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
source: LocalDataSource = new LocalDataSource();
|
||||||
|
loading: boolean = true;
|
||||||
|
brands: Brand[];
|
||||||
|
|
||||||
|
constructor(private brandService: BrandService, private router: Router) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.brandService.listBrands()
|
||||||
|
.pipe(
|
||||||
|
tap(() => {
|
||||||
|
this.loading = true;
|
||||||
|
}),
|
||||||
|
takeUntil(this.destroy$)
|
||||||
|
).subscribe(({ data, loading }) => {
|
||||||
|
this.loading = loading;
|
||||||
|
this.brands = data.listBrands;
|
||||||
|
this.source.load(this.brands);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
onEdit(event): void {
|
||||||
|
this.router.navigate(["admin", "brand", "edit", event.data.id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/app/admin/brand/brand-routing.module.ts
Normal file
37
src/app/admin/brand/brand-routing.module.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
|
||||||
|
import { BrandComponent } from './brand.component';
|
||||||
|
import { BrandEditComponent } from './brand-edit/brand-edit.component';
|
||||||
|
import { BrandUpsertComponent } from './brand-upsert/brand-upsert.component';
|
||||||
|
|
||||||
|
const routes: Routes = [{
|
||||||
|
path: '',
|
||||||
|
component: BrandComponent,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'edit',
|
||||||
|
component: BrandEditComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'edit/:id',
|
||||||
|
component: BrandUpsertComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'create',
|
||||||
|
component: BrandUpsertComponent,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule],
|
||||||
|
})
|
||||||
|
export class BrandRoutingModule { }
|
||||||
|
|
||||||
|
export const routedComponents = [
|
||||||
|
BrandComponent,
|
||||||
|
BrandEditComponent,
|
||||||
|
BrandUpsertComponent
|
||||||
|
];
|
||||||
58
src/app/admin/brand/brand-upsert/brand-upsert.component.html
Normal file
58
src/app/admin/brand/brand-upsert/brand-upsert.component.html
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<nb-card *ngIf="!loading">
|
||||||
|
<nb-card-header>
|
||||||
|
<nb-icon (click)="goBackToList()" [icon]="'arrow-ios-back-outline'" pack="eva"></nb-icon>
|
||||||
|
Brand {{ brand.id }}</nb-card-header>
|
||||||
|
<nb-card-body>
|
||||||
|
<div *ngIf="brand.id" class="summary-container">
|
||||||
|
<div>
|
||||||
|
<div>Created At</div>
|
||||||
|
<div class="h6">{{ brand.createdAt | date: 'dd:MM:YYYY HH:mm:ss' }}</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>Products Count</div>
|
||||||
|
<div class="h6">{{ brand._count?.products || 0 }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form (ngSubmit)="onSubmit(brandForm.form)" #brandForm="ngForm">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="brandName" class="label">Name</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
nbInput
|
||||||
|
fullWidth
|
||||||
|
id="brandName"
|
||||||
|
placeholder="Name"
|
||||||
|
required
|
||||||
|
[(ngModel)]="brand.name"
|
||||||
|
name="name"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group buttons-row">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
nbButton
|
||||||
|
status="primary"
|
||||||
|
[disabled]="!brandForm.form.valid"
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
*ngIf="brand.id"
|
||||||
|
type="button"
|
||||||
|
(click)="onDelete()"
|
||||||
|
nbButton
|
||||||
|
status="danger"
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
43
src/app/admin/brand/brand-upsert/brand-upsert.component.scss
Normal file
43
src/app/admin/brand/brand-upsert/brand-upsert.component.scss
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
@import "../../../@theme/styles/themes";
|
||||||
|
|
||||||
|
nb-checkbox {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb-icon {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-inline [fullWidth] {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-inline > * {
|
||||||
|
margin: 0 1.5rem 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb-card.inline-form-card nb-card-body {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
.summary-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex: 1;
|
||||||
|
background-color: nb-theme(background-basic-color-2);
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 1.5rem 4rem 1rem;
|
||||||
|
border: 1px solid nb-theme(border-basic-color-3);
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-row {
|
||||||
|
margin: -0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button[nbButton] {
|
||||||
|
margin: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
157
src/app/admin/brand/brand-upsert/brand-upsert.component.ts
Normal file
157
src/app/admin/brand/brand-upsert/brand-upsert.component.ts
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
|
import { ActivatedRoute, ParamMap, Router } from "@angular/router";
|
||||||
|
import { BrandService } from "../brand.service";
|
||||||
|
import { Brand } from "../brand.model";
|
||||||
|
import { NgForm } from "@angular/forms";
|
||||||
|
import { takeUntil, tap } from "rxjs/operators";
|
||||||
|
import {
|
||||||
|
NbDialogService,
|
||||||
|
NbToastrService,
|
||||||
|
} from "@nebular/theme";
|
||||||
|
import { Subject } from "rxjs";
|
||||||
|
import { DialogPromptComponent } from "../../../@theme/components/dialogs/dialog-name-prompt/dialog-prompt.component";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "ngx-brand-upsert",
|
||||||
|
styleUrls: ["./brand-upsert.component.scss"],
|
||||||
|
templateUrl: "./brand-upsert.component.html",
|
||||||
|
})
|
||||||
|
export class BrandUpsertComponent implements OnInit, OnDestroy {
|
||||||
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
|
|
||||||
|
id: string;
|
||||||
|
loading: boolean = false;
|
||||||
|
brand: Brand;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private router: Router,
|
||||||
|
private toastrService: NbToastrService,
|
||||||
|
private dialogService: NbDialogService,
|
||||||
|
private brandService: BrandService
|
||||||
|
) {
|
||||||
|
this.brand = new Brand();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.route.paramMap.subscribe((params: ParamMap) => {
|
||||||
|
this.id = params.get("id");
|
||||||
|
|
||||||
|
if (this.id) {
|
||||||
|
this.brandService
|
||||||
|
.findUniqueBrand(this.id)
|
||||||
|
.pipe(
|
||||||
|
tap(() => {
|
||||||
|
this.loading = true;
|
||||||
|
}),
|
||||||
|
takeUntil(this.destroy$)
|
||||||
|
)
|
||||||
|
.subscribe(({ data, loading }) => {
|
||||||
|
this.loading = loading;
|
||||||
|
this.brand = Object.assign({}, data.findUniqueBrand);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit(form: NgForm) {
|
||||||
|
const brand = {
|
||||||
|
...form.value,
|
||||||
|
id: this.id
|
||||||
|
} as Brand;
|
||||||
|
|
||||||
|
if (this.id) {
|
||||||
|
this.brandService
|
||||||
|
.updateBrand(brand)
|
||||||
|
.pipe(takeUntil(this.destroy$))
|
||||||
|
.subscribe(
|
||||||
|
({ data }) => {
|
||||||
|
this.toastrService.show(
|
||||||
|
null,
|
||||||
|
`Brand has been successfully updated`,
|
||||||
|
{
|
||||||
|
status: "success",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
this.toastrService.show(error.toString(), `Something went wrong`, {
|
||||||
|
status: "danger",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.brandService
|
||||||
|
.createBrand(brand)
|
||||||
|
.pipe(takeUntil(this.destroy$))
|
||||||
|
.subscribe(
|
||||||
|
({ data }) => {
|
||||||
|
this.toastrService.show(
|
||||||
|
null,
|
||||||
|
`Brand has been successfully created`,
|
||||||
|
{
|
||||||
|
status: "success",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.router.navigate([
|
||||||
|
"admin",
|
||||||
|
"brand",
|
||||||
|
"edit",
|
||||||
|
data.createBrand.id,
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
this.toastrService.show(error.toString(), `Something went wrong`, {
|
||||||
|
status: "danger",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDelete(){
|
||||||
|
if (!this.id) return;
|
||||||
|
|
||||||
|
this.dialogService.open(DialogPromptComponent)
|
||||||
|
.onClose.subscribe(result => result && this.onDeleteConfirmation());
|
||||||
|
}
|
||||||
|
|
||||||
|
onDeleteConfirmation() {
|
||||||
|
if (!this.id) return;
|
||||||
|
|
||||||
|
this.brandService
|
||||||
|
.deleteBrand(this.id)
|
||||||
|
.pipe(takeUntil(this.destroy$))
|
||||||
|
.subscribe(
|
||||||
|
({ data }) => {
|
||||||
|
this.toastrService.show(
|
||||||
|
null,
|
||||||
|
`Brand has been successfully deleted`,
|
||||||
|
{
|
||||||
|
status: "success",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.goBackToList()
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
this.toastrService.show(error.toString(), `Something went wrong`, {
|
||||||
|
status: "danger",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
goBackToList() {
|
||||||
|
this.router.navigate([
|
||||||
|
"admin",
|
||||||
|
"brand",
|
||||||
|
"edit"
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/app/admin/brand/brand.component.ts
Normal file
8
src/app/admin/brand/brand.component.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-brand',
|
||||||
|
template: `<router-outlet></router-outlet>`,
|
||||||
|
})
|
||||||
|
export class BrandComponent {
|
||||||
|
}
|
||||||
13
src/app/admin/brand/brand.model.ts
Normal file
13
src/app/admin/brand/brand.model.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { BrandCount } from "./brand-count.model";
|
||||||
|
|
||||||
|
export class Brand {
|
||||||
|
id!: string;
|
||||||
|
name!: string;
|
||||||
|
createdAt!: Date;
|
||||||
|
updatedAt!: Date | null;
|
||||||
|
_count?: BrandCount;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._count = new BrandCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
49
src/app/admin/brand/brand.module.ts
Normal file
49
src/app/admin/brand/brand.module.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import {
|
||||||
|
NbActionsModule,
|
||||||
|
NbButtonModule,
|
||||||
|
NbCardModule,
|
||||||
|
NbCheckboxModule,
|
||||||
|
NbDatepickerModule,
|
||||||
|
NbIconModule,
|
||||||
|
NbInputModule,
|
||||||
|
NbRadioModule,
|
||||||
|
NbSelectModule,
|
||||||
|
NbUserModule,
|
||||||
|
NbTreeGridModule,
|
||||||
|
NbListModule
|
||||||
|
} from '@nebular/theme';
|
||||||
|
import { Ng2SmartTableModule } from 'ng2-smart-table';
|
||||||
|
|
||||||
|
import { ThemeModule } from '../../@theme/theme.module';
|
||||||
|
import { BrandRoutingModule, routedComponents } from './brand-routing.module';
|
||||||
|
import { BrandService } from './brand.service';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
NbCardModule,
|
||||||
|
NbTreeGridModule,
|
||||||
|
NbIconModule,
|
||||||
|
NbInputModule,
|
||||||
|
ThemeModule,
|
||||||
|
BrandRoutingModule,
|
||||||
|
Ng2SmartTableModule,
|
||||||
|
FormsModule,
|
||||||
|
NbButtonModule,
|
||||||
|
NbActionsModule,
|
||||||
|
NbUserModule,
|
||||||
|
NbCheckboxModule,
|
||||||
|
NbRadioModule,
|
||||||
|
NbDatepickerModule,
|
||||||
|
NbSelectModule,
|
||||||
|
NbListModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
...routedComponents
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
BrandService,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class BrandModule { }
|
||||||
50
src/app/admin/brand/brand.service.ts
Normal file
50
src/app/admin/brand/brand.service.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { Apollo } from 'apollo-angular';
|
||||||
|
import { FIND_UNIQUE_BRAND, LIST_BRANDS } from './graphql/queries';
|
||||||
|
import { Brand } from './brand.model';
|
||||||
|
import { CREATE_BRAND, DELETE_BRAND, UPDATE_BRAND } from './graphql/mutations';
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BrandService {
|
||||||
|
|
||||||
|
constructor(private readonly apollo: Apollo) {}
|
||||||
|
|
||||||
|
listBrands(): Observable<any> {
|
||||||
|
return this.apollo
|
||||||
|
.watchQuery<Brand>({
|
||||||
|
query: LIST_BRANDS(),
|
||||||
|
})
|
||||||
|
.valueChanges
|
||||||
|
}
|
||||||
|
|
||||||
|
findUniqueBrand(id: Brand["id"]): Observable<any> {
|
||||||
|
return this.apollo
|
||||||
|
.watchQuery<Brand>({
|
||||||
|
query: FIND_UNIQUE_BRAND(id),
|
||||||
|
})
|
||||||
|
.valueChanges
|
||||||
|
}
|
||||||
|
|
||||||
|
createBrand(category: Brand) {
|
||||||
|
return this.apollo
|
||||||
|
.mutate<any>({
|
||||||
|
mutation: CREATE_BRAND(category),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateBrand(category: Brand) {
|
||||||
|
return this.apollo
|
||||||
|
.mutate({
|
||||||
|
mutation: UPDATE_BRAND(category),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteBrand(id: string) {
|
||||||
|
return this.apollo
|
||||||
|
.mutate({
|
||||||
|
mutation: DELETE_BRAND(id),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
47
src/app/admin/brand/graphql/mutations.ts
Normal file
47
src/app/admin/brand/graphql/mutations.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { gql } from "apollo-angular";
|
||||||
|
import { Brand } from "../brand.model";
|
||||||
|
|
||||||
|
export const UPDATE_BRAND = (brand: Brand) => gql`
|
||||||
|
mutation UpdateBrand {
|
||||||
|
updateBrand(
|
||||||
|
data: {
|
||||||
|
name: { set: "${brand.name}" }
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
id: "${brand.id}"
|
||||||
|
}) {
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
name
|
||||||
|
updatedAt
|
||||||
|
_count {
|
||||||
|
products
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CREATE_BRAND = (brand: Brand) => gql`
|
||||||
|
mutation CreateBrand {
|
||||||
|
createBrand(data: { name: "${brand.name}" }) {
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
name
|
||||||
|
updatedAt
|
||||||
|
_count {
|
||||||
|
products
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const DELETE_BRAND = (id: string) => gql`
|
||||||
|
mutation DeleteBrand {
|
||||||
|
deleteBrand(where: { id: "${id}" }) {
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
name
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
27
src/app/admin/brand/graphql/queries.ts
Normal file
27
src/app/admin/brand/graphql/queries.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { gql } from "apollo-angular";
|
||||||
|
|
||||||
|
export const LIST_BRANDS = () => gql`
|
||||||
|
query ListBrands {
|
||||||
|
listBrands {
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
name
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const FIND_UNIQUE_BRAND = (id: string) =>
|
||||||
|
gql`
|
||||||
|
query FindUniqueBrand {
|
||||||
|
findUniqueBrand(where: { id: "${id}" }) {
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
name
|
||||||
|
updatedAt
|
||||||
|
_count {
|
||||||
|
products
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
9
src/app/admin/category/category-count.model.ts
Normal file
9
src/app/admin/category/category-count.model.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
export class CategoryCount {
|
||||||
|
Product?: number;
|
||||||
|
SubCategory?: number;
|
||||||
|
|
||||||
|
constructor(){
|
||||||
|
this.Product = 0;
|
||||||
|
this.SubCategory = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<nb-card>
|
||||||
|
<nb-card-header>
|
||||||
|
Categories
|
||||||
|
</nb-card-header>
|
||||||
|
|
||||||
|
<nb-card-body>
|
||||||
|
<ng2-smart-table [settings]="settings" [source]="source" (edit)="onEdit($event)" (userRowSelect)="onEdit($event)">
|
||||||
|
</ng2-smart-table>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
nb-card {
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
|
import { LocalDataSource } from "ng2-smart-table";
|
||||||
|
import { CategoryService } from "../category.service";
|
||||||
|
import { Router } from "@angular/router";
|
||||||
|
import { Category } from "../category.model";
|
||||||
|
import { Subject } from "rxjs";
|
||||||
|
import { takeUntil, tap } from "rxjs/operators";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "ngx-category-edit",
|
||||||
|
templateUrl: "./category-edit.component.html",
|
||||||
|
styleUrls: ["./category-edit.component.scss"],
|
||||||
|
})
|
||||||
|
export class CategoryEditComponent implements OnInit, OnDestroy {
|
||||||
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
mode: 'external',
|
||||||
|
actions: {
|
||||||
|
add: false,
|
||||||
|
delete: false,
|
||||||
|
},
|
||||||
|
edit: {
|
||||||
|
editButtonContent: '<i class="nb-edit"></i>',
|
||||||
|
saveButtonContent: '<i class="nb-checkmark"></i>',
|
||||||
|
cancelButtonContent: '<i class="nb-close"></i>',
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
id: {
|
||||||
|
title: "ID",
|
||||||
|
type: "string",
|
||||||
|
editable: false,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
title: "Name",
|
||||||
|
type: "string",
|
||||||
|
editable: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
source: LocalDataSource = new LocalDataSource();
|
||||||
|
loading: boolean = true;
|
||||||
|
categories: Category[];
|
||||||
|
|
||||||
|
constructor(private categoryService: CategoryService, private router: Router) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.categoryService.listCategories()
|
||||||
|
.pipe(
|
||||||
|
tap(() => {
|
||||||
|
this.loading = true;
|
||||||
|
}),
|
||||||
|
takeUntil(this.destroy$)
|
||||||
|
).subscribe(({ data, loading }) => {
|
||||||
|
this.loading = loading;
|
||||||
|
this.categories = data.listCategorys;
|
||||||
|
this.source.load(this.categories);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
onEdit(event): void {
|
||||||
|
this.router.navigate(["admin", "category", "edit", event.data.id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/app/admin/category/category-routing.module.ts
Normal file
37
src/app/admin/category/category-routing.module.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
|
||||||
|
import { CategoryComponent } from './category.component';
|
||||||
|
import { CategoryEditComponent } from './category-edit/category-edit.component';
|
||||||
|
import { CategoryUpsertComponent } from './category-upsert/category-upsert.component';
|
||||||
|
|
||||||
|
const routes: Routes = [{
|
||||||
|
path: '',
|
||||||
|
component: CategoryComponent,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'edit',
|
||||||
|
component: CategoryEditComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'edit/:id',
|
||||||
|
component: CategoryUpsertComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'create',
|
||||||
|
component: CategoryUpsertComponent,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule],
|
||||||
|
})
|
||||||
|
export class CategoryRoutingModule { }
|
||||||
|
|
||||||
|
export const routedComponents = [
|
||||||
|
CategoryComponent,
|
||||||
|
CategoryEditComponent,
|
||||||
|
CategoryUpsertComponent
|
||||||
|
];
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<nb-card *ngIf="!loading">
|
||||||
|
<nb-card-header>
|
||||||
|
<nb-icon (click)="goBackToList()" [icon]="'arrow-ios-back-outline'" pack="eva"></nb-icon>
|
||||||
|
Category {{ category.id }}</nb-card-header>
|
||||||
|
<nb-card-body>
|
||||||
|
<div *ngIf="category.id" class="summary-container">
|
||||||
|
<div>
|
||||||
|
<div>Created At</div>
|
||||||
|
<div class="h6">{{ category.createdAt | date: 'dd:MM:YYYY HH:mm:ss' }}</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>Sub Categories Count</div>
|
||||||
|
<div class="h6">{{ category._count?.SubCategory || 0 }}</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>Products Count</div>
|
||||||
|
<div class="h6">{{ category._count?.Product || 0 }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form (ngSubmit)="onSubmit(categoryForm.form)" #categoryForm="ngForm">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="categoryName" class="label">Name</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
nbInput
|
||||||
|
fullWidth
|
||||||
|
id="categoryName"
|
||||||
|
placeholder="Name"
|
||||||
|
required
|
||||||
|
[(ngModel)]="category.name"
|
||||||
|
name="name"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="category.id" class="row">
|
||||||
|
<div class="col-md-12 col-lg-12 col-xxxl-12">
|
||||||
|
<nb-card class="list-card" size="small">
|
||||||
|
<nb-card-header>Sub Categories</nb-card-header>
|
||||||
|
<nb-card-body *ngIf="category.SubCategory.length === 0">
|
||||||
|
No sub categories yet.
|
||||||
|
</nb-card-body>
|
||||||
|
<nb-list *ngIf="category.SubCategory.length > 0">
|
||||||
|
<nb-list-item *ngFor="let subCategory of category.SubCategory; let i = index;">
|
||||||
|
{{subCategory.name}}
|
||||||
|
</nb-list-item>
|
||||||
|
</nb-list>
|
||||||
|
</nb-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group ">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
nbButton
|
||||||
|
status="primary"
|
||||||
|
[disabled]="!categoryForm.form.valid"
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
|
||||||
|
nb-checkbox {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb-icon {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-inline [fullWidth] {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-inline > * {
|
||||||
|
margin: 0 1.5rem 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb-card.inline-form-card nb-card-body {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
.summary-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex: 1;
|
||||||
|
background-color: nb-theme(background-basic-color-2);
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 1.5rem 4rem 1rem;
|
||||||
|
border: 1px solid nb-theme(border-basic-color-3);
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
|
import { ActivatedRoute, ParamMap, Router } from "@angular/router";
|
||||||
|
import { CategoryService } from "../category.service";
|
||||||
|
import { Category } from "../category.model";
|
||||||
|
import { NgForm } from "@angular/forms";
|
||||||
|
import { takeUntil, tap } from "rxjs/operators";
|
||||||
|
import {
|
||||||
|
NbToastrService,
|
||||||
|
} from "@nebular/theme";
|
||||||
|
import { Subject } from "rxjs";
|
||||||
|
import { SubCategory } from "../../sub-category/sub-category.model";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "ngx-category-upsert",
|
||||||
|
styleUrls: ["./category-upsert.component.scss"],
|
||||||
|
templateUrl: "./category-upsert.component.html",
|
||||||
|
})
|
||||||
|
export class CategoryUpsertComponent implements OnInit, OnDestroy {
|
||||||
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
|
|
||||||
|
id: string;
|
||||||
|
loading: boolean = false;
|
||||||
|
category: Category;
|
||||||
|
subCategories: SubCategory[] = [];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private router: Router,
|
||||||
|
private toastrService: NbToastrService,
|
||||||
|
private categoryService: CategoryService
|
||||||
|
) {
|
||||||
|
this.category = new Category();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.route.paramMap.subscribe((params: ParamMap) => {
|
||||||
|
this.id = params.get("id");
|
||||||
|
|
||||||
|
if (this.id) {
|
||||||
|
this.categoryService
|
||||||
|
.findUniqueCategory(this.id)
|
||||||
|
.pipe(
|
||||||
|
tap(() => {
|
||||||
|
this.loading = true;
|
||||||
|
}),
|
||||||
|
takeUntil(this.destroy$)
|
||||||
|
)
|
||||||
|
.subscribe(({ data, loading }) => {
|
||||||
|
this.loading = loading;
|
||||||
|
this.category = Object.assign({}, data.findUniqueCategory);
|
||||||
|
this.category.SubCategory = [...data.findUniqueCategory.SubCategory]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit(form: NgForm) {
|
||||||
|
const category = {
|
||||||
|
...form.value,
|
||||||
|
id: this.id
|
||||||
|
} as Category;
|
||||||
|
|
||||||
|
if (this.id) {
|
||||||
|
this.categoryService
|
||||||
|
.updateCategory(category)
|
||||||
|
.pipe(takeUntil(this.destroy$))
|
||||||
|
.subscribe(
|
||||||
|
({ data }) => {
|
||||||
|
this.toastrService.show(
|
||||||
|
null,
|
||||||
|
`Category has been successfully updated`,
|
||||||
|
{
|
||||||
|
status: "success",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
this.toastrService.show(error.toString(), `Something went wrong`, {
|
||||||
|
status: "danger",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.categoryService
|
||||||
|
.createCategory(category)
|
||||||
|
.pipe(takeUntil(this.destroy$))
|
||||||
|
.subscribe(
|
||||||
|
({ data }) => {
|
||||||
|
this.toastrService.show(
|
||||||
|
null,
|
||||||
|
`Category has been successfully created`,
|
||||||
|
{
|
||||||
|
status: "success",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.router.navigate([
|
||||||
|
"admin",
|
||||||
|
"category",
|
||||||
|
"edit",
|
||||||
|
data.createCategory.id,
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
this.toastrService.show(error.toString(), `Something went wrong`, {
|
||||||
|
status: "danger",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goBackToList() {
|
||||||
|
this.router.navigate([
|
||||||
|
"admin",
|
||||||
|
"category",
|
||||||
|
"edit"
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/app/admin/category/category.component.ts
Normal file
8
src/app/admin/category/category.component.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ngx-category',
|
||||||
|
template: `<router-outlet></router-outlet>`,
|
||||||
|
})
|
||||||
|
export class CategoryComponent {
|
||||||
|
}
|
||||||
16
src/app/admin/category/category.model.ts
Normal file
16
src/app/admin/category/category.model.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { CategoryCount } from "./category-count.model";
|
||||||
|
|
||||||
|
export class Category {
|
||||||
|
id!: string;
|
||||||
|
name!: string;
|
||||||
|
createdAt!: Date;
|
||||||
|
updatedAt!: Date | null;
|
||||||
|
//Products?: Array<Product>;
|
||||||
|
SubCategory?: Array<any>; //TODO:
|
||||||
|
_count?: CategoryCount;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.SubCategory = [];
|
||||||
|
this._count = new CategoryCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
49
src/app/admin/category/category.module.ts
Normal file
49
src/app/admin/category/category.module.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import {
|
||||||
|
NbActionsModule,
|
||||||
|
NbButtonModule,
|
||||||
|
NbCardModule,
|
||||||
|
NbCheckboxModule,
|
||||||
|
NbDatepickerModule,
|
||||||
|
NbIconModule,
|
||||||
|
NbInputModule,
|
||||||
|
NbRadioModule,
|
||||||
|
NbSelectModule,
|
||||||
|
NbUserModule,
|
||||||
|
NbTreeGridModule,
|
||||||
|
NbListModule
|
||||||
|
} from '@nebular/theme';
|
||||||
|
import { Ng2SmartTableModule } from 'ng2-smart-table';
|
||||||
|
|
||||||
|
import { ThemeModule } from '../../@theme/theme.module';
|
||||||
|
import { CategoryRoutingModule, routedComponents } from './category-routing.module';
|
||||||
|
import { CategoryService } from './category.service';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
NbCardModule,
|
||||||
|
NbTreeGridModule,
|
||||||
|
NbIconModule,
|
||||||
|
NbInputModule,
|
||||||
|
ThemeModule,
|
||||||
|
CategoryRoutingModule,
|
||||||
|
Ng2SmartTableModule,
|
||||||
|
FormsModule,
|
||||||
|
NbButtonModule,
|
||||||
|
NbActionsModule,
|
||||||
|
NbUserModule,
|
||||||
|
NbCheckboxModule,
|
||||||
|
NbRadioModule,
|
||||||
|
NbDatepickerModule,
|
||||||
|
NbSelectModule,
|
||||||
|
NbListModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
...routedComponents
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
CategoryService,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class CategoryModule { }
|
||||||
44
src/app/admin/category/category.service.ts
Normal file
44
src/app/admin/category/category.service.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { Apollo } from 'apollo-angular';
|
||||||
|
import { FIND_UNIQUE_CATEGORY, LIST_CATEGORIES } from './graphql/queries';
|
||||||
|
import { Category } from './category.model';
|
||||||
|
import { CREATE_CATEGORY, UPDATE_CATEGORY } from './graphql/mutations';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CategoryService {
|
||||||
|
|
||||||
|
constructor(private readonly apollo: Apollo) {}
|
||||||
|
|
||||||
|
listCategories(): Observable<any> {
|
||||||
|
return this.apollo
|
||||||
|
.watchQuery<Category>({
|
||||||
|
query: LIST_CATEGORIES(),
|
||||||
|
})
|
||||||
|
.valueChanges
|
||||||
|
}
|
||||||
|
|
||||||
|
findUniqueCategory(id: Category["id"]): Observable<any> {
|
||||||
|
return this.apollo
|
||||||
|
.watchQuery<Category>({
|
||||||
|
query: FIND_UNIQUE_CATEGORY(id),
|
||||||
|
})
|
||||||
|
.valueChanges
|
||||||
|
}
|
||||||
|
|
||||||
|
createCategory(category: Category) {
|
||||||
|
console.log(CREATE_CATEGORY(category));
|
||||||
|
return this.apollo
|
||||||
|
.mutate<any>({
|
||||||
|
mutation: CREATE_CATEGORY(category),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCategory(category: Category) {
|
||||||
|
console.log(UPDATE_CATEGORY(category));
|
||||||
|
return this.apollo
|
||||||
|
.mutate({
|
||||||
|
mutation: UPDATE_CATEGORY(category),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/app/admin/category/graphql/mutations.ts
Normal file
50
src/app/admin/category/graphql/mutations.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { gql } from "apollo-angular";
|
||||||
|
import { Category } from "../category.model";
|
||||||
|
|
||||||
|
export const UPDATE_CATEGORY = (category: Category) => gql`
|
||||||
|
mutation UpdateCategory {
|
||||||
|
updateCategory(
|
||||||
|
data: {
|
||||||
|
name: { set: "${category.name}" }
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
id: "${category.id}"
|
||||||
|
}) {
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
name
|
||||||
|
updatedAt
|
||||||
|
SubCategory {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
_count {
|
||||||
|
Product
|
||||||
|
SubCategory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const buildSubCategoryWhere = (id: string) => {
|
||||||
|
return `{ id: "${id}" }`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CREATE_CATEGORY = (category: Category) => gql`
|
||||||
|
mutation CreateCategory {
|
||||||
|
createCategory(data: { name: "${category.name}" }) {
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
name
|
||||||
|
updatedAt
|
||||||
|
SubCategory {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
_count {
|
||||||
|
Product
|
||||||
|
SubCategory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
36
src/app/admin/category/graphql/queries.ts
Normal file
36
src/app/admin/category/graphql/queries.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { gql } from "apollo-angular";
|
||||||
|
|
||||||
|
export const LIST_CATEGORIES = () => gql`
|
||||||
|
query ListCategorys {
|
||||||
|
listCategorys {
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
name
|
||||||
|
updatedAt
|
||||||
|
SubCategory {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const FIND_UNIQUE_CATEGORY = (id: string) =>
|
||||||
|
gql`
|
||||||
|
query FindUniqueCategory {
|
||||||
|
findUniqueCategory(where: { id: "${id}" }) {
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
name
|
||||||
|
updatedAt
|
||||||
|
SubCategory {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
_count {
|
||||||
|
Product
|
||||||
|
SubCategory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
7
src/app/admin/chat/chat-count.model.ts
Normal file
7
src/app/admin/chat/chat-count.model.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
export class ChatCount {
|
||||||
|
messages?: number;
|
||||||
|
|
||||||
|
constructor(){
|
||||||
|
this.messages = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<nb-card>
|
||||||
|
<nb-card-header>
|
||||||
|
Categories
|
||||||
|
</nb-card-header>
|
||||||
|
|
||||||
|
<nb-card-body>
|
||||||
|
<ng2-smart-table [settings]="settings" [source]="source" (edit)="onEdit($event)" (userRowSelect)="onEdit($event)">
|
||||||
|
</ng2-smart-table>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
@import '../../../@theme/styles/themes';
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
nb-card {
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
71
src/app/admin/chat/chat-messages/chat-messages.component.ts
Normal file
71
src/app/admin/chat/chat-messages/chat-messages.component.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
|
import { LocalDataSource } from "ng2-smart-table";
|
||||||
|
import { ChatService } from "../chat.service";
|
||||||
|
import { Router } from "@angular/router";
|
||||||
|
import { Chat } from "../chat.model";
|
||||||
|
import { Subject } from "rxjs";
|
||||||
|
import { takeUntil, tap } from "rxjs/operators";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "ngx-chat-messages",
|
||||||
|
templateUrl: "./chat-messages.component.html",
|
||||||
|
styleUrls: ["./chat-messages.component.scss"],
|
||||||
|
})
|
||||||
|
export class ChatMessageComponent implements OnInit, OnDestroy {
|
||||||
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
mode: 'external',
|
||||||
|
actions: {
|
||||||
|
add: false,
|
||||||
|
delete: false,
|
||||||
|
},
|
||||||
|
edit: {
|
||||||
|
editButtonContent: '<i class="nb-edit"></i>',
|
||||||
|
saveButtonContent: '<i class="nb-checkmark"></i>',
|
||||||
|
cancelButtonContent: '<i class="nb-close"></i>',
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
id: {
|
||||||
|
title: "ID",
|
||||||
|
type: "string",
|
||||||
|
editable: false,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
title: "Name",
|
||||||
|
type: "string",
|
||||||
|
editable: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
source: LocalDataSource = new LocalDataSource();
|
||||||
|
loading: boolean = true;
|
||||||
|
brands: Chat[];
|
||||||
|
|
||||||
|
constructor(private brandService: ChatService, private router: Router) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.brandService.listChats()
|
||||||
|
.pipe(
|
||||||
|
tap(() => {
|
||||||
|
this.loading = true;
|
||||||
|
}),
|
||||||
|
takeUntil(this.destroy$)
|
||||||
|
).subscribe(({ data, loading }) => {
|
||||||
|
this.loading = loading;
|
||||||
|
this.brands = data.listChats;
|
||||||
|
this.source.load(this.brands);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
onEdit(event): void {
|
||||||
|
this.router.navigate(["admin", "brand", "edit", event.data.id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/app/admin/chat/chat-routing.module.ts
Normal file
21
src/app/admin/chat/chat-routing.module.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
|
||||||
|
import { ChatComponent } from './chat/chat.component';
|
||||||
|
import { ChatMessageComponent } from './chat-messages/chat-messages.component';
|
||||||
|
|
||||||
|
const routes: Routes = [{
|
||||||
|
path: '',
|
||||||
|
component: ChatComponent
|
||||||
|
}];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule],
|
||||||
|
})
|
||||||
|
export class ChatRoutingModule { }
|
||||||
|
|
||||||
|
export const routedComponents = [
|
||||||
|
ChatComponent,
|
||||||
|
ChatMessageComponent
|
||||||
|
];
|
||||||
16
src/app/admin/chat/chat.model.ts
Normal file
16
src/app/admin/chat/chat.model.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { ChatCount } from "./chat-count.model";
|
||||||
|
import { Message } from "./message.model";
|
||||||
|
import { User } from "./user.model";
|
||||||
|
|
||||||
|
export class Chat {
|
||||||
|
id!: string;
|
||||||
|
userFromId!: string;
|
||||||
|
userToId!: string;
|
||||||
|
createdAt!: Date;
|
||||||
|
isActive!: boolean;
|
||||||
|
userFrom?: User;
|
||||||
|
userTo?: User;
|
||||||
|
messages?: Array<Message>;
|
||||||
|
//review?: Review | null;
|
||||||
|
_count?: ChatCount;
|
||||||
|
}
|
||||||
49
src/app/admin/chat/chat.module.ts
Normal file
49
src/app/admin/chat/chat.module.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import {
|
||||||
|
NbActionsModule,
|
||||||
|
NbButtonModule,
|
||||||
|
NbCardModule,
|
||||||
|
NbCheckboxModule,
|
||||||
|
NbDatepickerModule,
|
||||||
|
NbIconModule,
|
||||||
|
NbInputModule,
|
||||||
|
NbRadioModule,
|
||||||
|
NbSelectModule,
|
||||||
|
NbUserModule,
|
||||||
|
NbTreeGridModule,
|
||||||
|
NbListModule
|
||||||
|
} from '@nebular/theme';
|
||||||
|
import { Ng2SmartTableModule } from 'ng2-smart-table';
|
||||||
|
|
||||||
|
import { ThemeModule } from '../../@theme/theme.module';
|
||||||
|
import { ChatRoutingModule, routedComponents } from './chat-routing.module';
|
||||||
|
import { ChatService } from './chat.service';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
NbCardModule,
|
||||||
|
NbTreeGridModule,
|
||||||
|
NbIconModule,
|
||||||
|
NbInputModule,
|
||||||
|
ThemeModule,
|
||||||
|
ChatRoutingModule,
|
||||||
|
Ng2SmartTableModule,
|
||||||
|
FormsModule,
|
||||||
|
NbButtonModule,
|
||||||
|
NbActionsModule,
|
||||||
|
NbUserModule,
|
||||||
|
NbCheckboxModule,
|
||||||
|
NbRadioModule,
|
||||||
|
NbDatepickerModule,
|
||||||
|
NbSelectModule,
|
||||||
|
NbListModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
...routedComponents
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
ChatService,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class ChatModule { }
|
||||||
36
src/app/admin/chat/chat.service.ts
Normal file
36
src/app/admin/chat/chat.service.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { Apollo } from 'apollo-angular';
|
||||||
|
import { FIND_UNIQUE_CHAT, LIST_CHATS } from './graphql/queries';
|
||||||
|
import { Chat } from './chat.model';
|
||||||
|
import { CREATE_CHAT } from './graphql/mutations';
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ChatService {
|
||||||
|
|
||||||
|
constructor(private readonly apollo: Apollo) {}
|
||||||
|
|
||||||
|
listChats(): Observable<any> {
|
||||||
|
return this.apollo
|
||||||
|
.watchQuery<Chat>({
|
||||||
|
query: LIST_CHATS(),
|
||||||
|
})
|
||||||
|
.valueChanges
|
||||||
|
}
|
||||||
|
|
||||||
|
findUniqueChat(id: Chat["id"]): Observable<any> {
|
||||||
|
return this.apollo
|
||||||
|
.watchQuery<Chat>({
|
||||||
|
query: FIND_UNIQUE_CHAT(id),
|
||||||
|
})
|
||||||
|
.valueChanges
|
||||||
|
}
|
||||||
|
|
||||||
|
createChat(category: Chat) {
|
||||||
|
return this.apollo
|
||||||
|
.mutate<any>({
|
||||||
|
mutation: CREATE_CHAT(category),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
58
src/app/admin/chat/chat/chat.component.html
Normal file
58
src/app/admin/chat/chat/chat.component.html
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<nb-card *ngIf="!loading">
|
||||||
|
<nb-card-header>
|
||||||
|
<nb-icon (click)="goBackToList()" [icon]="'arrow-ios-back-outline'" pack="eva"></nb-icon>
|
||||||
|
Brand {{ brand.id }}</nb-card-header>
|
||||||
|
<nb-card-body>
|
||||||
|
<div *ngIf="brand.id" class="summary-container">
|
||||||
|
<div>
|
||||||
|
<div>Created At</div>
|
||||||
|
<div class="h6">{{ brand.createdAt | date: 'dd:MM:YYYY HH:mm:ss' }}</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>Products Count</div>
|
||||||
|
<div class="h6">{{ brand._count?.products || 0 }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form (ngSubmit)="onSubmit(brandForm.form)" #brandForm="ngForm">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="brandName" class="label">Name</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
nbInput
|
||||||
|
fullWidth
|
||||||
|
id="brandName"
|
||||||
|
placeholder="Name"
|
||||||
|
required
|
||||||
|
[(ngModel)]="brand.name"
|
||||||
|
name="name"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group buttons-row">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
nbButton
|
||||||
|
status="primary"
|
||||||
|
[disabled]="!brandForm.form.valid"
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
*ngIf="brand.id"
|
||||||
|
type="button"
|
||||||
|
(click)="onDelete()"
|
||||||
|
nbButton
|
||||||
|
status="danger"
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</nb-card-body>
|
||||||
|
</nb-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
43
src/app/admin/chat/chat/chat.component.scss
Normal file
43
src/app/admin/chat/chat/chat.component.scss
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
@import "../../../@theme/styles/themes";
|
||||||
|
|
||||||
|
nb-checkbox {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb-icon {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-inline [fullWidth] {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-inline > * {
|
||||||
|
margin: 0 1.5rem 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nb-card.inline-form-card nb-card-body {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include nb-install-component() {
|
||||||
|
.summary-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex: 1;
|
||||||
|
background-color: nb-theme(background-basic-color-2);
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 1.5rem 4rem 1rem;
|
||||||
|
border: 1px solid nb-theme(border-basic-color-3);
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-row {
|
||||||
|
margin: -0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button[nbButton] {
|
||||||
|
margin: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/app/admin/chat/chat/chat.component.ts
Normal file
32
src/app/admin/chat/chat/chat.component.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
|
import { ChatService } from "../chat.service";
|
||||||
|
import { Chat } from "../chat.model";
|
||||||
|
import { Subject } from "rxjs";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "ngx-chat",
|
||||||
|
styleUrls: ["./chat.component.scss"],
|
||||||
|
templateUrl: "./chat.component.html",
|
||||||
|
})
|
||||||
|
export class ChatComponent implements OnInit, OnDestroy {
|
||||||
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
|
|
||||||
|
id: string;
|
||||||
|
loading: boolean = false;
|
||||||
|
chat: Chat;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private chatService: ChatService
|
||||||
|
) {
|
||||||
|
this.chat = new Chat();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
console.log('init')
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
47
src/app/admin/chat/graphql/mutations.ts
Normal file
47
src/app/admin/chat/graphql/mutations.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { gql } from "apollo-angular";
|
||||||
|
import { Chat } from "../chat.model";
|
||||||
|
|
||||||
|
export const UPDATE_CHAT = (chat: Chat) => gql`
|
||||||
|
mutation UpdateChat {
|
||||||
|
updateChat(
|
||||||
|
data: {
|
||||||
|
name: { set: "${chat.id}" }
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
id: "${chat.id}"
|
||||||
|
}) {
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
name
|
||||||
|
updatedAt
|
||||||
|
_count {
|
||||||
|
products
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CREATE_CHAT = (chat: Chat) => gql`
|
||||||
|
mutation CreateChat {
|
||||||
|
createChat(data: { name: "${chat.id}" }) {
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
name
|
||||||
|
updatedAt
|
||||||
|
_count {
|
||||||
|
products
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const DELETE_CHAT = (id: string) => gql`
|
||||||
|
mutation DeleteChat {
|
||||||
|
deleteChat(where: { id: "${id}" }) {
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
name
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
27
src/app/admin/chat/graphql/queries.ts
Normal file
27
src/app/admin/chat/graphql/queries.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { gql } from "apollo-angular";
|
||||||
|
|
||||||
|
export const LIST_CHATS = () => gql`
|
||||||
|
query ListBrands {
|
||||||
|
listBrands {
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
name
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const FIND_UNIQUE_CHAT = (id: string) =>
|
||||||
|
gql`
|
||||||
|
query FindUniqueBrand {
|
||||||
|
findUniqueBrand(where: { id: "${id}" }) {
|
||||||
|
createdAt
|
||||||
|
id
|
||||||
|
name
|
||||||
|
updatedAt
|
||||||
|
_count {
|
||||||
|
products
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
14
src/app/admin/chat/message.model.ts
Normal file
14
src/app/admin/chat/message.model.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { Chat } from "./chat.model";
|
||||||
|
import { User } from "./user.model";
|
||||||
|
|
||||||
|
export class Message {
|
||||||
|
id!: string;
|
||||||
|
userId!: string;
|
||||||
|
chatId!: string;
|
||||||
|
text!: string;
|
||||||
|
imgUrl!: string | null;
|
||||||
|
createdAt!: Date;
|
||||||
|
isRead!: boolean;
|
||||||
|
user?: User;
|
||||||
|
chat?: Chat;
|
||||||
|
}
|
||||||
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