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
17854
package-lock.json
generated
17854
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-dynamic": "^15.2.10",
|
||||
"@angular/router": "^15.2.10",
|
||||
"@apollo/client": "^3.11.4",
|
||||
"@asymmetrik/ngx-leaflet": "3.0.1",
|
||||
"@nebular/auth": "11.0.1",
|
||||
"@nebular/eva-icons": "11.0.1",
|
||||
|
|
@ -47,6 +48,7 @@
|
|||
"@nebular/theme": "11.0.1",
|
||||
"@swimlane/ngx-charts": "^14.0.0",
|
||||
"angular2-chartjs": "0.4.1",
|
||||
"apollo-angular": "^7.0.2",
|
||||
"bootstrap": "4.3.1",
|
||||
"chart.js": "2.7.1",
|
||||
"ckeditor": "4.7.3",
|
||||
|
|
@ -54,6 +56,7 @@
|
|||
"core-js": "2.5.1",
|
||||
"echarts": "^4.9.0",
|
||||
"eva-icons": "^1.1.3",
|
||||
"graphql": "^16.9.0",
|
||||
"intl": "1.2.5",
|
||||
"ionicons": "2.0.1",
|
||||
"leaflet": "1.2.0",
|
||||
|
|
@ -62,7 +65,6 @@
|
|||
"ng2-completer": "^9.0.1",
|
||||
"ng2-smart-table": "^1.6.0",
|
||||
"ngx-echarts": "^4.2.2",
|
||||
"node-sass": "^4.14.1",
|
||||
"normalize.css": "6.0.0",
|
||||
"pace-js": "1.0.2",
|
||||
"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="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>
|
||||
</a>
|
||||
<a class="logo" href="#" (click)="navigateHome()">ngx-<span>admin</span></a>
|
||||
<a class="logo" href="#" (click)="navigateHome()"
|
||||
><span>Desapegrow</span></a
|
||||
>
|
||||
</div>
|
||||
<nb-select [selected]="currentTheme" (selectedChange)="changeTheme($event)" status="primary">
|
||||
<nb-option *ngFor="let theme of themes" [value]="theme.value"> {{ theme.name }}</nb-option>
|
||||
<nb-select
|
||||
[selected]="currentTheme"
|
||||
(selectedChange)="changeTheme($event)"
|
||||
status="primary"
|
||||
>
|
||||
<nb-option *ngFor="let theme of themes" [value]="theme.value">
|
||||
{{ theme.name }}</nb-option
|
||||
>
|
||||
</nb-select>
|
||||
</div>
|
||||
|
||||
<div class="header-container">
|
||||
<nb-actions size="small">
|
||||
|
||||
<nb-action class="control-item">
|
||||
<nb-search type="rotate-layout"></nb-search>
|
||||
</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="message-circle-outline"
|
||||
badgeDot
|
||||
badgeStatus="danger"
|
||||
badgePosition="top right"
|
||||
(click)="goToChat()"
|
||||
></nb-action>
|
||||
<nb-action class="user-action" *nbIsGranted="['view', 'user']">
|
||||
<nb-user [nbContextMenu]="userMenu"
|
||||
<nb-user
|
||||
[nbContextMenu]="userMenu"
|
||||
[onlyPicture]="userPictureOnly"
|
||||
[name]="user?.name"
|
||||
[picture]="user?.picture">
|
||||
[picture]="user?.picture"
|
||||
>
|
||||
</nb-user>
|
||||
</nb-action>
|
||||
</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 { UserData } from '../../../@core/data/users';
|
||||
import { LayoutService } from '../../../@core/utils';
|
||||
import { map, takeUntil } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-header',
|
||||
|
|
@ -12,7 +13,7 @@ import { Subject } from 'rxjs';
|
|||
templateUrl: './header.component.html',
|
||||
})
|
||||
export class HeaderComponent implements OnInit, OnDestroy {
|
||||
|
||||
@Input() menu: boolean = true;
|
||||
private destroy$: Subject<void> = new Subject<void>();
|
||||
userPictureOnly: boolean = false;
|
||||
user: any;
|
||||
|
|
@ -45,7 +46,8 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
|||
private themeService: NbThemeService,
|
||||
private userService: UserData,
|
||||
private layoutService: LayoutService,
|
||||
private breakpointService: NbMediaBreakpointsService) {
|
||||
private breakpointService: NbMediaBreakpointsService,
|
||||
private router: Router) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
|
@ -91,4 +93,11 @@ export class HeaderComponent implements OnInit, OnDestroy {
|
|||
this.menuService.navigateHome();
|
||||
return false;
|
||||
}
|
||||
|
||||
goToChat() {
|
||||
this.router.navigate([
|
||||
"admin",
|
||||
"chat"
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-one-column-layout',
|
||||
|
|
@ -6,10 +6,10 @@ import { Component } from '@angular/core';
|
|||
template: `
|
||||
<nb-layout windowMode>
|
||||
<nb-layout-header fixed>
|
||||
<ngx-header></ngx-header>
|
||||
<ngx-header [menu]="menu"></ngx-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>
|
||||
</nb-sidebar>
|
||||
|
||||
|
|
@ -23,4 +23,6 @@ import { Component } from '@angular/core';
|
|||
</nb-layout>
|
||||
`,
|
||||
})
|
||||
export class OneColumnLayoutComponent {}
|
||||
export class OneColumnLayoutComponent {
|
||||
@Input() menu: boolean = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
NbSelectModule,
|
||||
NbIconModule,
|
||||
NbThemeModule,
|
||||
NbCardModule,
|
||||
} from '@nebular/theme';
|
||||
import { NbEvaIconsModule } from '@nebular/eva-icons';
|
||||
import { NbSecurityModule } from '@nebular/security';
|
||||
|
|
@ -38,6 +39,7 @@ import { DEFAULT_THEME } from './styles/theme.default';
|
|||
import { COSMIC_THEME } from './styles/theme.cosmic';
|
||||
import { CORPORATE_THEME } from './styles/theme.corporate';
|
||||
import { DARK_THEME } from './styles/theme.dark';
|
||||
import { DialogPromptComponent } from './components/dialogs/dialog-name-prompt/dialog-prompt.component';
|
||||
|
||||
const NB_MODULES = [
|
||||
NbLayoutModule,
|
||||
|
|
@ -52,6 +54,7 @@ const NB_MODULES = [
|
|||
NbSelectModule,
|
||||
NbIconModule,
|
||||
NbEvaIconsModule,
|
||||
NbCardModule,
|
||||
];
|
||||
const COMPONENTS = [
|
||||
HeaderComponent,
|
||||
|
|
@ -61,6 +64,7 @@ const COMPONENTS = [
|
|||
OneColumnLayoutComponent,
|
||||
ThreeColumnsLayoutComponent,
|
||||
TwoColumnsLayoutComponent,
|
||||
DialogPromptComponent
|
||||
];
|
||||
const PIPES = [
|
||||
CapitalizePipe,
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
|||
{
|
||||
title: 'E-commerce',
|
||||
icon: 'shopping-cart-outline',
|
||||
link: '/pages/dashboard',
|
||||
link: '/admin/dashboard',
|
||||
home: true,
|
||||
},
|
||||
{
|
||||
title: 'IoT Dashboard',
|
||||
icon: 'home-outline',
|
||||
link: '/pages/iot-dashboard',
|
||||
link: '/admin/iot-dashboard',
|
||||
},
|
||||
{
|
||||
title: 'FEATURES',
|
||||
|
|
@ -22,24 +22,24 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
|||
children: [
|
||||
{
|
||||
title: 'Stepper',
|
||||
link: '/pages/layout/stepper',
|
||||
link: '/admin/layout/stepper',
|
||||
},
|
||||
{
|
||||
title: 'List',
|
||||
link: '/pages/layout/list',
|
||||
link: '/admin/layout/list',
|
||||
},
|
||||
{
|
||||
title: 'Infinite List',
|
||||
link: '/pages/layout/infinite-list',
|
||||
link: '/admin/layout/infinite-list',
|
||||
},
|
||||
{
|
||||
title: 'Accordion',
|
||||
link: '/pages/layout/accordion',
|
||||
link: '/admin/layout/accordion',
|
||||
},
|
||||
{
|
||||
title: 'Tabs',
|
||||
pathMatch: 'prefix',
|
||||
link: '/pages/layout/tabs',
|
||||
link: '/admin/layout/tabs',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -49,42 +49,98 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
|||
children: [
|
||||
{
|
||||
title: 'Form Inputs',
|
||||
link: '/pages/forms/inputs',
|
||||
link: '/admin/forms/inputs',
|
||||
},
|
||||
{
|
||||
title: 'Form Layouts',
|
||||
link: '/pages/forms/layouts',
|
||||
link: '/admin/forms/layouts',
|
||||
},
|
||||
{
|
||||
title: 'Buttons',
|
||||
link: '/pages/forms/buttons',
|
||||
link: '/admin/forms/buttons',
|
||||
},
|
||||
{
|
||||
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',
|
||||
icon: 'keypad-outline',
|
||||
link: '/pages/ui-features',
|
||||
link: '/admin/ui-features',
|
||||
children: [
|
||||
{
|
||||
title: 'Grid',
|
||||
link: '/pages/ui-features/grid',
|
||||
link: '/admin/ui-features/grid',
|
||||
},
|
||||
{
|
||||
title: 'Icons',
|
||||
link: '/pages/ui-features/icons',
|
||||
link: '/admin/ui-features/icons',
|
||||
},
|
||||
{
|
||||
title: 'Typography',
|
||||
link: '/pages/ui-features/typography',
|
||||
link: '/admin/ui-features/typography',
|
||||
},
|
||||
{
|
||||
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: [
|
||||
{
|
||||
title: 'Dialog',
|
||||
link: '/pages/modal-overlays/dialog',
|
||||
link: '/admin/modal-overlays/dialog',
|
||||
},
|
||||
{
|
||||
title: 'Window',
|
||||
link: '/pages/modal-overlays/window',
|
||||
link: '/admin/modal-overlays/window',
|
||||
},
|
||||
{
|
||||
title: 'Popover',
|
||||
link: '/pages/modal-overlays/popover',
|
||||
link: '/admin/modal-overlays/popover',
|
||||
},
|
||||
{
|
||||
title: 'Toastr',
|
||||
link: '/pages/modal-overlays/toastr',
|
||||
link: '/admin/modal-overlays/toastr',
|
||||
},
|
||||
{
|
||||
title: 'Tooltip',
|
||||
link: '/pages/modal-overlays/tooltip',
|
||||
link: '/admin/modal-overlays/tooltip',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -120,27 +176,27 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
|||
children: [
|
||||
{
|
||||
title: 'Calendar',
|
||||
link: '/pages/extra-components/calendar',
|
||||
link: '/admin/extra-components/calendar',
|
||||
},
|
||||
{
|
||||
title: 'Progress Bar',
|
||||
link: '/pages/extra-components/progress-bar',
|
||||
link: '/admin/extra-components/progress-bar',
|
||||
},
|
||||
{
|
||||
title: 'Spinner',
|
||||
link: '/pages/extra-components/spinner',
|
||||
link: '/admin/extra-components/spinner',
|
||||
},
|
||||
{
|
||||
title: 'Alert',
|
||||
link: '/pages/extra-components/alert',
|
||||
link: '/admin/extra-components/alert',
|
||||
},
|
||||
{
|
||||
title: 'Calendar Kit',
|
||||
link: '/pages/extra-components/calendar-kit',
|
||||
link: '/admin/extra-components/calendar-kit',
|
||||
},
|
||||
{
|
||||
title: 'Chat',
|
||||
link: '/pages/extra-components/chat',
|
||||
link: '/admin/extra-components/chat',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -150,19 +206,19 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
|||
children: [
|
||||
{
|
||||
title: 'Google Maps',
|
||||
link: '/pages/maps/gmaps',
|
||||
link: '/admin/maps/gmaps',
|
||||
},
|
||||
{
|
||||
title: 'Leaflet Maps',
|
||||
link: '/pages/maps/leaflet',
|
||||
link: '/admin/maps/leaflet',
|
||||
},
|
||||
{
|
||||
title: 'Bubble Maps',
|
||||
link: '/pages/maps/bubble',
|
||||
link: '/admin/maps/bubble',
|
||||
},
|
||||
{
|
||||
title: 'Search Maps',
|
||||
link: '/pages/maps/searchmap',
|
||||
link: '/admin/maps/searchmap',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -172,15 +228,15 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
|||
children: [
|
||||
{
|
||||
title: 'Echarts',
|
||||
link: '/pages/charts/echarts',
|
||||
link: '/admin/charts/echarts',
|
||||
},
|
||||
{
|
||||
title: 'Charts.js',
|
||||
link: '/pages/charts/chartjs',
|
||||
link: '/admin/charts/chartjs',
|
||||
},
|
||||
{
|
||||
title: 'D3',
|
||||
link: '/pages/charts/d3',
|
||||
link: '/admin/charts/d3',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -190,11 +246,11 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
|||
children: [
|
||||
{
|
||||
title: 'TinyMCE',
|
||||
link: '/pages/editors/tinymce',
|
||||
link: '/admin/editors/tinymce',
|
||||
},
|
||||
{
|
||||
title: 'CKEditor',
|
||||
link: '/pages/editors/ckeditor',
|
||||
link: '/admin/editors/ckeditor',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -204,11 +260,11 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
|||
children: [
|
||||
{
|
||||
title: 'Smart Table',
|
||||
link: '/pages/tables/smart-table',
|
||||
link: '/admin/tables/smart-table',
|
||||
},
|
||||
{
|
||||
title: 'Tree Grid',
|
||||
link: '/pages/tables/tree-grid',
|
||||
link: '/admin/tables/tree-grid',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -218,7 +274,7 @@ export const MENU_ITEMS: NbMenuItem[] = [
|
|||
children: [
|
||||
{
|
||||
title: '404',
|
||||
link: '/pages/miscellaneous/404',
|
||||
link: '/admin/miscellaneous/404',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { PagesComponent } from './pages.component';
|
||||
import { AdminComponent } from './admin.component';
|
||||
import { DashboardComponent } from './dashboard/dashboard.component';
|
||||
import { ECommerceComponent } from './e-commerce/e-commerce.component';
|
||||
import { NotFoundComponent } from './miscellaneous/not-found/not-found.component';
|
||||
|
||||
const routes: Routes = [{
|
||||
path: '',
|
||||
component: PagesComponent,
|
||||
component: AdminComponent,
|
||||
children: [
|
||||
{
|
||||
path: 'dashboard',
|
||||
|
|
@ -63,6 +63,31 @@ const routes: Routes = [{
|
|||
loadChildren: () => import('./tables/tables.module')
|
||||
.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',
|
||||
loadChildren: () => import('./miscellaneous/miscellaneous.module')
|
||||
|
|
@ -84,5 +109,5 @@ const routes: Routes = [{
|
|||
imports: [RouterModule.forChild(routes)],
|
||||
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 { MENU_ITEMS } from './pages-menu';
|
||||
import { MENU_ITEMS } from './admin-menu';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-pages',
|
||||
styleUrls: ['pages.component.scss'],
|
||||
selector: 'ngx-admin',
|
||||
styleUrls: ['admin.component.scss'],
|
||||
template: `
|
||||
<ngx-one-column-layout>
|
||||
<nb-menu [items]="menu"></nb-menu>
|
||||
|
|
@ -12,7 +12,7 @@ import { MENU_ITEMS } from './pages-menu';
|
|||
</ngx-one-column-layout>
|
||||
`,
|
||||
})
|
||||
export class PagesComponent {
|
||||
export class AdminComponent {
|
||||
|
||||
menu = MENU_ITEMS;
|
||||
}
|
||||
|
|
@ -2,24 +2,30 @@ import { NgModule } from '@angular/core';
|
|||
import { NbMenuModule } from '@nebular/theme';
|
||||
|
||||
import { ThemeModule } from '../@theme/theme.module';
|
||||
import { PagesComponent } from './pages.component';
|
||||
import { AdminComponent } from './admin.component';
|
||||
import { DashboardModule } from './dashboard/dashboard.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 { CategoryModule } from './category/category.module';
|
||||
import { SubCategoryModule } from './sub-category/sub-category.module';
|
||||
import { BrandModule } from './brand/brand.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
PagesRoutingModule,
|
||||
AdminRoutingModule,
|
||||
ThemeModule,
|
||||
NbMenuModule,
|
||||
DashboardModule,
|
||||
ECommerceModule,
|
||||
MiscellaneousModule,
|
||||
CategoryModule,
|
||||
SubCategoryModule,
|
||||
BrandModule
|
||||
],
|
||||
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