Commit da09ad77 by Ooh-Ao

emport import template

parent 2b7a1d84
{ {
"$schema": "./node_modules/@angular/cli/lib/config/schema.json", "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"cli": { "cli": {
"analytics": "9ea24997-323a-4ccd-9e9d-ab32af54a3f0" "analytics": false
}, },
"version": 1, "version": 1,
"newProjectRoot": "projects", "newProjectRoot": "projects",
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
"build": "ng build", "build": "ng build",
"test": "ng test", "test": "ng test",
"lint": "ng lint", "lint": "ng lint",
"e2e": "ng e2e" "e2e": "ng e2e",
"postinstall": "ngcc"
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
...@@ -22,12 +23,49 @@ ...@@ -22,12 +23,49 @@
"@angular/platform-browser-dynamic": "^12.0.2", "@angular/platform-browser-dynamic": "^12.0.2",
"@angular/platform-server": "^12.0.2", "@angular/platform-server": "^12.0.2",
"@angular/router": "^12.0.2", "@angular/router": "^12.0.2",
"@iplab/ngx-file-upload": "^2.0.6",
"@ng-bootstrap/ng-bootstrap": "^9.0.2", "@ng-bootstrap/ng-bootstrap": "^9.0.2",
"@ngx-translate/core": "^13.0.0", "@ngx-translate/core": "^13.0.0",
"@ngx-translate/http-loader": "^6.0.0", "@ngx-translate/http-loader": "^6.0.0",
"angular-notifier": "^6.0.1", "@swimlane/ngx-charts": "^16.0.0",
"@swimlane/ngx-datatable": "^17.0.0",
"@types/quill": "1.3.6",
"angular-calendar": "^0.28.16",
"angular-datatables": "^11.1.1",
"angular-feather": "^6.0.10",
"angular-notifier": "^6.0.1",
"angularx-flatpickr": "^6.5.1",
"apexcharts": "^3.25.0",
"bootstrap": "^4.5.0", "bootstrap": "^4.5.0",
"c3": "^0.7.18",
"calendar-utils": "^0.8.1",
"chart.js": "^2.9.3",
"chartist": "^0.11.4",
"core-js": "^3.6.5",
"crossvent": "^1.5.5",
"d3": "^4.8.0",
"d3-array": "^2.7.1",
"datatables.net": "^1.10.20",
"datatables.net-dt": "^1.10.20",
"date-fns": "^2.14.0",
"dom-autoscroller": "^2.3.4",
"dom-plane": "^1.0.2",
"dom-set": "^1.1.1",
"flatpickr": "^4.6.6",
"handlebars": "^4.7.7",
"lodash": "^4.17.19",
"ng-apexcharts": "^1.5.6",
"ng-chartist": "^4.1.0",
"ng-multiselect-dropdown": "^0.2.10",
"ng2-archwizard": "^2.1.0",
"ng2-charts": "^2.3.2",
"ng2-search-filter": "^0.5.1",
"ngx-custom-validators": "8.0.0",
"ngx-perfect-scrollbar": "^9.0.0", "ngx-perfect-scrollbar": "^9.0.0",
"ngx-quill": "^12.0.1",
"ngx-toastr": "^12.0.0",
"pace-js": "^1.0.2",
"quill": "^1.3.7",
"rxjs": "^6.6.3", "rxjs": "^6.6.3",
"rxjs-compat": "^6.5.4", "rxjs-compat": "^6.5.4",
"sass": "^1.29.0", "sass": "^1.29.0",
...@@ -63,4 +101,4 @@ ...@@ -63,4 +101,4 @@
"peerDependencies": { "peerDependencies": {
"tslib": "1.10.0" "tslib": "1.10.0"
} }
} }
\ No newline at end of file
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; import { Routes } from '@angular/router';
import { FullComponent } from './layouts/full/full.component'; import { FullComponent } from './layouts/full/full.component';
import { BlankComponent } from './layouts/blank/blank.component'; import { BlankComponent } from './layouts/blank/blank.component';
import { LoginComponent } from './login/login.component';
import { AuthGuard } from './auth.guard'; import { AuthGuard } from './auth.guard';
export const Approutes: Routes = [ export const Approutes: Routes = [
{ {
path: '', path: '',
component: FullComponent, component: FullComponent,
canActivate: [AuthGuard], // canActivate: [AuthGuard],
children: [ children: [
{ path: '', redirectTo: '/login', pathMatch: 'full' }, { path: '', redirectTo: '/authentication/login', pathMatch: 'full' },
{ {
path: 'starter', path: 'starter',
loadChildren: () => import('./starter/starter.module').then(m => m.StarterModule) loadChildren: () => import('./starter/starter.module').then(m => m.StarterModule)
}, },
{ {
path: 'component', path: 'component',
loadChildren: () => import('./component/component.module').then(m => m.ComponentsModule) loadChildren: () => import('./component/component.module').then(m => m.ComponentsModule)
} },
] { path: 'apps', loadChildren: () => import('./apps/apps.module').then(m => m.AppsModule) },
},
{
path: '**',
redirectTo: '/login'
},
{
path: 'login',
component: LoginComponent,
}
];
]
},
{
path: '',
component: BlankComponent,
children: [
{
path: 'authentication',
loadChildren:
() => import('./authentication/authentication.module').then(m => m.AuthenticationModule)
}
]
},
{
path: '**',
redirectTo: '/authentication/404'
}
];
import * as $ from 'jquery';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { CommonModule } from '@angular/common'; import {
CommonModule
} from '@angular/common';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule, HttpClient } from '@angular/common/http'; import { HttpClientModule } from '@angular/common/http';
import { Routes, RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
//import { AgmCoreModule } from '@agm/core';
import { DataTablesModule } from 'angular-datatables';
import { NgMultiSelectDropDownModule } from 'ng-multiselect-dropdown';
import { Ng2SearchPipeModule } from 'ng2-search-filter';
import { ToastrModule } from 'ngx-toastr';
import { FullComponent } from './layouts/full/full.component'; import { FullComponent } from './layouts/full/full.component';
import { BlankComponent } from './layouts/blank/blank.component'; import { BlankComponent } from './layouts/blank/blank.component';
import { FeatherModule } from 'angular-feather';
import { allIcons } from 'angular-feather/icons';
import { VerticalNavigationComponent } from './shared/vertical-header/vertical-navigation.component'; import { VerticalNavigationComponent } from './shared/vertical-header/vertical-navigation.component';
import { VerticalSidebarComponent } from './shared/vertical-sidebar/vertical-sidebar.component'; import { VerticalSidebarComponent } from './shared/vertical-sidebar/vertical-sidebar.component';
...@@ -18,12 +25,9 @@ import { BreadcrumbComponent } from './shared/breadcrumb/breadcrumb.component'; ...@@ -18,12 +25,9 @@ import { BreadcrumbComponent } from './shared/breadcrumb/breadcrumb.component';
import { HorizontalNavigationComponent } from './shared/horizontal-header/horizontal-navigation.component'; import { HorizontalNavigationComponent } from './shared/horizontal-header/horizontal-navigation.component';
import { HorizontalSidebarComponent } from './shared/horizontal-sidebar/horizontal-sidebar.component'; import { HorizontalSidebarComponent } from './shared/horizontal-sidebar/horizontal-sidebar.component';
import { Approutes } from './app-routing.module'; import { Approutes } from './app-routing.module';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { SpinnerComponent } from './shared/spinner.component'; import { SpinnerComponent } from './shared/spinner.component';
import { LoginComponent } from './login/login.component';
import { AuthGuard } from './auth.guard';
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar'; import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
import { PERFECT_SCROLLBAR_CONFIG } from 'ngx-perfect-scrollbar'; import { PERFECT_SCROLLBAR_CONFIG } from 'ngx-perfect-scrollbar';
...@@ -31,6 +35,7 @@ import { PerfectScrollbarConfigInterface } from 'ngx-perfect-scrollbar'; ...@@ -31,6 +35,7 @@ import { PerfectScrollbarConfigInterface } from 'ngx-perfect-scrollbar';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader'; import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { HttpClient } from '@angular/common/http';
export function HttpLoaderFactory(http: HttpClient) { export function HttpLoaderFactory(http: HttpClient) {
...@@ -39,11 +44,13 @@ export function HttpLoaderFactory(http: HttpClient) { ...@@ -39,11 +44,13 @@ export function HttpLoaderFactory(http: HttpClient) {
const DEFAULT_PERFECT_SCROLLBAR_CONFIG: PerfectScrollbarConfigInterface = { const DEFAULT_PERFECT_SCROLLBAR_CONFIG: PerfectScrollbarConfigInterface = {
suppressScrollX: true, suppressScrollX: true,
wheelSpeed: 2, wheelSpeed: 1,
wheelPropagation: true, wheelPropagation: true,
minScrollbarLength: 20 minScrollbarLength: 20
}; };
// Select some icons (use an object, not an array)
@NgModule({ @NgModule({
declarations: [ declarations: [
...@@ -55,19 +62,27 @@ const DEFAULT_PERFECT_SCROLLBAR_CONFIG: PerfectScrollbarConfigInterface = { ...@@ -55,19 +62,27 @@ const DEFAULT_PERFECT_SCROLLBAR_CONFIG: PerfectScrollbarConfigInterface = {
BreadcrumbComponent, BreadcrumbComponent,
VerticalSidebarComponent, VerticalSidebarComponent,
HorizontalNavigationComponent, HorizontalNavigationComponent,
HorizontalSidebarComponent, HorizontalSidebarComponent
LoginComponent
], ],
imports: [ imports: [
CommonModule, CommonModule,
BrowserModule, BrowserModule,
BrowserAnimationsModule, BrowserAnimationsModule,
FormsModule, FormsModule,
ToastrModule.forRoot(),
FeatherModule.pick(allIcons),
ReactiveFormsModule,
DataTablesModule,
HttpClientModule, HttpClientModule,
NgbModule, NgbModule,
RouterModule.forRoot(Approutes), FeatherModule,
Ng2SearchPipeModule,
RouterModule.forRoot(Approutes, { relativeLinkResolution: 'legacy' }),
PerfectScrollbarModule, PerfectScrollbarModule,
HttpClientModule, NgMultiSelectDropDownModule.forRoot(),
// AgmCoreModule.forRoot({ apiKey: 'AIzaSyDoliAneRffQDyA7Ul9cDk3tLe7vaU4yP8' }),
TranslateModule.forRoot({ TranslateModule.forRoot({
loader: { loader: {
provide: TranslateLoader, provide: TranslateLoader,
...@@ -80,8 +95,7 @@ const DEFAULT_PERFECT_SCROLLBAR_CONFIG: PerfectScrollbarConfigInterface = { ...@@ -80,8 +95,7 @@ const DEFAULT_PERFECT_SCROLLBAR_CONFIG: PerfectScrollbarConfigInterface = {
{ {
provide: PERFECT_SCROLLBAR_CONFIG, provide: PERFECT_SCROLLBAR_CONFIG,
useValue: DEFAULT_PERFECT_SCROLLBAR_CONFIG useValue: DEFAULT_PERFECT_SCROLLBAR_CONFIG
}, }
AuthGuard
], ],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
......
import { NgModule } from '@angular/core';
import { CommonModule, DatePipe, DecimalPipe } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { CalendarModule, DateAdapter } from 'angular-calendar';
import { FlatpickrModule } from 'angularx-flatpickr';
import { adapterFactory } from 'angular-calendar/date-adapters/date-fns';
import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { HttpClientModule } from '@angular/common/http';
import { QuillModule } from 'ngx-quill';
import { Ng2SearchPipeModule } from 'ng2-search-filter';
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
import { DragDropModule } from '@angular/cdk/drag-drop';
import { FeatherModule } from 'angular-feather';
import { Camera, Heart, Github, Activity, Airplay, AlertCircle, AlertOctagon, AlertTriangle, AlignCenter, AlignJustify, AlignLeft, AlignRight, Anchor, Aperture, Archive, ArrowDown, ArrowDownCircle, ArrowDownLeft, ArrowDownRight, ArrowLeftCircle, ArrowLeft, ArrowRight, ArrowRightCircle, ArrowUp, ArrowUpCircle, ArrowUpLeft, ArrowUpRight, AtSign, Award, BarChart2, BarChart, BatteryCharging, Battery, BellOff, Bell, Bluetooth, Bold, BookOpen, Book, Bookmark, Box, Briefcase, Calendar, CameraOff, Cast, CheckCircle, CheckSquare, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ChevronsDown, ChevronsLeft, ChevronsRight, ChevronsUp, Chrome, Circle, Clipboard, Clock, CloudDrizzle, CloudLightning, CloudOff, CloudRain, Cloud, CloudSnow, Code, Codepen, Codesandbox, Coffee, Columns, Command, Compass, Copy, CornerDownLeft, CornerDownRight, CornerLeftDown, CornerLeftUp, CornerRightDown, CornerRightUp, CornerUpLeft, CornerUpRight, Cpu, CreditCard, Crop, Crosshair, Database, Delete, Disc, DollarSign, DownloadCloud, Download, Droplet, Edit, Edit2, Edit3, ExternalLink, EyeOff, Eye, Facebook, FastForward, Feather, Figma, FileMinus, FilePlus, FileText, File, Film, Filter, Flag, Folder, FolderMinus, FolderPlus, Framer, Frown, Gift, GitBranch, GitCommit, GitMerge, GitPullRequest, Gitlab, Globe, Grid, HardDrive, Hash, Headphones, HelpCircle, Hexagon, Home, MoreHorizontal, Image, Inbox, Info, Instagram, Italic, Key, Layers, Layout, LifeBuoy, Link, Link2, Linkedin, List, Loader, Lock, LogIn, LogOut, Mail, MapPin, Map, Maximize, Maximize2, Meh, Menu, MessageCircle, MessageSquare, Mic, MicOff, Minimize, Minimize2, MinusCircle, MinusSquare, Minus, Monitor, Moon, MoreVertical, MousePointer, Move, Music, Navigation, Navigation2, Octagon, Package, Paperclip, PauseCircle, Pause, PenTool, Percent, PhoneCall, PhoneForwarded, PhoneIncoming, PhoneMissed, Phone, PhoneOff, PhoneOutgoing, PieChart, Play, PlayCircle, Plus, PlusCircle, PlusSquare, Pocket, Power, Printer, Radio, RefreshCcw, RefreshCw, Repeat, Rewind, RotateCcw, RotateCw, Rss, Save, Scissors, Search, Send, Server, Settings, Share, Share2, Shield, ShieldOff, ShoppingBag, ShoppingCart, Shuffle, Sidebar, SkipBack, SkipForward, Slack, Slash, Sliders, Smartphone, Smile, Speaker, Square, Star, StopCircle, Sun, Sunrise, Sunset, Tablet, Tag, Target, Terminal, Thermometer, ThumbsDown, ThumbsUp, ToggleLeft, ToggleRight, Tool, Trash, Trash2, Trello, TrendingDown, TrendingUp, Triangle, Truck, Tv, Twitch, Twitter, Type, Umbrella, Underline, Unlock, Upload, UploadCloud, User, UserCheck, UserMinus, UserPlus, UserX, Users, Video, VideoOff, Voicemail, Volume, Volume1, Volume2, VolumeX, Watch, Wifi, WifiOff, Wind, XCircle, XOctagon, XSquare, X, Youtube, Zap, ZapOff, ZoomIn, ZoomOut } from 'angular-feather/icons';
import { AppsRoutes } from './apps.routing';
import { ChatComponent } from './chat/chat.component';
import { TicketsComponent } from './ticketlist/tickets.component';
import { TicketdetailsComponent } from './ticketdetails/ticketdetails.component';
import { TaskboardComponent } from './taskboard/taskboard.component';
import { FullcalendarComponent } from './fullcalendar/fullcalendar.component';
import { TodosComponent } from './todos/todos.component';
import { NotesComponent } from './notes/notes.component';
// new
import { TasksComponent } from './tasks/tasks.component';
import { ContactListComponent } from './contact-list/contact-list.component';
import { MailboxComponent } from './mail/mailbox.component';
import { ListingComponent } from './mail/listing/listing.component';
import { DetailComponent } from './mail/detail/detail.component';
import { ComposeComponent } from './mail/compose/compose.component';
import { ContactComponent } from './contact/contact.component';
import { ContactsComponent } from './contacts/contacts.component';
import { ListUsersComponent } from './users/list-users/list-users.component';
import { EditAddUserComponent } from './users/edit-add-user/edit-add-user.component';
// Job search
import { JobsListComponent } from './jobs/jobs-list/jobs-list.component';
import { JobDetailComponent } from './jobs/job-detail/job-detail.component';
import { JobApplyComponent } from './jobs/job-apply/job-apply.component';
import { ServicejobService } from './jobs/servicejob.service';
import { TicketService } from './ticketlist/tickets.service';
import { TimeAgoPipe } from './ticketlist/date-ago.pipe';
import { ContactService } from './contacts/contact.service';
import { NoteService } from './notes/note.service';
import { TodoService } from './todos/todo.service';
import { UserService } from './users/userService.service';
import { TasksService } from './tasks/tasks-service.service';
// New
import { MailGlobalVariable } from './mail/mail.service';
import { MailService } from './mail/mailService';
// rxjs
import { UserRxjsComponent } from './user-rxjs/user-rxjs.component';
import { UserRxjsServiceService } from './user-rxjs/user-rxjs-service.service';
import { ContactRxjsComponent } from './contact-rxjs/contact-rxjs.component';
import { ServiceContactrxjsService } from './contact-rxjs/service-contactrxjs.service';
import { ContactListRxjsComponent } from './contact-list-rxjs/contact-list-rxjs.component';
import { ServiceContactlistRxjsService } from './contact-list-rxjs/service-contactlist-rxjs.service';
import { InvoiceService } from './invoice/invoice.service';
import { AddInvoiceComponent } from './invoice/add-invoice/add-invoice.component';
import { ListInvoicesComponent } from './invoice/list-invoices/list-invoices.component';
import { ViewInvoiceComponent } from './invoice/view-invoice/view-invoice.component';
import { EditInvoiceComponent } from './invoice/edit-invoice/edit-invoice.component';
import { ListTemplateImportComponent } from './users/list-template-import/list-template-import.component';
import { ListTemplateExportComponent } from './users/list-template-export/list-template-export.component';
@NgModule({
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
NgbModule,
NgbModalModule,
CalendarModule.forRoot({
provide: DateAdapter,
useFactory: adapterFactory
}),
QuillModule.forRoot(),
RouterModule.forChild(AppsRoutes),
PerfectScrollbarModule,
Ng2SearchPipeModule,
DragDropModule,
FlatpickrModule.forRoot(),
HttpClientModule,
FeatherModule
],
declarations: [
ChatComponent,
TicketsComponent,
TicketdetailsComponent,
TaskboardComponent,
TodosComponent,
ContactComponent,
ContactsComponent,
FullcalendarComponent,
NotesComponent,
TimeAgoPipe,
ListUsersComponent,
EditAddUserComponent,
TasksComponent,
ContactListComponent,
MailboxComponent,
ListingComponent,
DetailComponent,
ComposeComponent,
UserRxjsComponent,
ContactRxjsComponent,
ContactListRxjsComponent,
AddInvoiceComponent,
ListInvoicesComponent,
ViewInvoiceComponent,
EditInvoiceComponent,
JobsListComponent,
JobDetailComponent,
JobApplyComponent,
ListTemplateImportComponent,
ListTemplateExportComponent
],
providers: [
ContactService,
NoteService,
TodoService,
UserService,
DatePipe,
TicketService,
DecimalPipe,
TasksService,
MailService,
MailGlobalVariable,
UserRxjsServiceService,
ServiceContactrxjsService,
ServiceContactlistRxjsService,
InvoiceService,
ServicejobService
]
})
export class AppsModule { }
import { Routes } from "@angular/router";
import { ChatComponent } from "./chat/chat.component";
import { TicketsComponent } from "./ticketlist/tickets.component";
import { TicketdetailsComponent } from "./ticketdetails/ticketdetails.component";
import { TaskboardComponent } from "./taskboard/taskboard.component";
import { FullcalendarComponent } from "./fullcalendar/fullcalendar.component";
import { TodosComponent } from "./todos/todos.component";
import { NotesComponent } from "./notes/notes.component";
import { ContactComponent } from "./contact/contact.component";
import { ContactsComponent } from "./contacts/contacts.component";
import { TasksComponent } from "./tasks/tasks.component";
import { ContactListComponent } from "./contact-list/contact-list.component";
import { MailboxComponent } from "./mail/mailbox.component";
import { DetailComponent } from "./mail/detail/detail.component";
import { ComposeComponent } from "./mail/compose/compose.component";
import { ListUsersComponent } from "./users/list-users/list-users.component";
import { UserRxjsComponent } from "./user-rxjs/user-rxjs.component";
import { ContactRxjsComponent } from "./contact-rxjs/contact-rxjs.component";
import { ContactListRxjsComponent } from "./contact-list-rxjs/contact-list-rxjs.component";
import { ListInvoicesComponent } from "./invoice/list-invoices/list-invoices.component";
import { AddInvoiceComponent } from "./invoice/add-invoice/add-invoice.component";
import { ViewInvoiceComponent } from "./invoice/view-invoice/view-invoice.component";
import { EditInvoiceComponent } from "./invoice/edit-invoice/edit-invoice.component";
import { JobsListComponent } from "./jobs/jobs-list/jobs-list.component";
import { JobDetailComponent } from "./jobs/job-detail/job-detail.component";
import { JobApplyComponent } from "./jobs/job-apply/job-apply.component";
import { ListTemplateImportComponent } from "./users/list-template-import/list-template-import.component";
import { ListTemplateExportComponent } from "./users/list-template-export/list-template-export.component";
export const AppsRoutes: Routes = [
{
path: "",
children: [
{
path: "chat",
component: ChatComponent,
data: {
title: "",
urls: [],
},
},
{
path: "mail/:type",
component: MailboxComponent,
children: [
{ path: ":id", component: DetailComponent },
{ path: "/compose", component: ComposeComponent },
],
data: {
title: "",
urls: [],
},
},
{
path: "ticket/ticketlist",
component: TicketsComponent,
data: {
title: "Ticket List",
urls: [
{ title: "Dashboard", url: "/dashboard" },
{ title: "Ticket List" },
],
},
},
{
path: "ticket/ticketdetails",
component: TicketdetailsComponent,
data: {
title: "Ticket Details",
urls: [
{ title: "Dashboard", url: "/dashboard" },
{ title: "Ticket Details" },
],
},
},
{
path: "taskboard",
component: TaskboardComponent,
data: {
title: "Taskboard",
urls: [
{ title: "Dashboard", url: "/dashboard" },
{ title: "Taskboard" },
],
},
},
{
path: "fullcalendar",
component: FullcalendarComponent,
data: {
title: "Full-Calendar",
urls: [
{ title: "Dashboard", url: "/dashboard" },
{ title: "Full-Calendar" },
],
},
},
{
path: "todo",
component: TodosComponent,
data: {
title: "",
urls: [],
},
},
{
path: "tasks",
component: TasksComponent,
data: {
title: "",
urls: [],
},
},
{
path: "contact-list",
component: ContactListComponent,
data: {
title: "",
urls: [],
},
},
{
path: "contact-list-rxjs",
component: ContactListRxjsComponent,
data: {
title: "",
urls: [],
},
},
{
path: "notes",
component: NotesComponent,
data: {
title: "",
urls: [],
},
},
{
path: "users",
component: ListUsersComponent,
data: {
title: "Users App",
urls: [
{ title: "Dashboard", url: "/dashboard" },
{ title: "Users App" },
],
},
},
{
path: "import-template",
component: ListTemplateImportComponent,
data: {
title: "Import Template",
urls: [
{ title: "Import Template" },
],
},
},
{
path: "export-template",
component: ListTemplateExportComponent,
data: {
title: "Export Template",
urls: [
{ title: "Export Template" },
],
},
},
{
path: "usersrxjs",
component: UserRxjsComponent,
data: {
title: "Users-Rxjs App",
urls: [
{ title: "Apps", url: "/dashboard" },
{ title: "Users-Rxjs App" },
],
},
},
{
path: "contact-grid",
component: ContactComponent,
data: {
title: "Contact Grid",
urls: [
{ title: "Dashboard", url: "/dashboard" },
{ title: "Contact Grid" },
],
},
},
{
path: "contact",
component: ContactsComponent,
data: {
title: "",
urls: [],
},
},
{
path: "contactrxjs",
component: ContactRxjsComponent,
data: {
title: "",
urls: [],
},
},
{
path: "invoice",
component: ListInvoicesComponent,
data: {
title: "Invoice",
urls: [],
},
},
{
path: "addinvoice",
component: AddInvoiceComponent,
data: {
title: "Add Invoice",
urls: [],
},
},
{
path: "viewinvoice/:id",
component: ViewInvoiceComponent,
data: {
title: "View Invoice",
urls: [],
},
},
{
path: "editinvoice/:id",
component: EditInvoiceComponent,
data: {
title: "",
urls: [],
},
},
{
path: "jobs",
component: JobsListComponent,
data: {
title: "Jobs",
urls: [],
},
},
{
path: "job-detail/:id",
component: JobDetailComponent,
data: {
title: "Jobs Details",
urls: [],
},
},
{
path: "apply-job",
component: JobApplyComponent,
data: {
title: "Apply Job",
urls: [],
},
},
],
},
];
<!-- Mobile toggle button -->
<a [ngClass]="(showSidebar)?'ti-close':'ti-menu'" class="btn btn-success show-left-part d-block d-md-none"
href="javascript:void(0)" (click)="mobileSidebar()"></a>
<div class="main-part">
<div class="left-part bg-white fixed-left-part" [ngClass]="{'show-panel': showSidebar}">
<div class="position-relative" style="height:100%;">
<div class="p-l-15 p-r-25 py-3 d-flex align-items-center mt-1 border-bottom">
<div>
<img src="assets/images/users/8.jpg" width="45" alt="user" class="rounded-circle">
</div>
<div class="text-dark m-b-0 m-l-15 font-18">
Bruce Banner
<p class="m-b-0 font-12">
<i class="fa fa-circle text-success font-10 m-r-5"></i>
<span>Online</span>
</p>
</div>
</div>
<ul class="mailbox list-style-none">
<li>
<div class="message-center" style="height: calc(100vh - 267px);" [perfectScrollbar]="config">
<div *ngFor="let contact of contactList">
<a class="message-item" [class.active]="activeChatUserId === contact.id" (click)="setActive(contact.id)">
<span class="user-img">
<img src={{contact.imagePath}} alt="user" class="rounded-circle" width="100">
<span class="profile-status online pull-right"></span>
</span>
<div class="mail-contnet">
<h5 class="message-title">{{contact.name}}</h5>
<span class="mail-desc">{{contact.signature}}</span>
<p class="time text-uppercase">{{contact.time}}</p>
</div>
</a>
</div>
</div>
</li>
</ul>
</div>
</div>
<div class="right-part">
<div class="card mb-0">
<div class="p-l-15 p-r-25 py-3 d-flex align-items-center border-bottom bg-info">
<div class="mr-3">
<img [src]="[activeChatUserImg]" alt="user" class="rounded-circle" width="50" />
</div>
<div>
<h5 class="text-white mb-0">{{ activeChatUser }}</h5>
<p class="mb-0 text-white">{{ activeChatUserStatus }}</p>
</div>
</div>
<div class="card-body py-0 pr-0">
<div class="chat-box p-r-15" #scrollMe [scrollTop]="scrollMe.scrollHeight"
style="height:calc(100vh - 350px); overflow-y: auto;">
<!--chat Row -->
<ul class="chat-list">
<li class="chat-item" [ngClass]="[chat.chatClass]" *ngFor="let chat of savedMessages">
<div class="chat-img">
<img [src]="[chat.imagePath]" alt="avatar" />
</div>
<div class="chat-content" *ngFor="let message of chat.messages">
<div class="box bg-light-info">
{{ message }}
</div>
</div>
<div class="chat-time text-lowercase" *ngIf="chat.time !='' ">{{chat.time}}</div>
</li>
<li class="chat-item odd type-msg" *ngIf="messages.length > 0">
<div class="chat-img" data-toggle="tooltip" data-placement="right" title="" data-original-title="">
<img src="assets/images/users/8.jpg" alt="user-images" />
</div>
<div class="chat-messages">
<div class="chat-content" *ngFor="let message of messages">
<div class="box bg-light-info">{{ message }}</div>
</div>
</div>
<div class="chat-time">{{ now | date: 'hh.mm a' }}</div>
</li>
</ul>
</div>
</div>
<div class="card-body border-top">
<form class="chat-app-input row">
<div class="col-9">
<input type="text" class="form-control border-0" id="iconLeft4" placeholder="Type your message and enter"
(keydown.enter)="onAddMessage();$event.preventDefault()" #messageInput>
</div>
<div class="col-3">
<button type="button" class="btn-circle btn-lg btn-cyan float-right text-white border-0"
(click)="onAddMessage()">
<i class="fas fa-paper-plane"></i>
</button>
</div>
</form>
</div>
</div>
</div>
</div>
import { Component, ViewChild, ElementRef, OnInit, ChangeDetectionStrategy } from '@angular/core';
import { Chat } from './chat';
import { ContactList } from './contactList';
import { ChatMessages } from './chatMessages';
import { PerfectScrollbarConfigInterface } from 'ngx-perfect-scrollbar';
@Component({
selector: 'app-chat',
templateUrl: './chat.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChatComponent implements OnInit {
public config: PerfectScrollbarConfigInterface = {};
public showSidebar = false;
public now: Date | null = null;
activeChatUserId = 1;
activeChatUser: string | null | undefined = '';
activeChatUserImg: string | null = '';
activeChatUserStatus = '';
@ViewChild('messageInput', { static: true })
messageInputRef: ElementRef | null = null;
messages = new Array();
contactList: ContactList[] | null = null;
savedMessages: Chat[] | null = null;
constructor() {
const chatMessage: ChatMessages = new ChatMessages();
this.contactList = [
{
id: 1,
imagePath: 'assets/images/users/1.jpg',
name: 'Steve Rogers',
signature: 'Hey Banner, where are you?',
time: '9:30AM',
chats: chatMessage.chat1,
},
{
id: 2,
imagePath: 'assets/images/users/2.jpg',
name: 'Ram',
signature: 'ram ram ram .....',
time: '10:30AM',
chats: chatMessage.chat2,
},
{
id: 3,
imagePath: 'assets/images/users/3.jpg',
name: 'Shyam',
signature: 'shyam shyam .....',
time: '11:30AM',
chats: chatMessage.chat3,
},
{
id: 4,
imagePath: 'assets/images/users/4.jpg',
name: 'Mark',
signature: 'mark mark ......',
time: '8:30AM',
chats: chatMessage.chat4,
},
{
id: 5,
imagePath: 'assets/images/users/5.jpg',
name: 'Robin',
signature: 'robin robin ......',
time: '6:30AM',
chats: chatMessage.chat5,
}
];
// tslint:disable-next-line:no-non-null-assertion
this.activeChatUser = this.contactList!.find(x => x.id === 1)?.name;
// tslint:disable-next-line:no-non-null-assertion
this.activeChatUserImg = this.contactList!.find(x => x.id === 1)!.imagePath;
// tslint:disable-next-line:no-non-null-assertion
this.savedMessages = this.contactList!.find(x => x.id === 1)!.chats;
this.activeChatUserStatus = 'Online';
}
ngOnInit() {
}
// chat user list click event function
setActive(chatId: number) {
this.savedMessages = new Array();
this.messages = [];
if (this.contactList !== null) {
for (let i = 0; i < this.contactList.length; i++) {
if (this.contactList[i].id === chatId) {
this.activeChatUserId = this.contactList[i].id;
this.activeChatUser = this.contactList[i].name;
this.activeChatUserImg = this.contactList[i].imagePath;
this.savedMessages = this.contactList[i].chats;
this.activeChatUserStatus = 'Online';
}
}
}
}
onAddMessage() {
if (this.messageInputRef?.nativeElement.value !== '') {
this.messages.push(this.messageInputRef?.nativeElement.value);
}
if (this.messageInputRef !== null) {
this.messageInputRef.nativeElement.value = '';
this.messageInputRef.nativeElement.focus();
}
this.now = new Date();
}
mobileSidebar() {
this.showSidebar = !this.showSidebar;
}
}
export class Chat {
public chatClass: string;
public imagePath: string;
public time: string;
public messages: string[];
constructor(
chatClass: string,
imagePath: string,
time: string,
messages: string[]
) {
this.chatClass = chatClass;
this.imagePath = imagePath;
this.time = time;
this.messages = messages;
}
}
import { Chat } from './chat';
export class ChatMessages {
constructor() {
}
public chat1: Chat[] = [
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.30 am',
[
'Hi, How are you ?'
],
),
new Chat(
'even',
'assets/images/users/1.jpg',
'9.30 am',
[
'Hey Bruce, I am Fine'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.31 am',
[
'What are you doing nowadays ?'
],
),
new Chat(
'even',
'assets/images/users/1.jpg',
'9.31 am',
[
'Nothing Much.'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.32 am',
[
'yes'
],
),
new Chat(
'even',
'assets/images/users/1.jpg',
'9.32 am',
[
'Do you have interest in IOS ?'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.33 am',
[
'Yes, not more.'
],
)
];
public chat2: Chat[] = [new Chat(
'odd',
'assets/images/users/6.jpg',
'9.32 am',
[
'Hi ram ..'
],
),
new Chat(
'even',
'assets/images/users/2.jpg',
'9.32 am',
[
'Hi, Bruce'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.32 am',
[
'Have a knowledge about Cordova ram ..?'
],
),
new Chat(
'even',
'assets/images/users/2.jpg',
'9.34 am',
[
'Yes, You also have interest in that ?'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.34 am',
[
'Yeah, I have also develop a mobile app on that ram ..'
],
),
new Chat(
'even',
'assets/images/users/2.jpg',
'9.34 am',
[
'Do you upload that on play store ?'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.34 am',
[
'Nope ram ..'
],
),
new Chat(
'even',
'assets/images/users/2.jpg',
'9.35 am',
[
'Then Upload it, you will get money.'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.35 am',
[
'Okay ram ...'
],
)
];
public chat3: Chat[] = [
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.37 am',
[
'Hey, How are you ?'
],
),
new Chat(
'even',
'assets/images/users/3.jpg',
'9.37 am',
[
'Hi, I am fine.'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.37 am',
[
'okay'
],
),
new Chat(
'even',
'assets/images/users/3.jpg',
'9.37 am',
[
'Lets go for tea.'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.39 am',
[
'Yeah, Sure'
],
),
new Chat(
'even',
'assets/images/users/3.jpg',
'9.39 am',
[
'What about time?'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.39 am',
[
'I will ask you after'
],
),
new Chat(
'even',
'assets/images/users/3.jpg',
'9.39 am',
[
'Okay, let me know. Once you decide.'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.41 am',
[
'Yeah'
],
),
new Chat(
'even',
'assets/images/users/3.jpg',
'9.41 am',
[
'Bye'
],
)
];
public chat4: Chat[] = [
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.21 am',
[
'Hi, How are you ?'
],
),
new Chat(
'even',
'assets/images/users/4.jpg',
'9.21 am',
[
'Hey Bruce, I am Fine'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.21 am',
[
'What are you doing nowadays ?'
],
),
new Chat(
'even',
'assets/images/users/4.jpg',
'9.21 am',
[
'Nothing Much.'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.21 am',
[
'yes'
],
),
new Chat(
'even',
'assets/images/users/4.jpg',
'9.22 am',
[
'Do you have interest in IOS ?'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.23 am',
[
'Yes, not more.'
],
),
new Chat(
'even',
'assets/images/users/4.jpg',
'9.24 am',
[
'Okay.'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.24 am',
[
'I have join Android Classes.'
],
),
new Chat(
'even',
'assets/images/users/4.jpg',
'9.24 am',
[
'Okay, Great.'
],
)
];
public chat5: Chat[] = [
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.14 am',
[
'Hi'
],
),
new Chat(
'even',
'assets/images/users/5.jpg',
'9.14 am',
[
'Hi, Bruce'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.14 am',
[
'Have a knowledge about Cordova ?'
],
),
new Chat(
'even',
'assets/images/users/5.jpg',
'9.15 am',
[
'Yes, You also have interest in that ?'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.15 am',
[
'Yeah, I have also develop a mobile app on that'
],
),
new Chat(
'even',
'assets/images/users/5.jpg',
'9.15 am',
[
'Do you upload that on play store ?'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.16 am',
[
'Nope'
],
),
new Chat(
'even',
'assets/images/users/5.jpg',
'9.16 am',
[
'Then Upload it, you will get money.'
],
),
new Chat(
'odd',
'assets/images/users/6.jpg',
'9.16 am',
[
'Okay.'
],
)
];
}
import { Chat } from './chat';
export class ContactList {
public id = 0;
public imagePath: string | null = null;
public name: string | null = null;
public signature: string | null = null;
public time: string | null = null;
public chats: Chat[] | null = null;
}
import { ContactLists } from './contact-list';
export const ContactList: ContactLists[] = [
{
Id: 1,
Imagepath: 'assets/images/users/2.jpg',
Name: 'Emma Adams',
Tags: 'Friend',
Jobtitle: 'Web Developer',
Company: 'Wrappixel',
Email: 'adams@mail.com',
Phonenumber: 1548462031,
Address: 'Boston, USA',
DOB: new Date,
Description: 'Felis bibendum ut tristique et egestas quis. In cursus turpis massa tincidunt dui ut.'
},
{
Id: 2,
Imagepath: 'assets/images/users/3.jpg',
Name: 'Olivia Allen',
Tags: 'Family',
Jobtitle: 'Ethical Hacker',
Company: 'Infosys',
Email: 'allen@mail.com',
Phonenumber: 9478021640,
Address: 'Sydney, Australia',
DOB: new Date,
Description: 'Est ante in nibh mauris cursus mattis molestie a iaculis.'
},
{
Id: 3,
Imagepath: 'assets/images/users/4.jpg',
Name: 'Emily Atkinson',
Tags: 'Friend',
Jobtitle: 'UX/UI Designer',
Company: 'Google',
Email: 'atkinson@mail.com',
Phonenumber: 6302154203,
Address: 'Edinburgh, UK',
DOB: new Date,
Description: 'Orci nulla pellentesque dignissim enim.'
},
{
Id: 4,
Imagepath: 'assets/images/users/5.jpg',
Name: 'Isabella Anderson',
Tags: 'Friend',
Jobtitle: 'UX/UI Designer',
Company: 'Tesala',
Email: 'anderson@mail.com',
Phonenumber: 1503201502,
Address: 'Miami, USA',
DOB: new Date,
Description: 'Gravida cum sociis natoque penatibus et magnis dis parturient.'
},
{
Id: 5,
Imagepath: 'assets/images/users/6.jpg',
Name: 'Amelia Armstrong',
Tags: 'Office',
Jobtitle: 'Ethical Hacker',
Company: 'Infosys',
Email: 'armstrong@mail.com',
Phonenumber: 8124502316,
Address: 'Tokyo, Japan',
DOB: new Date,
Description: 'Sit amet luctus venenatis lectus magna fringilla urna porttitor.'
},
{
Id: 6,
Imagepath: 'assets/images/users/7.jpg',
Name: 'Sofia Bailey',
Tags: 'Family',
Jobtitle: 'Theme Designer',
Company: 'Google',
Email: 'bailey@mail.com',
Phonenumber: 7080642130,
Address: 'New York, USA',
DOB: new Date,
Description: 'Sapien et ligula ullamcorper malesuada proin libero nunc.'
},
{
Id: 7,
Imagepath: 'assets/images/users/8.jpg',
Name: 'Victoria Sharma',
Tags: 'Friend',
Jobtitle: 'Project Manager',
Company: 'Wrappixel',
Email: 'sharma@mail.com',
Phonenumber: 9040263102,
Address: 'Miami, USA',
DOB: new Date,
Description: 'Id venenatis a condimentum vitae sapien pellentesque habitant morbi.'
},
{
Id: 8,
Imagepath: 'assets/images/users/agent.jpg',
Name: 'Olivia Allen',
Tags: 'Friend',
Jobtitle: 'Ethical Hacker',
Company: 'Infosys',
Email: 'allen@mail.com',
Phonenumber: 7800245169,
Address: 'Sydney, Australia',
DOB: new Date,
Description: 'Elit at imperdiet dui accumsan sit amet nulla facilisi morbi. Porta lorem mollis aliquam ut porttitor leo a diam.'
},
{
Id: 9,
Imagepath: 'assets/images/users/agent2.jpg',
Name: 'Emily Atkinson',
Tags: 'Office',
Jobtitle: 'UX/UI Designer',
Company: 'Google',
Email: 'atkinson@mail.com',
Phonenumber: 9874560213,
Address: 'Edinburgh, UK',
DOB: new Date,
Description: 'Vivamus arcu felis bibendum ut tristique.'
},
{
Id: 10,
Imagepath: 'assets/images/users/d2.jpg',
Name: 'Emma Adams',
Tags: 'Office',
Jobtitle: 'Web Developer',
Company: 'Wrappixel',
Email: 'adams@mail.com',
Phonenumber: 4500231620,
Address: 'Boston, USA',
DOB: new Date,
Description: 'Habitasse platea dictumst vestibulum rhoncus.'
},
{
Id: 11,
Imagepath: 'assets/images/users/3.jpg',
Name: 'Olivia Allen',
Tags: 'Friend',
Jobtitle: 'Ethical Hacker',
Company: 'Infosys',
Email: 'allen@mail.com',
Phonenumber: 9748020130,
Address: 'Sydney, Australia',
DOB: new Date,
Description: 'Aliquet porttitor lacus luctus accumsan tortor posuere.'
},
{
Id: 12,
Imagepath: 'assets/images/users/4.jpg',
Name: 'Emily Atkinson',
Tags: 'Friend',
Jobtitle: 'UX/UI Designer',
Company: 'Google',
Email: 'atkinson@mail.com',
Phonenumber: 8200154212,
Address: 'Edinburgh, UK',
DOB: new Date,
Description: 'Elit at imperdiet dui accumsan sit amet nulla.'
},
];
<div class="app-sidebar card" id="rightMenu">
<!-- Details View of Contact -->
<div *ngIf='selectedContact!=null && !editable'>
<img src="assets/images/background/profile-bg.jpg" class="card-img" />
<div class="card-img-overlay">
<div class="d-flex justify-content-end">
<a href="javascript:void(0)" class="btn bg-white text-info py-1 px-2 link" placement="bottom"
ngbTooltip="Edit Contact" (click)='editContact()'>
<i-feather name="edit-2" class="feather-sm"></i-feather>
</a>
<a href="javascript:void(0)" class="btn bg-white text-danger py-1 px-2 link ml-3"
(click)="closeRightMenu()">
<i-feather name="x" class="feather-sm"></i-feather>
</a>
</div>
</div>
<div class="text-center">
<img [src]='selectedContact.Imagepath' class="rounded-circle mt-n5 shadow" alt="Cinque Terre" height="100px"
width="100px">
<h4 class="text-dark mt-2 mb-0">{{selectedContact.Name}}</h4>
<span class="badge badge-info badge-pill font-medium px-2">{{selectedContact.Tags}}</span>
</div>
<div class="position-relative" [perfectScrollbar]="config2" style="height: 350px;">
<div class="d-flex align-items-center py-2 px-3 border-bottom"
*ngIf='selectedContact.Jobtitle !=undefined && selectedContact.Company!=undefined'>
<button class="btn btn-success btn-circle mr-2 d-flex align-items-center btn-sm justify-content-center">
<i-feather name="Briefcase" class="feather-sm"></i-feather>
</button>
<div class="text-dark font-medium">{{selectedContact.Jobtitle}} , {{selectedContact.Company}}</div>
</div>
<div class="d-flex align-items-center py-2 px-3 border-bottom" *ngIf='selectedContact.Email !=undefined'>
<button class="btn btn-danger btn-circle mr-2 d-flex align-items-center btn-sm justify-content-center">
<i-feather name="Mail" class="feather-sm"></i-feather>
</button>
<div class="text-dark font-medium">{{selectedContact.Email}}</div>
</div>
<div class="d-flex align-items-center py-2 px-3 border-bottom"
*ngIf='selectedContact.Phonenumber !=undefined'>
<button class="btn btn-warning btn-circle mr-2 d-flex align-items-center btn-sm justify-content-center">
<i-feather name="Phone" class="feather-sm"></i-feather>
</button>
<div class="text-dark font-medium">{{selectedContact.Phonenumber}}</div>
</div>
<div class="d-flex align-items-center py-2 px-3 border-bottom" *ngIf='selectedContact.Address !=undefined'>
<button class="btn btn-primary btn-circle mr-2 d-flex align-items-center btn-sm justify-content-center">
<i-feather name="Map" class="feather-sm"></i-feather>
</button>
<div class="text-dark font-medium">{{selectedContact.Address}}</div>
</div>
<div class="d-flex align-items-center py-2 px-3 border-bottom" *ngIf='selectedContact.DOB !=undefined'>
<button class="btn btn-dark btn-circle mr-2 d-flex align-items-center btn-sm justify-content-center">
<i-feather name="Gift" class="feather-sm"></i-feather>
</button>
<div class="text-dark font-medium">{{selectedContact.DOB | date}}</div>
</div>
<div class="d-flex align-items-start py-2 px-3 border-bottom"
*ngIf='selectedContact.Description !=undefined'>
<button class="btn btn-info btn-circle mr-2 d-flex align-items-center btn-sm justify-content-center">
<i-feather name="file-text" class="feather-sm"></i-feather>
</button>
<div class="text-dark font-medium">{{selectedContact.Description}}</div>
</div>
</div>
</div>
<!-- Edit View of Contact -->
<div *ngIf='selectedContact!=null && editable'>
<img src="assets/images/background/profile-bg.jpg" class="card-img" />
<div class="card-img-overlay" style="height: 95px;">
<div class="d-flex justify-content-end">
<a href="javascript:void(0)" class="btn bg-white text-success py-1 px-2 link" placement="bottom"
ngbTooltip="Save Contact" (click)='saveClick(selectedContact.Id)'>
<i-feather name="save" class="feather-sm"></i-feather>
</a>
<a href="javascript:void(0)" class="btn bg-white text-danger py-1 px-2 link ml-3" placement="bottom"
ngbTooltip="Delete Contact" (click)='deleteClick(selectedContact.Id)'>
<i-feather name="trash-2" class="feather-sm"></i-feather>
</a>
<a href="javascript:void(0)" class="btn bg-white text-danger py-1 px-2 link ml-3"
(click)='cancelClick()'>
<i-feather name="x" class="feather-sm"></i-feather>
</a>
</div>
</div>
<!-- Editable Form here -->
<div>
<form>
<div class="form-group mt-n5 text-center">
<input type="file" style="display: none;" (change)='preview(filevar.files)' #filevar>
<img [src]='selectedContactCopy.Imagepath' class="rounded-circle image" alt="" height="100px"
width="100px" (click)='filevar.click()'>
<div class="text-center">
<span class="font-weight-normal">Change Image</span>
</div>
</div>
<div class="p-3 position-relative" [perfectScrollbar]="config" style="height: 350px;">
<div class="row">
<div class="col-12 form-group">
<label class="mb-0 text-dark">Name</label>
<input type="text" name="name" [(ngModel)]="selectedContactCopy.Name" class="form-control">
</div>
<div class="col-12 form-group">
<label class="mb-0 text-dark">Job Title</label>
<input type="text" name="Jobtitle" [(ngModel)]="selectedContactCopy.Jobtitle"
class="form-control">
</div>
<div class="col-12 form-group">
<label class="mb-0 text-dark">Company name</label>
<input type="text" name="company" [(ngModel)]="selectedContactCopy.Company"
class="form-control">
</div>
<div class="col-12 form-group">
<label class="mb-0 text-dark">Email</label>
<input type="text" name="email" [(ngModel)]="selectedContactCopy.Email"
class="form-control">
</div>
<div class="col-12 form-group">
<label class="mb-0 text-dark">Phone Number</label>
<input type="text" name="phone" [(ngModel)]="selectedContactCopy.Phonenumber"
class="form-control">
</div>
<div class="col-12 form-group">
<label class="mb-0 text-dark">Location</label>
<input name="address" type="text" [(ngModel)]="selectedContactCopy.Address"
class="form-control">
</div>
<div class="col-12 form-group">
<label class="mb-0 text-dark">Birthdate</label>
<input name="dob" type="date" [(ngModel)]="selectedContactCopy.DOB" class="form-control">
</div>
<div class="col-12 form-group">
<label class="mb-0 text-dark">Description</label>
<textarea name="description" type="text" [(ngModel)]="selectedContactCopy.Description"
class="form-control"></textarea>
</div>
</div>
</div>
</form>
</div>
<!-- end editable form here -->
</div>
</div>
<!-- -------------------------------------------------------------------- -->
<!-- Contact Listing -->
<!-- -------------------------------------------------------------------- -->
<div class="d-md-flex align-items-center bg-white p-3">
<h3 class="mb-0">Contact List</h3>
<div class="ml-auto mt-3 mt-md-0">
<!-- Add Contact -->
<button type="button" class="btn btn-cyan rounded-pill py-2" (click)='addContact()'><i
class="fas fa-plus font-14 mr-1 text-white"></i>
<span class="ml-1 text-white font-weight-bold">Add Contact</span>
</button>
</div>
</div>
<div class="d-md-flex align-items-center border-top bg-white p-3">
<div>
<input type="text" placeholder="Search by Name" class="form-control rounded-pill" [(ngModel)]='searchTerm'>
</div>
<div class="ml-auto mt-3 mt-md-0">
<!-- No. of Contacts-->
<a href="javascript:void(0)" class="d-flex align-items-center p-2 rounded-pill bg-light">
<h5 class="mb-0 mr-1 text-dark font-weight-bold font-14"> Total Contacts
</h5>
<span *ngIf='contactFilter'
class="badge badge-danger badge-pill px-3 font-weight-bold font-14">{{contactFilter.length}}</span>
</a>
</div>
</div>
<div class="table-responsive">
<table class="table bg-white table-hover align-middle mb-0 no-wrap">
<thead>
<tr>
<th>Name</th>
<th scope="col">Email</th>
<th scope="col">Phone Number</th>
<th scope="col">Job title & company</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let co of contactFilter|slice: (page-1) * pageSize : (page-1) * pageSize + pageSize">
<td>
<img [src]='co.Imagepath' class="rounded-circle mr-2" alt="" height="45" width="45">
<span class="text-dark font-medium font-16">{{ co.Name }}</span>
</td>
<td class="align-middle">
<span>
<span class="badge badge-light text-dark rounded-pill font-16 mr-1">
<i-feather name="Mail" class="feather-sm"></i-feather>
</span>
{{ co.Email }}
</span>
</td>
<td class="align-middle">
<span>
<span class="badge badge-light text-dark rounded-pill font-16 mr-1">
<i-feather name="phone" class="feather-sm"></i-feather>
</span>
{{ co.Phonenumber }}
</span>
</td>
<td class="align-middle position-relative">
<span>
<span class="badge badge-light text-dark rounded-pill font-16 mr-1">
<i-feather name="Briefcase" class="feather-sm"></i-feather>
</span>
{{ co.Jobtitle}} , {{co.Company}}
</span>
</td>
<td class="align-middle">
<a href="javascript:void(0)" class="link font-16 mr-2 font-medium" (click)='tableRowClicked(co)'>
<i-feather name="edit-3" class="feather-sm"></i-feather>
</a>
<a href="javascript:void(0)" class="link font-16 mr-2 font-weight-bold" (click)='viewClicked(co)'>
<i-feather name="eye" class="feather-sm"></i-feather>
</a>
<a href="javascript:void(0)" class="link font-16 font-medium" (click)='deleteClick(co.Id)'>
<i-feather name="trash-2" class="feather-sm"></i-feather>
</a>
</td>
</tr>
</tbody>
</table>
</div>
<div class="d-flex justify-content-center p-2 pt-3 bg-white border-top">
<ngb-pagination [collectionSize]="collectionSize" [(page)]="page" [pageSize]="pageSize">
</ngb-pagination>
</div>
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ContactListRxjsComponent } from './contact-list-rxjs.component';
describe('ContactListRxjsComponent', () => {
let component: ContactListRxjsComponent;
let fixture: ComponentFixture<ContactListRxjsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ContactListRxjsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ContactListRxjsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
});
import { Component, OnInit } from '@angular/core';
import { ContactLists } from './contact-list';
import { ServiceContactlistRxjsService } from './service-contactlist-rxjs.service';
@Component({
selector: 'app-contact-list-rxjs',
templateUrl: './contact-list-rxjs.component.html',
styleUrls: ['./contact-list-rxjs.component.css']
})
export class ContactListRxjsComponent implements OnInit {
contacts: ContactLists[] = [];
contactFilter: ContactLists[] | null = null;
selectedContact: ContactLists | null = null;
selectedContactCopy: ContactLists | null | any = null;
editable = false;
page = 1;
pageSize = 5;
collectionSize = 0;
_searchTerm = '';
// image.......................................
public imagePath: string | null = null;
imgURL: string | null = null;
public message = '';
constructor(public contactListservice: ServiceContactlistRxjsService) {
this.contactListservice.getContactList().subscribe((data) => {
this.contacts.push(data);
})
}
ngOnInit() {
this.contactFilter = this.contacts;
this.collectionSize = this.contactFilter.length;
this.selectedContact = null;
}
// search...
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this._searchTerm = val;
this.contactFilter = this.filter(val);
}
filter(v: string) {
return this.contacts.filter(x => x.Name.toLowerCase().indexOf(v.toLowerCase()) !== -1);
}
// table row clicked...
tableRowClicked(contact: ContactLists) {
this.selectedContact = contact;
(document.getElementById('rightMenu') as HTMLFormElement).style.width = '300px';
this.editContact();
}
viewClicked(contact: ContactLists) {
this.selectedContact = contact;
(document.getElementById('rightMenu') as HTMLFormElement).style.width = '300px';
}
// right menu closed...
closeRightMenu() {
this.editable = false;
this.selectedContact = null;
this.selectedContactCopy = null;
(document.getElementById('rightMenu') as HTMLFormElement).style.width = '0';
}
editContact() {
this.selectedContactCopy = Object.assign({}, this.selectedContact);
this.editable = true;
}
// cancel clicked on right menu...
cancelClick() {
this.selectedContact = null;
this.selectedContactCopy = null;
this.closeRightMenu();
}
// edit contact-list...
saveClick(id: number) {
if (this.contactFilter) {
const c: ContactLists | undefined = this.contactFilter.find(con => con.Id === id);
if (c !== undefined && this.selectedContactCopy) {
c.Imagepath = this.selectedContactCopy.Imagepath;
c.Name = this.selectedContactCopy.Name;
c.Tags = this.selectedContactCopy.Tags;
c.Jobtitle = this.selectedContactCopy.Jobtitle;
c.Company = this.selectedContactCopy.Company;
c.Email = this.selectedContactCopy.Email;
c.Phonenumber = this.selectedContactCopy.Phonenumber;
c.Address = this.selectedContactCopy.Address;
c.DOB = this.selectedContactCopy.DOB;
c.Description = this.selectedContactCopy.Description;
this.contactListservice.updateContactList(id, c);
this.closeRightMenu();
}
}
}
// delete click...
deleteClick(id: number) {
if (this.contactFilter) {
this.contactListservice.deleteContactList(id);
this.contactFilter = this.contactFilter.filter(user => user.Id !== id);
}
this.collectionSize--;
this.selectedContact = null;
this.closeRightMenu();
}
// add contact...
addContact() {
const con: ContactLists = new ContactLists();
if (this.contactFilter) {
const n = Math.max.apply(Math,
this.contactFilter.map(function (o) { return o.Id; })) + 1;
con.Id = n;
}
con.Imagepath = '/assets/images/users/1.jpg';
con.Name = 'New Contact';
con.Tags = 'Test';
con.Jobtitle = 'Web Designer';
con.Company = 'Wrappixel';
con.Email = 'newcontact@gmail.com';
con.Phonenumber = 9405123015;
con.Address = 'Bhavnagar, India';
con.DOB = new Date;
con.Description = 'Add a Description';
this.contactListservice.addContactList(con);
this.contactFilter?.splice(0, 0, con);
this.collectionSize++;
this.tableRowClicked(con);
this.editContact();
}
preview(files: any) {
if (files.length === 0) {
return;
}
const mimeType = files[0].type;
if (mimeType.match(/image\/*/) == null) {
this.message = 'Only images are supported.';
return;
}
const reader = new FileReader();
this.imagePath = files;
reader.readAsDataURL(files[0]);
reader.onload = (_event) => {
this.selectedContactCopy!.Imagepath = reader.result;
};
}
}
export class ContactLists {
Id = 0;
Imagepath: string | null | undefined = '';
Name = '';
Tags = '';
Jobtitle = '';
Company = '';
Email = '';
Phonenumber = 0;
Address = '';
DOB: Date | null = null;
Description = '';
}
import { TestBed } from '@angular/core/testing';
import { ServiceContactlistRxjsService } from './service-contactlist-rxjs.service';
describe('ServiceContactlistRxjsService', () => {
let service: ServiceContactlistRxjsService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(ServiceContactlistRxjsService);
});
// it('should be created', () => {
// expect(service).toBeTruthy();
// });
});
import { Injectable } from '@angular/core';
import { from, Observable } from 'rxjs';
import { ContactLists } from './contact-list';
import { ContactList } from './contact-list-data';
@Injectable({
providedIn: 'root'
})
export class ServiceContactlistRxjsService {
constructor() { }
private contactList: ContactLists[] = ContactList;
// getContactList(): Observable<ContactLists> {
// You can also fetch data from Api using HttpClient.
// return this.http.get(url..)
// }
getContactList(): Observable<ContactLists> {
return from(this.contactList);
}
deleteContactList(id: number): void {
this.contactList = this.contactList.filter(cl => cl.Id !== id);
}
addContactList(cl: ContactLists): void {
this.contactList?.push(cl);
}
updateContactList(index: number, cl: ContactLists): void {
this.contactList[index] = cl;
}
}
import { ContactLists } from './contact-list';
export const ContactList: ContactLists[] = [
{
Id: 1,
Imagepath: 'assets/images/users/2.jpg',
Name: 'Emma Adams',
Tags: 'Friend',
Jobtitle: 'Web Developer',
Company: 'Wrappixel',
Email: 'adams@mail.com',
Phonenumber: 1548462031,
Address: 'Boston, USA',
DOB: new Date,
Description: 'Felis bibendum ut tristique et egestas quis. In cursus turpis massa tincidunt dui ut.'
},
{
Id: 2,
Imagepath: 'assets/images/users/3.jpg',
Name: 'Olivia Allen',
Tags: 'Family',
Jobtitle: 'Ethical Hacker',
Company: 'Infosys',
Email: 'allen@mail.com',
Phonenumber: 9478021640,
Address: 'Sydney, Australia',
DOB: new Date,
Description: 'Est ante in nibh mauris cursus mattis molestie a iaculis.'
},
{
Id: 3,
Imagepath: 'assets/images/users/4.jpg',
Name: 'Emily Atkinson',
Tags: 'Friend',
Jobtitle: 'UX/UI Designer',
Company: 'Google',
Email: 'atkinson@mail.com',
Phonenumber: 6302154203,
Address: 'Edinburgh, UK',
DOB: new Date,
Description: 'Orci nulla pellentesque dignissim enim.'
},
{
Id: 4,
Imagepath: 'assets/images/users/5.jpg',
Name: 'Isabella Anderson',
Tags: 'Friend',
Jobtitle: 'UX/UI Designer',
Company: 'Tesala',
Email: 'anderson@mail.com',
Phonenumber: 1503201502,
Address: 'Miami, USA',
DOB: new Date,
Description: 'Gravida cum sociis natoque penatibus et magnis dis parturient.'
},
{
Id: 5,
Imagepath: 'assets/images/users/6.jpg',
Name: 'Amelia Armstrong',
Tags: 'Office',
Jobtitle: 'Ethical Hacker',
Company: 'Infosys',
Email: 'armstrong@mail.com',
Phonenumber: 8124502316,
Address: 'Tokyo, Japan',
DOB: new Date,
Description: 'Sit amet luctus venenatis lectus magna fringilla urna porttitor.'
},
{
Id: 6,
Imagepath: 'assets/images/users/7.jpg',
Name: 'Sofia Bailey',
Tags: 'Family',
Jobtitle: 'Theme Designer',
Company: 'Google',
Email: 'bailey@mail.com',
Phonenumber: 7080642130,
Address: 'New York, USA',
DOB: new Date,
Description: 'Sapien et ligula ullamcorper malesuada proin libero nunc.'
},
{
Id: 7,
Imagepath: 'assets/images/users/8.jpg',
Name: 'Victoria Sharma',
Tags: 'Friend',
Jobtitle: 'Project Manager',
Company: 'Wrappixel',
Email: 'sharma@mail.com',
Phonenumber: 9040263102,
Address: 'Miami, USA',
DOB: new Date,
Description: 'Id venenatis a condimentum vitae sapien pellentesque habitant morbi.'
},
{
Id: 8,
Imagepath: 'assets/images/users/agent.jpg',
Name: 'Olivia Allen',
Tags: 'Friend',
Jobtitle: 'Ethical Hacker',
Company: 'Infosys',
Email: 'allen@mail.com',
Phonenumber: 7800245169,
Address: 'Sydney, Australia',
DOB: new Date,
Description: 'Elit at imperdiet dui accumsan sit amet nulla facilisi morbi. Porta lorem mollis aliquam ut porttitor leo a diam.'
},
{
Id: 9,
Imagepath: 'assets/images/users/agent2.jpg',
Name: 'Emily Atkinson',
Tags: 'Office',
Jobtitle: 'UX/UI Designer',
Company: 'Google',
Email: 'atkinson@mail.com',
Phonenumber: 9874560213,
Address: 'Edinburgh, UK',
DOB: new Date,
Description: 'Vivamus arcu felis bibendum ut tristique.'
},
{
Id: 10,
Imagepath: 'assets/images/users/d2.jpg',
Name: 'Emma Adams',
Tags: 'Office',
Jobtitle: 'Web Developer',
Company: 'Wrappixel',
Email: 'adams@mail.com',
Phonenumber: 4500231620,
Address: 'Boston, USA',
DOB: new Date,
Description: 'Habitasse platea dictumst vestibulum rhoncus.'
},
{
Id: 11,
Imagepath: 'assets/images/users/3.jpg',
Name: 'Olivia Allen',
Tags: 'Friend',
Jobtitle: 'Ethical Hacker',
Company: 'Infosys',
Email: 'allen@mail.com',
Phonenumber: 9748020130,
Address: 'Sydney, Australia',
DOB: new Date,
Description: 'Aliquet porttitor lacus luctus accumsan tortor posuere.'
},
{
Id: 12,
Imagepath: 'assets/images/users/4.jpg',
Name: 'Emily Atkinson',
Tags: 'Friend',
Jobtitle: 'UX/UI Designer',
Company: 'Google',
Email: 'atkinson@mail.com',
Phonenumber: 8200154212,
Address: 'Edinburgh, UK',
DOB: new Date,
Description: 'Elit at imperdiet dui accumsan sit amet nulla.'
},
];
.image {
display: block;
margin-left: auto;
margin-right: auto;
}
.cursor-pointer {
cursor: pointer;
}
<div class="app-sidebar card" id="rightMenu">
<!-- Details View of Contact -->
<div *ngIf='selectedContact!=null && !editable'>
<img src="assets/images/background/profile-bg.jpg" class="card-img cursor-pointer" />
<div class="card-img-overlay">
<div class="d-flex justify-content-end">
<a href="javascript:void(0)" class="btn bg-white text-info py-1 px-2 link" placement="bottom"
ngbTooltip="Edit Contact" (click)='editContact()'>
<i-feather name="edit-2" class="feather-sm"></i-feather>
</a>
<a href="javascript:void(0)" class="btn bg-white text-danger py-1 px-2 link ml-3"
(click)="closeRightMenu()">
<i-feather name="x" class="feather-sm"></i-feather>
</a>
</div>
</div>
<div class="text-center">
<img [src]='selectedContact.Imagepath' class="rounded-circle mt-n5 shadow" alt="Cinque Terre" height="100px"
width="100px">
<h4 class="text-dark mt-2 mb-0">{{selectedContact.Name}}</h4>
<span class="badge badge-info badge-pill font-medium px-2">{{selectedContact.Tags}}</span>
</div>
<div class="position-relative" [perfectScrollbar]="config2" style="height: 350px;">
<div class="d-flex align-items-center py-2 px-3 border-bottom"
*ngIf='selectedContact.Jobtitle !=undefined && selectedContact.Company!=undefined'>
<button class="btn btn-success btn-circle mr-2 d-flex align-items-center btn-sm justify-content-center">
<i-feather name="Briefcase" class="feather-sm"></i-feather>
</button>
<div class="text-dark font-medium">{{selectedContact.Jobtitle}} , {{selectedContact.Company}}</div>
</div>
<div class="d-flex align-items-center py-2 px-3 border-bottom" *ngIf='selectedContact.Email !=undefined'>
<button class="btn btn-danger btn-circle mr-2 d-flex align-items-center btn-sm justify-content-center">
<i-feather name="Mail" class="feather-sm"></i-feather>
<!-- <i class="mdi mdi-email font-16"></i> -->
</button>
<div class="text-dark font-medium">{{selectedContact.Email}}</div>
</div>
<div class="d-flex align-items-center py-2 px-3 border-bottom"
*ngIf='selectedContact.Phonenumber !=undefined'>
<button class="btn btn-warning btn-circle mr-2 d-flex align-items-center btn-sm justify-content-center">
<i-feather name="Phone" class="feather-sm"></i-feather>
</button>
<div class="text-dark font-medium">{{selectedContact.Phonenumber}}</div>
</div>
<div class="d-flex align-items-center py-2 px-3 border-bottom" *ngIf='selectedContact.Address !=undefined'>
<button class="btn btn-primary btn-circle mr-2 d-flex align-items-center btn-sm justify-content-center">
<i-feather name="Map" class="feather-sm"></i-feather>
</button>
<div class="text-dark font-medium">{{selectedContact.Address}}</div>
</div>
<div class="d-flex align-items-center py-2 px-3 border-bottom" *ngIf='selectedContact.DOB !=undefined'>
<button class="btn btn-dark btn-circle mr-2 d-flex align-items-center btn-sm justify-content-center">
<i-feather name="Gift" class="feather-sm"></i-feather>
</button>
<div class="text-dark font-medium">{{selectedContact.DOB | date}}</div>
</div>
<div class="d-flex align-items-start py-2 px-3 border-bottom"
*ngIf='selectedContact.Description !=undefined'>
<button class="btn btn-info btn-circle mr-2 d-flex align-items-center btn-sm justify-content-center">
<i-feather name="file-text" class="feather-sm"></i-feather>
</button>
<div class="text-dark font-medium">{{selectedContact.Description}}</div>
</div>
</div>
</div>
<!-- Edit View of Contact -->
<div *ngIf='selectedContact!=null && editable'>
<img src="assets/images/background/profile-bg.jpg" class="card-img cursor-pointer" />
<div class="card-img-overlay" style="height: 95px;">
<div class="d-flex justify-content-end">
<a href="javascript:void(0)" class="btn bg-white text-success py-1 px-2 link" placement="bottom"
ngbTooltip="Save Contact" (click)='saveClick(selectedContact.Id)'>
<i-feather name="save" class="feather-sm"></i-feather>
</a>
<a href="javascript:void(0)" class="btn bg-white text-danger py-1 px-2 link ml-3" placement="bottom"
ngbTooltip="Delete Contact" (click)='deleteClick(selectedContact.Id)'>
<i-feather name="trash-2" class="feather-sm"></i-feather>
<!-- <i class="ti-trash"></i> -->
</a>
<a href="javascript:void(0)" class="btn bg-white text-danger py-1 px-2 link ml-3"
(click)='cancelClick()'>
<i-feather name="x" class="feather-sm"></i-feather>
<!-- <i class="ti-close"></i> -->
</a>
</div>
</div>
<!-- Editable Form here -->
<div>
<form>
<div class="form-group mt-n5 text-center">
<input type="file" style="display: none;" (change)='preview(filevar.files)' #filevar>
<img [src]='selectedContactCopy.Imagepath' class="rounded-circle image cursor-pointer" alt=""
height="100px" width="100px" (click)='filevar.click()'>
<div class="text-center">
<span class="font-weight-normal">Change Image</span>
</div>
</div>
<div class="p-3 position-relative" [perfectScrollbar]="config" style="height: 350px;">
<div class="row">
<div class="col-12 form-group">
<label class="mb-0 text-dark">Name</label>
<input type="text" name="name" [(ngModel)]="selectedContactCopy.Name" class="form-control">
</div>
<div class="col-12 form-group">
<label class="mb-0 text-dark">Job Title</label>
<input type="text" name="Jobtitle" [(ngModel)]="selectedContactCopy.Jobtitle"
class="form-control">
</div>
<div class="col-12 form-group">
<label class="mb-0 text-dark">Company name</label>
<input type="text" name="company" [(ngModel)]="selectedContactCopy.Company"
class="form-control">
</div>
<div class="col-12 form-group">
<label class="mb-0 text-dark">Email</label>
<input type="text" name="email" [(ngModel)]="selectedContactCopy.Email"
class="form-control">
</div>
<div class="col-12 form-group">
<label class="mb-0 text-dark">Phone Number</label>
<input type="text" name="phone" [(ngModel)]="selectedContactCopy.Phonenumber"
class="form-control">
</div>
<div class="col-12 form-group">
<label class="mb-0 text-dark">Location</label>
<input name="address" type="text" [(ngModel)]="selectedContactCopy.Address"
class="form-control">
</div>
<div class="col-12 form-group">
<label class="mb-0 text-dark">Birthdate</label>
<input name="dob" type="date" [(ngModel)]="selectedContactCopy.DOB" class="form-control">
</div>
<div class="col-12 form-group">
<label class="mb-0 text-dark">Description</label>
<textarea name="description" type="text" [(ngModel)]="selectedContactCopy.Description"
class="form-control"></textarea>
</div>
</div>
</div>
</form>
</div>
<!-- end editable form here -->
</div>
</div>
<!-- -------------------------------------------------------------------- -->
<!-- Contact Listing -->
<!-- -------------------------------------------------------------------- -->
<div class="d-md-flex align-items-center bg-white p-3">
<h3 class="mb-0">Contact List</h3>
<div class="ml-auto mt-3 mt-md-0">
<!-- Add Contact -->
<button type="button" class="btn btn-cyan rounded-pill py-2" (click)='addContact()'><i
class="fas fa-plus font-14 mr-1 text-white"></i>
<span class="ml-1 text-white font-weight-bold">Add Contact</span>
</button>
</div>
</div>
<div class="d-md-flex align-items-center border-top bg-white p-3">
<div>
<input type="text" placeholder="Search by Name" class="form-control rounded-pill" [(ngModel)]='searchTerm'>
</div>
<div class="ml-auto mt-3 mt-md-0">
<!-- No. of Contacts-->
<a href="javascript:void(0)" class="d-flex align-items-center p-2 rounded-pill bg-light">
<h5 class="mb-0 mr-1 text-dark font-weight-bold font-14"> Total Contacts
</h5>
<span *ngIf='contactFilter'
class="badge badge-danger badge-pill px-3 font-weight-bold font-14">{{contactFilter.length}}</span>
</a>
</div>
</div>
<div class="table-responsive">
<table class="table bg-white table-hover align-middle mb-0 no-wrap">
<thead>
<tr>
<th>Name</th>
<th scope="col">Email</th>
<th scope="col">Phone Number</th>
<th scope="col">Job title & company</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let co of contactFilter|slice: (page-1) * pageSize : (page-1) * pageSize + pageSize">
<td>
<img [src]='co.Imagepath' class="rounded-circle mr-2" alt="" height="45" width="45">
<span class="text-dark font-medium font-16">{{ co.Name }}</span>
</td>
<td class="align-middle">
<span>
<span class="badge badge-light text-dark rounded-pill font-16 mr-1">
<i-feather name="Mail" class="feather-sm"></i-feather>
</span>
{{ co.Email }}
</span>
</td>
<td class="align-middle">
<span>
<span class="badge badge-light text-dark rounded-pill font-16 mr-1">
<i-feather name="phone" class="feather-sm"></i-feather>
</span>
{{ co.Phonenumber }}
</span>
</td>
<td class="align-middle position-relative">
<span>
<span class="badge badge-light text-dark rounded-pill font-16 mr-1">
<i-feather name="Briefcase" class="feather-sm"></i-feather>
</span>
{{ co.Jobtitle}} , {{co.Company}}
</span>
</td>
<td class="align-middle">
<a href="javascript:void(0)" class="link font-16 font-medium mr-2" (click)='tableRowClicked(co)'>
<i-feather name="edit-3" class="feather-sm"></i-feather>
</a>
<a href="javascript:void(0)" class="link font-16 font-weight-bold" (click)='viewClicked(co)'>
<i-feather name="eye" class="feather-sm"></i-feather>
</a>
</td>
</tr>
</tbody>
</table>
</div>
<div class="d-flex justify-content-center p-2 pt-3 bg-white border-top">
<ngb-pagination [collectionSize]="collectionSize" [(page)]="page" [pageSize]="pageSize">
</ngb-pagination>
</div>
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
import { ContactList } from './contact-list-data';
import { ContactLists } from './contact-list';
import { MailGlobalVariable } from '../mail/mail.service';
@Component({
selector: 'app-contact-list',
templateUrl: './contact-list.component.html',
styleUrls: ['./contact-list.component.css']
})
export class ContactListComponent implements OnInit {
contacts: ContactLists[] = ContactList;
contactFilter: ContactLists[] | null = null;
selectedContact: ContactLists | null = null;
selectedContactCopy: ContactLists | null | any = null;
editable = false;
page = 1;
pageSize = 5;
collectionSize = 0;
_searchTerm = '';
// image.......................................
public imagePath: string | null = null;
imgURL: string | null = null;
public message = '';
constructor(public ms: MailGlobalVariable) {
this.ms.selectedMail = null;
}
ngOnInit() {
this.contactFilter = this.contacts;
this.collectionSize = this.contactFilter.length;
this.selectedContact = null;
}
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this._searchTerm = val;
this.contactFilter = this.filter(val);
}
filter(v: string) {
return this.contacts.filter(x => x.Name.toLowerCase().indexOf(v.toLowerCase()) !== -1);
}
tableRowClicked(contact: ContactLists) {
this.selectedContact = contact;
(document.getElementById('rightMenu') as HTMLFormElement).style.width = '300px';
this.editContact();
}
viewClicked(contact: ContactLists) {
this.selectedContact = contact;
(document.getElementById('rightMenu') as HTMLFormElement).style.width = '300px';
}
closeRightMenu() {
this.editable = false;
this.selectedContact = null;
this.selectedContactCopy = null;
(document.getElementById('rightMenu') as HTMLFormElement).style.width = '0';
}
editContact() {
this.selectedContactCopy = Object.assign({}, this.selectedContact);
this.editable = true;
}
cancelClick() {
this.selectedContact = null;
this.selectedContactCopy = null;
this.closeRightMenu();
}
saveClick(id: number) {
if (this.contactFilter) {
const c: ContactLists | undefined = this.contactFilter.find(con => con.Id === id);
if (c !== undefined && this.selectedContactCopy) {
c.Imagepath = this.selectedContactCopy.Imagepath;
c.Name = this.selectedContactCopy.Name;
c.Tags = this.selectedContactCopy.Tags;
c.Jobtitle = this.selectedContactCopy.Jobtitle;
c.Company = this.selectedContactCopy.Company;
c.Email = this.selectedContactCopy.Email;
c.Phonenumber = this.selectedContactCopy.Phonenumber;
c.Address = this.selectedContactCopy.Address;
c.DOB = this.selectedContactCopy.DOB;
c.Description = this.selectedContactCopy.Description;
this.closeRightMenu();
}
}
}
deleteClick(id: number) {
if (this.contactFilter) {
this.contactFilter = this.contactFilter.filter(user => user.Id !== id);
}
this.collectionSize--;
// id = id - 1;
// this.contacts.splice(id, 1);
this.selectedContact = null;
this.closeRightMenu();
}
addContact() {
const con: ContactLists = new ContactLists();
if (this.contactFilter) {
const n = Math.max.apply(Math,
this.contactFilter.map(function (o) { return o.Id; })) + 1;
con.Id = n;
}
con.Imagepath = '/assets/images/users/1.jpg';
con.Name = 'New Contact';
con.Tags = 'Test';
con.Jobtitle = 'Job Title';
con.Company = 'Company';
con.Email = 'newcontact@gmail.com';
con.Phonenumber = 1111111111;
con.Address = 'City, Country';
con.DOB = new Date;
con.Description = 'Add a Description';
this.contactFilter?.splice(0, 0, con);
this.collectionSize++;
this.tableRowClicked(con);
this.editContact();
}
preview(files: any) {
if (files.length === 0) {
return;
}
const mimeType = files[0].type;
if (mimeType.match(/image\/*/) == null) {
this.message = 'Only images are supported.';
return;
}
const reader = new FileReader();
this.imagePath = files;
reader.readAsDataURL(files[0]);
reader.onload = (_event) => {
this.selectedContactCopy!.Imagepath = reader.result;
};
}
}
export class ContactLists {
Id = 0;
Imagepath: string | null | undefined = '';
Name = '';
Tags = '';
Jobtitle = '';
Company = '';
Email = '';
Phonenumber = 0;
Address = '';
DOB: Date | null = null;
Description = '';
}
import { Contact } from './contact';
export const contacts: Contact[] = [
{
id:1,
firstName: 'Raj',
lastName: 'Dev',
mobile: '979797992',
home: 'jodhpur',
company: ' F creation',
work: 'AD',
notes: ' i qb inujjbw.',
imagePath: 'assets/images/users/5.jpg'
},
{
id:2,
firstName: 'Mark',
lastName: 'Smith',
mobile: '989797772',
home: 'Rajasthan',
company: ' F creation',
work: 'Designer',
notes: ' noyes kns nal sjj s slhjal.',
imagePath: 'assets/images/users/2.jpg'
},
{
id:3,
firstName: 'Jony',
lastName: 'Deep',
mobile: '9234567563',
home: 'LA',
company: ' F creation',
work: 'Admin',
notes: ' admin : baun ja ayu gsiko iaij sikioa...',
imagePath: 'assets/images/users/3.jpg'
},
{
id:4,
firstName: 'Leonardo',
lastName: 'Caprio',
mobile: '7837937777',
home: 'NJ',
company: ' F creation',
work: 'ADMIN',
notes: 'Leo nah ujhakj jjj akkak asdkfga an a .',
imagePath: 'assets/images/users/4.jpg'
}
];
<!-- Mobile toggle button -->
<a [ngClass]="(showSidebar)?'ti-close':'ti-menu'" class="btn btn-success show-left-part d-block d-md-none"
href="javascript:void(0)" (click)="mobileSidebar()"></a>
<div class="main-part">
<!-- Left Part -->
<div class="left-part bg-white fixed-left-part" [ngClass]="{'show-panel': showSidebar}">
<div class="position-relative">
<div class="p-l-15 p-r-25 py-3 d-flex align-items-center border-bottom">
<input type="text" class="form-control" placeholder="Search Contact" [(ngModel)]='searchTerm'>
</div>
<ul class="contact-list list-style-none">
<li class="contact-item border-bottom p-3" *ngFor='let c of filterArray' [class.active]="c === selectedContact"
(click)="onSelect(c);">
<img class="rounded-circle" [src]='c.imagePath' height="40" width="40" />
<span class="ml-3 font-medium">{{c.firstName}}&nbsp;{{c.lastName}}</span>
</li>
</ul>
</div>
</div>
<!-- End Left Part -->
<!-- Right Part -->
<div class="right-part bg-white">
<div class="card">
<div class="">
<button type="button" id="btnAddContact" class="btn btn-primary" (click)='addContact()'>Add New
Contact</button>
<!-- Contact detail -->
<div *ngIf="selectedContact">
<div class="px-3 py-3 d-flex align-items-center border-bottom">
<a href="javascript: void(0);" (click)='editContact()' class="btn btn-success mr-2">
{{editSave}}
</a>
<a href="javascript: void(0);" class="btn btn-danger" (click)='deleteContact(selectedContact)'>
Delete
</a>
</div>
<div class="px-3">
<div class="row" *ngIf="show" (click)="editContact()">
<div class="col-md-2 text-center col-xl-1"><img class="rounded-circle mt-4"
[src]='selectedContact.imagePath' height="100" width="100"></div>
<div class="col-md-8">
<table class="table mt-3 table-lg table-borderless v-middle">
<tbody>
<tr>
<td class="font-bold detail-title">Name</td>
<td class="pl-2">{{selectedContact.firstName}}&nbsp;{{selectedContact.lastName}}</td>
</tr>
<tr>
<td class="font-bold detail-title">Company</td>
<td class="pl-2">{{selectedContact.company}}</td>
</tr>
<tr>
<td class="font-bold detail-title">Work</td>
<td class="pl-2">{{selectedContact.work}}</td>
</tr>
<tr>
<td class="font-bold detail-title">Phone</td>
<td class="pl-2">{{selectedContact.mobile}}</td>
</tr>
<tr>
<td class="font-bold detail-title">Address</td>
<td class="pl-2">{{selectedContact.home}}</td>
</tr>
<tr>
<td class="font-bold detail-title">Note</td>
<td class="pl-2">{{selectedContact.notes}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="mt-4 row" *ngIf="!show">
<div class="col-md-2 text-center col-xl-1"><img class="rounded-circle mt-4 flex-shrink-0"
[src]='selectedContact.imagePath' height="100" width="100"></div>
<div class="col-md-8">
<table class="ml-4 table table-borderless v-middle">
<tbody>
<tr>
<td class="font-bold detail-title">Name</td>
<td class="d-flex">
<input type="text" [(ngModel)]="selectedContact.firstName" class="form-control">
<input type="text" [(ngModel)]="selectedContact.lastName" class="form-control ml-2"></td>
</tr>
<tr>
<td class="font-bold detail-title">Company</td>
<td><input type="text" [(ngModel)]="selectedContact.company" class="form-control"></td>
</tr>
<tr>
<td class="font-bold detail-title">Work</td>
<td><input type="text" [(ngModel)]="selectedContact.work" class="form-control"></td>
</tr>
<tr>
<td class="font-bold detail-title">Phone</td>
<td><input type="text" [(ngModel)]="selectedContact.mobile" class="form-control" maxlength="10">
</td>
</tr>
<tr>
<td class="font-bold detail-title">Address</td>
<td><input type="text" [(ngModel)]="selectedContact.home" class="form-control"></td>
</tr>
<tr>
<td class="font-bold detail-title">Note</td>
<td><textarea [(ngModel)]="selectedContact.notes" class="form-control"></textarea></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- End Contact detail -->
</div>
</div>
</div>
<!-- End Right Part -->
</div>
.detail-title {
width: 80px;
position: relative;
&:after {
content: ":";
position: absolute;
right: 0px;
}
}
.contact-list {
.contact-item {
&:hover {
cursor: pointer;
}
&.active {
background-color: #e9ecef;
}
}
}
#btnAddContact {
position: absolute;
right: 15px;
top: 15px;
}
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ContactRxjsComponent } from './contact-rxjs.component';
describe('ContactRxjsComponent', () => {
let component: ContactRxjsComponent;
let fixture: ComponentFixture<ContactRxjsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ContactRxjsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ContactRxjsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
});
import { Component, OnInit } from '@angular/core';
import { Contact } from './contact';
import { ServiceContactrxjsService } from './service-contactrxjs.service';
@Component({
selector: 'app-contact-rxjs',
templateUrl: './contact-rxjs.component.html',
styleUrls: ['./contact-rxjs.component.scss']
})
export class ContactRxjsComponent implements OnInit {
public showSidebar = false;
contacts: Contact[] = [];
filterArray: Contact[] = [];
selectedContact: Contact | null = null;
show = true;
editSave = 'Edit';
constructor(public contactService: ServiceContactrxjsService) {
this.contactService.getContacts().subscribe((data) => {
this.contacts.push(data);
});
}
ngOnInit() {
this.filterArray = this.contacts;
if (this.contacts.length > 0) {
this.onSelect(this.contacts[0]);
}
}
mobileSidebar() {
this.showSidebar = !this.showSidebar;
}
// search...
_searchTerm = '';
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this._searchTerm = val;
this.filterArray = this.filter(val);
}
filter(v: string) {
return this.contacts.filter(x => x.firstName.toLowerCase().
indexOf(v.toLowerCase()) !== -1 || x.lastName.toLowerCase().indexOf(v.toLowerCase()) !== -1);
}
//on click contact...
onSelect(contact: Contact) {
this.selectedContact = contact;
}
// edit contact...
editContact() {
if (this.editSave === 'Save') {
this.show = true;
this.editSave = 'Edit';
} else {
this.show = false;
this.editSave = 'Save';
}
}
// add contact...
addContact() {
let c: Contact = new Contact()
c.id = Math.max.apply(Math, this.filterArray.map(function (o) { return o.id; })) + 1;
c.firstName = 'First Name';
c.lastName = 'Last Name';
c.mobile = '';
c.home = '';
c.company = '';
c.work = '';
c.notes = '';
c.imagePath = 'assets/images/users/1.jpg';
this.contactService.addContact(c);
this.filterArray.splice(0,0,c);
this.selectedContact = this.filterArray[0];
this.editContact();
}
// delete contact...
deleteContact(contact: Contact) {
this.contactService.deleteContact(contact);
this.filterArray = this.filterArray.filter(con => con.firstName !== contact.firstName && con.lastName !== contact.lastName);
this.selectedContact = null;
}
}
export class Contact {
id=0;
firstName = '';
lastName = '';
mobile = '';
home = '';
company = '';
work = '';
notes = '';
imagePath = '';
}
import { TestBed } from '@angular/core/testing';
import { ServiceContactrxjsService } from './service-contactrxjs.service';
describe('ServiceContactrxjsService', () => {
let service: ServiceContactrxjsService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(ServiceContactrxjsService);
});
// it('should be created', () => {
// expect(service).toBeTruthy();
// });
});
import { Injectable } from '@angular/core';
import { from, Observable } from 'rxjs';
import { Contact } from './contact';
import { contacts } from './contact-data';
@Injectable({
providedIn: 'root'
})
export class ServiceContactrxjsService {
constructor() { }
private contacts: Contact[] = contacts;
// getContacts(): Observable<Contact> {
// You can also fetch data from Api using HttpClient.
// return this.http.get(url..)
// }
getContacts(): Observable<Contact> {
return from(this.contacts)
}
deleteContact(contact: Contact): void {
this.contacts = this.contacts.filter(Contact =>
Contact.firstName !== contact.firstName && Contact.lastName !== contact.lastName);
}
addContact(con: Contact): void {
this.contacts?.push(con);
}
}
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-6 col-lg-3 col-xl-2">
<input type="text" class="form-control form-control-lg" type="text" name="search" [(ngModel)]="searchText"
autocomplete="off" placeholder="Search here...">
</div>
<div class="col-md-6 col-lg-9 col-xl-10 text-md-right mt-4 mt-md-0">
<button class="btn btn-lg btn-cyan text-white" (click)="open(addContactModal)">
<i class="fa fa-plus-square mr-2"></i>Add Contact</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row justify-content-center" *ngIf='contact && contact.length'>
<div class="col-md-4" *ngFor="let c of contact | filter:searchText">
<div class="card">
<div class="card-body text-center">
<img src="{{ c.img }}" class="rounded-circle border p-1" width="100">
<h4 class="card-title mt-3 mb-0">{{ c.name }}</h4>
<small class="text-muted">{{ c.post }}</small>
<div class="mt-3">
<button class="btn btn-info">Chat</button>
<button class="btn btn-light">Follow</button>
</div>
<div class="mt-3 pt-3">
<address>
{{ c.address }}
<br />
<br />
<i class="fas fa-mobile-alt mr-2"></i>{{ c.contactno }}</address>
</div>
</div>
<div class="d-flex text-center justify-content-md-center bg-light border-top">
<div class="col-4 border-right border-bottom py-2">
<a href="javascript:void(0)" class="link">
<i class="icon-social-instagram m-r-10"></i>
{{ c.insta }}
</a>
</div>
<div class="col-4 border-right border-bottom py-2">
<a href="javascript:void(0)" class="link">
<i class="icon-social-linkedin m-r-10"></i>
{{ c.linkedin }}
</a>
</div>
<div class="col-4 py-2 border-bottom">
<a href="javascript:void(0)" class="link">
<i class="icon-social-facebook m-r-10"></i>
{{ c.facebook }}
</a>
</div>
</div>
</div>
</div>
</div>
<!-- Modal -->
<ng-template #addContactModal let-modal>
<div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">Profile update</h4>
<button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form [formGroup]="contacts">
<div class="form-group" [ngClass]="{'has-error':formsErrors.name}">
<label for="contactname">Enter Name Here</label>
<input type="text" class="form-control" required id="contactname" formControlName="name"
(blur)='logValidationErrors(contacts)' placeholder="name here">
<span class="help-block text-danger font-14" *ngIf="formsErrors.name">
{{formsErrors.name}}
</span>
</div>
<div class="form-group" [ngClass]="{'has-error':formsErrors.post}">
<label for="contactpost">Enter Post Here</label>
<input type="text" class="form-control" required id="contactpost" formControlName="post"
(blur)='logValidationErrors(contacts)' placeholder="post here">
<span class="help-block text-danger font-14" *ngIf="formsErrors.post">
{{formsErrors.post}}
</span>
</div>
<div class="form-group" [ngClass]="{'has-error':formsErrors.address}">
<label for="contactadd">Enter Address Here</label>
<input type="text" class="form-control" required id="contactadd" formControlName="address"
(blur)='logValidationErrors(contacts)' placeholder="address here">
<span class="help-block text-danger font-14" *ngIf="formsErrors.address">
{{formsErrors.address}}
</span>
</div>
<div class="form-group" [ngClass]="{'has-error':formsErrors.contactno}">
<label for="contactno">Enter Number Here</label>
<input type="text" class="form-control" required id="contactno" formControlName="contactno"
(blur)='logValidationErrors(contacts)' placeholder="Number here">
<span class="help-block text-danger font-14" *ngIf="formsErrors.contactno">
{{formsErrors.contactno}}
</span>
</div>
<div class="form-group" [ngClass]="{'has-error':formsErrors.insta}">
<label for="contactinsta">Enter Instagram Follower Here</label>
<input type="text" class="form-control" required id="contactinsta" formControlName="insta"
(blur)='logValidationErrors(contacts)' placeholder="Instagram Follower here">
<span class="help-block text-danger font-14" *ngIf="formsErrors.insta">
{{formsErrors.insta}}
</span>
</div>
<div class="form-group" [ngClass]="{'has-error':formsErrors.linkedin}">
<label for="contactlinked">Enter Linkedin Follower Here</label>
<input type="text" class="form-control" required id="contactlinked" formControlName="linkedin"
(blur)='logValidationErrors(contacts)' placeholder="Linkedin Follower here">
<span class="help-block text-danger font-14" *ngIf="formsErrors.linkedin">
{{formsErrors.linkedin}}
</span>
</div>
<div class="form-group" [ngClass]="{'has-error':formsErrors.facebook}">
<label for="contactfacebook">Enter Facebook Follower Here</label>
<input type="text" class="form-control" required id="contactfacebook" formControlName="facebook"
(blur)='logValidationErrors(contacts)' placeholder="Facebook Follower here">
<span class="help-block text-danger font-14" *ngIf="formsErrors.facebook">
{{formsErrors.facebook}}
</span>
</div>
<div class="form-group">
<button type="submit" [disabled]="contacts.invalid" (click)="addContact(); modal.dismiss('Cross click');"
class="btn btn-outline-dark">Add Contact</button>
</div>
</form>
</div>
</ng-template>
import { Component, OnInit } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Contact } from './contact';
@Component({
templateUrl: './contact.component.html'
})
export class ContactComponent implements OnInit {
constructor(private modalService: NgbModal, private fb: FormBuilder) { }
closeResult: string | null = '';
contact: Contact[] = new Array();
searchText: any;
contacts: FormGroup = Object.create(null);
ValidationMessage = {
name: { required: 'Required name.' },
post: { required: 'Required post.' },
address: { required: 'Required address.' },
contactno: {
required: 'Required contactno.',
maxlength: 'Max length is 10 digits.',
pattern: 'Should be numbers only.'
},
insta: {
required: 'Required field.',
maxlength: 'Max length is 5 digits.',
pattern: 'Should be numbers only.'
},
linkedin: {
required: 'Required field.',
maxlength: 'Max length is 5 digits.',
pattern: 'Should be numbers only.'
},
facebook: {
required: 'Required field.',
maxlength: 'Max length is 5 digits.',
pattern: 'Should be numbers only.'
}
};
formsErrors = {};
open(content: string) {
this.modalService.open(content, { size: 'lg', centered: true });
}
ngOnInit() {
this.contacts = this.fb.group({
name: ['', Validators.required],
post: ['', Validators.required],
address: ['', Validators.required],
contactno: ['', [Validators.required, Validators.maxLength(10), Validators.pattern('^[0-9]*$')]],
insta: ['', [Validators.required, Validators.maxLength(5), Validators.pattern('^[0-9]*$')]],
linkedin: ['', [Validators.required, Validators.maxLength(5), Validators.pattern('^[0-9]*$')]],
facebook: ['', [Validators.required, Validators.maxLength(5), Validators.pattern('^[0-9]*$')]],
});
this.contacts.valueChanges.subscribe((d: any) => {
this.logValidationErrors(this.contacts);
});
this.contact = [
{
img: 'assets/images/users/2.jpg',
name: 'Johnathan Doe',
post: 'Web Designer',
address: '795 Folsom Ave, Suite 600 San Francisco, CADGE 94107',
contactno: 1234567890,
insta: 254,
linkedin: 54,
facebook: 154
},
{
img: 'assets/images/users/8.jpg',
name: 'Oliver Smith',
post: 'Theme Designer',
address: '55 E 11th St #1OTH, Suite 600 New York, NY, 10003 ',
contactno: 2122288403,
insta: 150,
linkedin: 14,
facebook: 165
},
{
img: 'assets/images/users/4.jpg',
name: 'George Johnson',
post: 'Front End Developer',
address: '36 W 138th St, San Francisco New York, NY, 10037',
contactno: 2122341783,
insta: 300,
linkedin: 65,
facebook: 130
},
{
img: 'assets/images/users/5.jpg',
name: 'Harry Potter',
post: 'Hacker',
address: '2289 5th Ave, Suite 600 San Francisco New York, NY, 10037',
contactno: 2124568403,
insta: 220,
linkedin: 38,
facebook: 178
},
{
img: 'assets/images/users/6.jpg',
name: 'Jack Williams',
post: 'Back End Developer',
address: '425 5th Ave, San Francisco New York, NY, 10016',
contactno: 1544568745,
insta: 650,
linkedin: 150,
facebook: 195
},
{
img: 'assets/images/users/7.jpg',
name: 'Jacob Jones',
post: 'Graphics Designer',
address: '17 Stuyvesant Walk, Suite 600 New York, NY, 10009',
contactno: 1507847890,
insta: 151,
linkedin: 29,
facebook: 160
}
];
}
logValidationErrors(group: FormGroup) {
// Object.keys(group.controls).forEach((key: string) => {
// const ac = group.get(key);
// this.formsErrors[key] = '';
// if (ac && !ac.valid && (ac.touched || ac.dirty)) {
// const message = this.ValidationMessage[key];
// for (const errorKey in ac.errors) {
// if (errorKey) {
// this.formsErrors[key] += message[errorKey] + ' ';
// }
// }
// }
// if (ac instanceof FormGroup) {
// this.logValidationErrors(ac)
// }
// })
}
addContact() {
const cnt: Contact = new Contact();
cnt.img = 'assets/images/users/6.jpg';
if (this.contacts != null) {
cnt.name = this.contacts?.get('name')?.value;
}
cnt.post = this.contacts?.get('post')?.value;
cnt.address = this.contacts?.get('address')?.value;
cnt.contactno = this.contacts?.get('contactno')?.value;
cnt.insta = this.contacts?.get('insta')?.value;
cnt.linkedin = this.contacts?.get('linkedin')?.value;
cnt.facebook = this.contacts?.get('facebook')?.value;
this.contact.push(cnt);
}
}
export class Contact {
img = '';
name = '';
post = '';
address = '';
contactno = 0;
insta = 0;
linkedin = 0;
facebook = 0;
}
import { Contact } from './contact';
export const contacts: Contact[] = [
{
firstName: 'Raj',
lastName: 'Dev',
mobile: '979797992',
home: 'jodhpur',
company: ' F creation',
work: 'AD',
notes: ' i qb inujjbw.',
imagePath: 'assets/images/users/5.jpg'
},
{
firstName: 'Mark',
lastName: 'Smith',
mobile: '989797772',
home: 'Rajasthan',
company: ' F creation',
work: 'Designer',
notes: ' noyes kns nal sjj s slhjal.',
imagePath: 'assets/images/users/2.jpg'
},
{
firstName: 'Jony',
lastName: 'Deep',
mobile: '9234567563',
home: 'LA',
company: ' F creation',
work: 'Admin',
notes: ' admin : baun ja ayu gsiko iaij sikioa...',
imagePath: 'assets/images/users/3.jpg'
},
{
firstName: 'Leonardo',
lastName: 'Caprio',
mobile: '7837937777',
home: 'NJ',
company: ' F creation',
work: 'ADMIN',
notes: 'Leo nah ujhakj jjj akkak asdkfga an a .',
imagePath: 'assets/images/users/4.jpg'
}
];
import { Injectable } from '@angular/core';
import { Contact } from './contact';
import { contacts } from './contact-data';
@Injectable()
export class ContactService {
public contacts: Contact[] = contacts;
public getContacts() {
return this.contacts;
}
}
export class Contact {
firstName = '';
lastName = '';
mobile = '';
home = '';
company = '';
work = '';
notes = '';
imagePath = '';
}
<!-- Mobile toggle button -->
<a [ngClass]="(showSidebar)?'ti-close':'ti-menu'" class="btn btn-success show-left-part d-block d-md-none"
href="javascript:void(0)" (click)="mobileSidebar()"></a>
<div class="main-part">
<!-- Left Part -->
<div class="left-part bg-white fixed-left-part" [ngClass]="{'show-panel': showSidebar}">
<div class="position-relative">
<div class="p-l-15 p-r-25 py-3 d-flex align-items-center border-bottom">
<input type="text" class="form-control" placeholder="Search Contact" [(ngModel)]='searchTerm'>
</div>
<ul class="contact-list list-style-none">
<li class="contact-item border-bottom p-3" *ngFor='let c of filterArray' [class.active]="c === selectedContact"
(click)="onSelect(c);">
<img class="rounded-circle" [src]='c.imagePath' height="40" width="40" />
<span class="ml-3 font-medium">{{c.firstName}}&nbsp;{{c.lastName}}</span>
</li>
</ul>
</div>
</div>
<!-- End Left Part -->
<!-- Right Part -->
<div class="right-part bg-white">
<div class="card">
<div class="">
<button type="button" id="btnAddContact" class="btn btn-primary" (click)='addContact()'>Add New
Contact</button>
<!-- Contact detail -->
<div *ngIf="selectedContact">
<div class="px-3 py-3 d-flex align-items-center border-bottom">
<a href="javascript: void(0);" (click)='editContact()' class="btn btn-success mr-2">
{{editSave}}
</a>
<a href="javascript: void(0);" class="btn btn-danger" (click)='deleteContact(selectedContact)'>
Delete
</a>
</div>
<div class="px-3">
<div class="row" *ngIf="show" (click)="editContact()">
<div class="col-md-2 text-center col-xl-1"><img class="rounded-circle mt-4"
[src]='selectedContact.imagePath' height="100" width="100"></div>
<div class="col-md-8">
<table class="table mt-3 table-lg table-borderless v-middle">
<tbody>
<tr>
<td class="font-bold detail-title">Name</td>
<td class="pl-2">{{selectedContact.firstName}}&nbsp;{{selectedContact.lastName}}</td>
</tr>
<tr>
<td class="font-bold detail-title">Company</td>
<td class="pl-2">{{selectedContact.company}}</td>
</tr>
<tr>
<td class="font-bold detail-title">Work</td>
<td class="pl-2">{{selectedContact.work}}</td>
</tr>
<tr>
<td class="font-bold detail-title">Phone</td>
<td class="pl-2">{{selectedContact.mobile}}</td>
</tr>
<tr>
<td class="font-bold detail-title">Address</td>
<td class="pl-2">{{selectedContact.home}}</td>
</tr>
<tr>
<td class="font-bold detail-title">Note</td>
<td class="pl-2">{{selectedContact.notes}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="mt-4 row" *ngIf="!show">
<div class="col-md-2 text-center col-xl-1"><img class="rounded-circle mt-4 flex-shrink-0"
[src]='selectedContact.imagePath' height="100" width="100"></div>
<div class="col-md-8">
<table class="ml-4 table table-borderless v-middle">
<tbody>
<tr>
<td class="font-bold detail-title">Name</td>
<td class="d-flex">
<input type="text" [(ngModel)]="selectedContact.firstName" class="form-control">
<input type="text" [(ngModel)]="selectedContact.lastName" class="form-control ml-2"></td>
</tr>
<tr>
<td class="font-bold detail-title">Company</td>
<td><input type="text" [(ngModel)]="selectedContact.company" class="form-control"></td>
</tr>
<tr>
<td class="font-bold detail-title">Work</td>
<td><input type="text" [(ngModel)]="selectedContact.work" class="form-control"></td>
</tr>
<tr>
<td class="font-bold detail-title">Phone</td>
<td><input type="text" [(ngModel)]="selectedContact.mobile" class="form-control" maxlength="10">
</td>
</tr>
<tr>
<td class="font-bold detail-title">Address</td>
<td><input type="text" [(ngModel)]="selectedContact.home" class="form-control"></td>
</tr>
<tr>
<td class="font-bold detail-title">Note</td>
<td><textarea [(ngModel)]="selectedContact.notes" class="form-control"></textarea></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- End Contact detail -->
</div>
</div>
</div>
<!-- End Right Part -->
</div>
.detail-title {
width: 80px;
position: relative;
&:after {
content: ":";
position: absolute;
right: 0px;
}
}
.contact-list {
.contact-item {
&:hover {
cursor: pointer;
}
&.active {
background-color: #e9ecef;
}
}
}
#btnAddContact {
position: absolute;
right: 15px;
top: 15px;
}
import { Component, OnInit } from '@angular/core';
import { Contact } from './contact';
import { ContactService } from './contact.service';
@Component({
selector: 'app-contacts',
templateUrl: './contacts.component.html',
styleUrls: ['./contacts.component.scss']
})
export class ContactsComponent implements OnInit {
public showSidebar = false;
contacts = this.contactService.getContacts();
selectedContact: Contact | null = null;
show = true;
editSave = 'Edit';
filterArray: Contact[] = [];
_searchTerm = '';
mobileSidebar() {
this.showSidebar = !this.showSidebar;
}
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this._searchTerm = val;
this.filterArray = this.filter(val);
}
filter(v: string) {
return this.contacts.filter(x => x.firstName.toLowerCase().
indexOf(v.toLowerCase()) !== -1 || x.lastName.toLowerCase().indexOf(v.toLowerCase()) !== -1);
}
constructor(public contactService: ContactService) {
}
ngOnInit() {
this.filterArray = this.contacts;
if (this.contacts.length > 0) {
this.onSelect(this.contacts[0]);
}
}
onSelect(contact: Contact) {
this.selectedContact = contact;
}
editContact() {
if (this.editSave === 'Save') {
this.show = true;
this.editSave = 'Edit';
} else {
this.show = false;
this.editSave = 'Save';
}
}
addContact() {
this.contacts.push({
firstName: 'Enter',
lastName: 'Name',
mobile: '',
home: '',
company: '',
work: '',
notes: '',
imagePath: 'assets/images/users/1.jpg'
});
this.filterArray = this.contacts;
this.selectedContact = this.filterArray[this.filterArray.length - 1];
this.editContact();
}
deleteContact(i: Contact) {
this.contacts = this.contacts.filter(con => con.firstName !== i.firstName);
this.filterArray = this.contacts.filter(con => con.firstName !== i.firstName);
// if(this.filterArray.length>0)
this.selectedContact = null;
}
}
<div class="event-dialog-wrapper">
<mat-toolbar matDialogTitle class="mat-primary m-0">
<div fxFlex fxLayout="row" fxLayoutAlign="space-between center">
<span class="title dialog-title">{{dialogTitle}}</span>
<button mat-icon-button (click)="dialogRef.close()" aria-label="Close dialog">
<mat-icon>close</mat-icon>
</button>
</div>
</mat-toolbar>
<div mat-dialog-content class="p-16 m-0">
<form name="eventForm" [formGroup]="eventForm" class="event-form" fxFlex>
<div fxLayout="row wrap" fxLayout.lt-sm="column">
<div fxFlex="100">
<mat-form-field class="full-width">
<input
matInput
name="title"
formControlName="title"
placeholder="Title"
required>
</mat-form-field>
</div>
<div fxLayout="row" fxLayout.lt-sm="column" fxFlex="100" formGroupName="color">
<mat-form-field fxFlex>
<input
matInput
class="color-picker-input"
name="primaryColor"
formControlName="primary"
placeholder="Primary color"
type="color"
[style.background]="event.color.primary"
(colorPickerChange)="eventForm.patchValue({color:{primary: event.color.primary}})"
/>
</mat-form-field>
<span fxFlex="16px"></span>
<mat-form-field fxFlex>
<input
matInput
class="color-picker-input"
name="secondaryColor"
formControlName="secondary"
placeholder="Secondary color"
type="color"
[style.background]="event.color.secondary"
(colorPickerChange)="eventForm.patchValue({color:{secondary: event.color.secondary}})"
/>
</mat-form-field>
</div>
<div fxLayout="row" fxLayout.lt-sm="column" fxFlex="100">
<mat-form-field fxFlex>
<input
matInput
[matDatepicker]="startDateDP"
placeholder="Start Date"
name="startDate"
formControlName="start">
<mat-datepicker-toggle matSuffix [for]="startDateDP"></mat-datepicker-toggle>
<mat-datepicker #startDateDP></mat-datepicker>
</mat-form-field>
<span fxFlex="16px"></span>
<mat-form-field fxFlex>
<input
matInput
[matDatepicker]="endDateDP"
placeholder="End Date"
name="endDate"
formControlName="end">
<mat-datepicker-toggle matSuffix [for]="endDateDP"></mat-datepicker-toggle>
<mat-datepicker #endDateDP></mat-datepicker>
</mat-form-field>
</div>
<div fxLayout="column" fxFlex="100">
<mat-form-field formGroupName="meta" class="">
<input
matInput
name="location"
formControlName="location"
placeholder="Location">
</mat-form-field>
<mat-form-field formGroupName="meta" class="">
<textarea
matInput
formControlName="notes"
placeholder="Notes"
max-rows="4">
</textarea>
</mat-form-field>
</div>
</div>
</form>
</div>
<div mat-dialog-actions class="m-0 p-16" fxLayout="row" fxLayoutAlign="space-between center">
<button
mat-raised-button
color="primary"
(click)="dialogRef.close({action: 'save', event: eventForm.value})"
[disabled]="eventForm.invalid"
aria-label="SAVE">
Save
</button>
<button
*ngIf="action ==='edit'"
mat-icon-button color="warn"
(click)="dialogRef.close({action: 'delete'})"
aria-label="Delete"
matTooltip="Delete">
<mat-icon>delete</mat-icon>
</button>
</div>
</div>
\ No newline at end of file
import { Component, Inject, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { CalendarEvent } from 'angular-calendar';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { EgretCalendarEvent} from '../event.model';
interface DialogData {
event?: CalendarEvent,
action?: string,
date?: Date
}
@Component({
selector: 'app-calendar-form-dialog',
templateUrl: './calendar-form-dialog.component.html',
styleUrls: ['./calendar-form-dialog.component.scss']
})
export class CalendarFormDialogComponent implements OnInit {
event:any
dialogTitle: string;
eventForm: FormGroup;
action: any;
constructor(
public dialogRef: MatDialogRef<CalendarFormDialogComponent>,
@Inject(MAT_DIALOG_DATA) private data: DialogData,
private formBuilder: FormBuilder
) {
this.event = data.event;
this.action = data.action;
if (this.action === 'edit') {
this.dialogTitle = this.event.title;
} else {
this.dialogTitle = 'Add Event';
this.event = new EgretCalendarEvent({
start: data.date,
end: data.date
});
}
// console.log(data);
this.eventForm = this.buildEventForm(this.event);
}
ngOnInit() {
}
buildEventForm(event: any) {
return new FormGroup({
_id: new FormControl(event._id),
title: new FormControl(event.title),
start: new FormControl(event.start),
end: new FormControl(event.end),
allDay: new FormControl(event.allDay),
color: this.formBuilder.group({
primary: new FormControl(event.color.primary),
secondary: new FormControl(event.color.secondary)
}),
meta: this.formBuilder.group({
location: new FormControl(event.meta.location),
notes: new FormControl(event.meta.notes)
}),
draggable:new FormControl(true),
});
}
}
import { CalendarEventAction, CalendarEvent } from 'angular-calendar';
import {
startOfDay,
endOfDay,
subDays,
addDays,
endOfMonth,
isSameDay,
isSameMonth,
addHours
} from 'date-fns';
export class EgretCalendarEvent implements CalendarEvent {
_id?: string;
start: Date;
end: Date ;
title: string;
color?: {
primary: string;
secondary: string;
};
actions?: CalendarEventAction[];
allDay?: boolean;
cssClass?: string;
resizable?: {
beforeStart?: boolean;
afterEnd?: boolean;
};
draggable?: boolean;
meta?: {
location: string,
notes: string
};
constructor(data:any) {
data = data || {};
this.start = new Date(data.start) || startOfDay(new Date());
this.end = new Date(data.end);
this._id = data._id || '';
this.title = data.title || '';
this.color = {
primary: data.color && data.color.primary || '#247ba0',
secondary: data.color && data.color.secondary || '#D1E8FF'
};
this.draggable = data.draggable || true;
this.resizable = {
beforeStart: data.resizable && data.resizable.beforeStart || true,
afterEnd: data.resizable && data.resizable.afterEnd || true
};
this.actions = data.actions || [];
this.allDay = data.allDay || false;
this.cssClass = data.cssClass || '';
this.meta = {
location: data.meta && data.meta.location || '',
notes: data.meta && data.meta.notes || ''
};
}
}
<div class="card">
<div class="card-body">
<!-- ============================================================== -->
<!-- Top Buttons -->
<!-- ============================================================== -->
<h3>
Angular Calendar
<button class="btn btn-primary float-right" (click)="addEvent()">
Add New Event
</button>
<div class="clearfix"></div>
</h3>
<hr>
<div class="pt-3 row">
<div class="col-md-4">
<div class="btn-group">
<div class="btn btn-success" mwlCalendarPreviousView [view]="view" [(viewDate)]="viewDate"
(viewDateChange)="activeDayIsOpen = false">
Previous </div>
<div class="btn btn-outline-secondary" mwlCalendarToday [(viewDate)]="viewDate"> Today </div>
<div class="btn btn-info" mwlCalendarNextView [view]="view" [(viewDate)]="viewDate"
(viewDateChange)="activeDayIsOpen = false">
Next </div>
</div>
</div>
<div class="col-md-4 text-center">
<h3>{{ viewDate | calendarDate:(view + 'ViewTitle'):'en' }}</h3>
</div>
<div class="col-md-4 text-right">
<div class="btn-group">
<div class="btn btn-info" (click)="setView(CalendarView.Month)" [class.active]="view === CalendarView.Month">
Month </div>
<div class="btn btn-success" (click)="setView(CalendarView.Week)" [class.active]="view === CalendarView.Week">
Week </div>
<div class="btn btn-warning" (click)="setView(CalendarView.Day)" [class.active]="view === CalendarView.Day">
Day </div>
</div>
</div>
</div>
<br>
<!-- ============================================================== -->
<!-- Calander Area -->
<!-- ============================================================== -->
<div [ngSwitch]="view">
<mwl-calendar-month-view *ngSwitchCase="CalendarView.Month" [viewDate]="viewDate" [events]="events"
[refresh]="refresh" [activeDayIsOpen]="activeDayIsOpen" (dayClicked)="dayClicked($event.day)"
(eventClicked)="handleEvent('Clicked', $event.event)" (eventTimesChanged)="eventTimesChanged($event)">
</mwl-calendar-month-view>
<mwl-calendar-week-view *ngSwitchCase="CalendarView.Week" [viewDate]="viewDate" [events]="events"
[refresh]="refresh" (eventClicked)="handleEvent('Clicked', $event.event)"
(eventTimesChanged)="eventTimesChanged($event)">
</mwl-calendar-week-view>
<mwl-calendar-day-view *ngSwitchCase="CalendarView.Day" [viewDate]="viewDate" [events]="events"
[refresh]="refresh" (eventClicked)="handleEvent('Clicked', $event.event)"
(eventTimesChanged)="eventTimesChanged($event)">
</mwl-calendar-day-view>
</div>
<br /><br />
<hr>
<br />
<!-- ============================================================== -->
<!-- Edit Evenets -->
<!-- ============================================================== -->
<h3>
Edit events
<button class="btn btn-primary float-right" (click)="addEvent()">
Add new
</button>
<div class="clearfix"></div>
</h3>
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th>Title</th>
<th>Primary color</th>
<th>Secondary color</th>
<th>Starts at</th>
<th>Ends at</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let event of events">
<td>
<input type="text" class="form-control" [(ngModel)]="event.title" (keyup)="refresh.next()" />
</td>
<td>
<input type="color" [(ngModel)]="event.color.primary" (change)="refresh.next()" />
</td>
<td>
<input type="color" [(ngModel)]="event.color.secondary" (change)="refresh.next()" />
</td>
<td>
<input class="form-control bg-white" type="text" mwlFlatpickr [(ngModel)]="event.start"
(ngModelChange)="refresh.next()" [altInput]="true" [convertModelValue]="true" [enableTime]="true"
dateFormat="Y-m-dTH:i" altFormat="F j, Y H:i" placeholder="Not set" />
</td>
<td>
<input class="form-control bg-white" type="text" mwlFlatpickr [(ngModel)]="event.end"
(ngModelChange)="refresh.next()" [altInput]="true" [convertModelValue]="true" [enableTime]="true"
dateFormat="Y-m-dTH:i" altFormat="F j, Y H:i" placeholder="Not set" />
</td>
<td>
<button class="btn btn-danger" (click)="deleteEvent(event)">
Delete
</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- ============================================================== -->
<!-- Event Popup -->
<!-- ============================================================== -->
<ng-template #modalContent let-close="close">
<div class="modal-header">
<h5 class="modal-title">Event {{ modalData?.action }}</h5>
<button type="button" class="close" (click)="close()">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body" >
{{ modalData?.action }}
<!-- Event if Edited -->
<div *ngIf="modalData?.action === 'Edit'">
<h5>Event Title</h5>
<input type="text" class="form-control" [(ngModel)]="modalData?.event.title" (keyup)="refresh.next()" />
<div class="row">
<div class="col-md-12">
<h5 class="mt-3">Event Color</h5>
<input type="color" [(ngModel)]="modalData?.event.color.primary" (change)="refresh.next()"
width="500px" />
</div>
</div>
<div class="row">
<div class="col-md-6">
<h5 class="mt-3">Event Start</h5>
<input class="form-control bg-white" type="text" mwlFlatpickr [(ngModel)]="modalData?.event.start"
(ngModelChange)="refresh.next()" [altInput]="true" [convertModelValue]="true" [enableTime]="true"
dateFormat="Y-m-dTH:i" altFormat="F j, Y H:i" placeholder="Not set" />
</div>
<div class="col-md-6">
<h5 class="mt-3">Event End</h5>
<input class="form-control bg-white" type="text" mwlFlatpickr [(ngModel)]="modalData?.event.end"
(ngModelChange)="refresh.next()" [altInput]="true" [convertModelValue]="true" [enableTime]="true"
dateFormat="Y-m-dTH:i" altFormat="F j, Y H:i" placeholder="Not set" />
</div>
<button type="button" class="btn btn-primary mt-4 ml-3" (click)="close()">
OK
</button>
</div>
</div>
</div>
</ng-template>
<ng-template #modalContentAdd let-close="close">
<div class="modal-header">
<h5 class="modal-title">Add Event</h5>
<button type="button" class="close" (click)="close()">
<span aria-hidden="true">&times;</span>
</button>
</div>
<form #add="ngForm" (ngSubmit)="onSubmit(add)">
<div class="modal-body">
<h5>Event Title</h5>
<input type="text" class="form-control" (keyup)="refresh.next()" required name="title" ngModel />
<h5 class="mt-3">Event Color</h5>
<input type="color" (change)="refresh.next()" name="color" ngModel />
<div class="row">
<div class="col-md-6">
<h5 class="mt-3">Event Start</h5>
<input class="form-control bg-white" type="text" name="startDate" ngModel mwlFlatpickr
(ngModelChange)="refresh.next()" [altInput]="true" [convertModelValue]="true" [enableTime]="true"
dateFormat="Y-m-dTH:i" altFormat="F j, Y H:i" placeholder="Not set" required/>
</div>
<div class="col-md-6">
<h5 class="mt-3">Event End</h5>
<input class="form-control bg-white" type="text" name="endDate" ngModel mwlFlatpickr
(ngModelChange)="refresh.next()" [altInput]="true" [convertModelValue]="true" [enableTime]="true"
dateFormat="Y-m-dTH:i" altFormat="F j, Y H:i" placeholder="Not set" />
</div>
<button type="submit" class="btn btn-primary mt-4 ml-3" [disabled]="add.invalid">Add Event</button>
</div>
</div>
</form>
</ng-template>
</div>
</div>
\ No newline at end of file
input[type="color"] {
-webkit-appearance: none;
border: none;
width: 100%;
}
input[type="color"]::-webkit-color-swatch-wrapper {
padding: 0;
}
input[type="color"]::-webkit-color-swatch {
border: none;
}
\ No newline at end of file
import {
Component,
ChangeDetectionStrategy,
ViewChild,
TemplateRef
} from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import {
startOfDay,
endOfDay,
subDays,
addDays,
endOfMonth,
isSameDay,
isSameMonth,
addHours
} from 'date-fns';
import { Subject } from 'rxjs';
import {
CalendarEvent,
CalendarEventAction,
CalendarEventTimesChangedEvent,
CalendarView,
} from 'angular-calendar';
import { NgForm } from '@angular/forms';
const colors: any = {
red: {
primary: '#ff5c6c',
secondary: '#FAE3E3'
},
blue: {
primary: '#1e90ff',
secondary: '#D1E8FF'
},
yellow: {
primary: '#24d2b5',
secondary: '#FDF1BA'
}
};
@Component({
selector: 'app-fullcalendar',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './fullcalendar.component.html',
styleUrls: ['./fullcalendar.component.scss']
})
export class FullcalendarComponent {
@ViewChild('modalContent', { static: true }) modalContent!: TemplateRef<any>;
@ViewChild('modalContentAdd', { static: true }) modalContentAdd!: TemplateRef<any>;
view: CalendarView = CalendarView.Month;
CalendarView = CalendarView;
viewDate: Date = new Date();
/*/////////////////////////////////////
Event action buttons
////////////////////////////////////*/
actions: CalendarEventAction[] = [
{
label: '<span class="badge badge-info ml-1"><i class="ti-pencil"></i></span>',
a11yLabel: 'Edit',
onClick: ({ event }: { event: CalendarEvent }): void => {
this.handleEvent('Edit', event);
},
},
{
label: '<span class="badge badge-danger ml-1"><i class="ti-trash"></i></span>',
a11yLabel: 'Delete',
onClick: ({ event }: { event: CalendarEvent }): void => {
this.events = this.events.filter((iEvent) => iEvent !== event);
this.handleEvent('Deleted', event);
},
},
];
refresh: Subject<any> = new Subject();
/*/////////////////////////////////////
Default Events added
////////////////////////////////////*/
events: CalendarEvent[] = [
{
start: subDays(startOfDay(new Date()), 1),
end: addDays(new Date(), 1),
title: 'A 3 day event',
color: colors.red,
actions: this.actions,
allDay: true,
resizable: {
beforeStart: true,
afterEnd: true,
},
draggable: true,
},
{
start: startOfDay(new Date()),
title: 'An event with no end date',
color: colors.yellow,
actions: this.actions,
},
{
start: subDays(endOfMonth(new Date()), 3),
end: addDays(endOfMonth(new Date()), 3),
title: 'A long event that spans 2 months',
color: colors.blue,
allDay: true,
},
{
start: addHours(startOfDay(new Date()), 2),
end: addHours(new Date(), 2),
title: 'A draggable and resizable event',
color: colors.yellow,
actions: this.actions,
resizable: {
beforeStart: true,
afterEnd: true,
},
draggable: true,
},
];
activeDayIsOpen: boolean = true;
modalData!: {
action: string;
event: CalendarEvent;
};
constructor(private modal: NgbModal) {
}
/*/////////////////////////////////////
On Day Click
////////////////////////////////////*/
dayClicked({ date, events }: { date: Date; events: CalendarEvent[] }): void {
if (isSameMonth(date, this.viewDate)) {
if (
(isSameDay(this.viewDate, date) && this.activeDayIsOpen === true) ||
events.length === 0
) {
this.activeDayIsOpen = false;
} else {
this.activeDayIsOpen = true;
}
this.viewDate = date;
}
}
eventTimesChanged({
event,
newStart,
newEnd,
}: CalendarEventTimesChangedEvent): void {
this.events = this.events.map((iEvent) => {
if (iEvent === event) {
return {
...event,
start: newStart,
end: newEnd,
};
}
return iEvent;
});
this.handleEvent('Dropped or resized', event);
}
handleEvent(action: string, event: CalendarEvent): void {
this.modalData = { event, action };
this.modal.open(this.modalContent, { size: 'lg' });
}
/*/////////////////////////////////////
Add Event
////////////////////////////////////*/
addEvent(): void {
this.modal.open(this.modalContentAdd, {
size: 'lg',
});
}
/*/////////////////////////////////////
Delete Event
////////////////////////////////////*/
deleteEvent(eventToDelete: CalendarEvent) {
this.events = this.events.filter((event) => event !== eventToDelete);
}
setView(view: CalendarView) {
this.view = view;
}
closeOpenMonthViewDay() {
this.activeDayIsOpen = false;
}
onSubmit(data: NgForm) {
this.events = [
...this.events,
{
title: data.value.title,
start: data.value.startDate,
end: data.value.endDate,
color: data.value.color,
actions: this.actions,
allDay: true,
resizable: {
beforeStart: true,
afterEnd: true,
},
draggable: true,
},
];
this.modal.dismissAll();
}
}
<div class="card">
<div class="card-body">
<form #invoiceForm='ngForm'>
<div class="row mb-3">
<div class="col-md-6">
<h4 class="mb-0">Invoice Id : # <span name="id" [(ngModel)]='invoice.id' ngDefaultControl>
{{invoice.id}}</span></h4>
</div>
<div class="col-md-6 mt-3 mt-md-0">
<div class="row justify-content-end">
<div class="col-lg-3 col-md-4 col-6">
<a routerLink='/apps/invoice'
class="btn btn-outline-danger shadow-sm font-medium btn-block">
Cancel
</a>
</div>
<div class="col-lg-3 col-md-4 col-6">
<button type="button" class="btn btn-outline-success shadow-sm font-medium btn-block"
(click)=saveDetail() [disabled]="addForm.invalid">Save</button>
</div>
</div>
</div>
</div>
<div class="d-flex align-items-center border-top pt-3 pb-3 border-bottom">
<div>
<h5>Order Status : </h5>
<select class="form-control mt-2" name="satus" [(ngModel)]='invoice.status'>
<option value="Pending">Pending</option>
<option value="Shipped">Shipped</option>
<option value="Delivered">Delivered</option>
</select>
</div>
<div class="ml-auto">
<h5>Order Date</h5>
<span name="date" [(ngModel)]='invoice.orderDate'
ngDefaultControl>{{invoice.orderDate | date: 'dd-MM-yyyy'}}</span>
</div>
</div>
<div class="row mt-4">
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" placeholder="Bill From" name="from"
[(ngModel)]='invoice.billFrom'>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" placeholder="Bill To" name="to"
[(ngModel)]='invoice.billTo'>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<textarea class="form-control" rows="3" placeholder="Enter From Address" name="fromAddress"
[(ngModel)]='invoice.billFromAddress'></textarea>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<textarea class="form-control" rows="3" placeholder="Enter To Address" name="toAddress"
[(ngModel)]='invoice.billToAddress'></textarea>
</div>
</div>
</div>
</form>
<div [formGroup]="addForm">
<div class="table-responsive">
<table class="table table-hover table-bordered no-wrap v-middle">
<thead>
<tr>
<th class="border-bottom-0">#</th>
<th class="border-bottom-0">Item Name</th>
<th class="border-bottom-0">Unit Price</th>
<th class="border-bottom-0">Units</th>
<th class="border-bottom-0">Unit Total Price</th>
<th class="border-bottom-0"></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of addForm.get('rows')?.controls;let index = index;">
<td>
{{index+1}}
</td>
<td>
<input type="text" class="form-control" [formControl]="row.get('itemName')"
(input)="itemsChanged()">
</td>
<td>
<input type="number" class="form-control" min=1 [formControl]="row.get('unitPrice')"
(input)="itemsChanged()">
</td>
<td>
<input type="number" class="form-control" min=1 [formControl]="row.get('units')"
(input)="itemsChanged()">
</td>
<td>
<input disabled class="form-control" [formControl]="row.get('itemTotal')"
[value]="row.get('unitPrice').value * row.get('units').value">
</td>
<td>
<span *ngIf='index > 0'>
<button type="button" class="btn btn-danger"
(click)="onRemoveRow(index)">Remove</button>
</span>
</td>
</tr>
</tbody>
</table>
</div>
<div class="text-right">
<button type="button" class="btn btn-info" (click)="onAddRow()" [disabled]="addForm.invalid"
*ngIf="addForm.get('rows')">Add row</button>
<div class="border-top mt-3 pt-3">
<h5><span>Sub total </span> : {{subTotal}}</h5>
</div>
<div class="border-top mt-3 pt-3">
<h5>Total Vat:</h5>
<div class="row justify-content-end">
<div class="col-lg-2 col-md-4">
<div class="input-group mb-3">
<input type="number" class="form-control" value="10">
<div class="input-group-append">
<span class="input-group-text">%</span>
<span class="input-group-text bg-white font-medium">: {{vat}}</span>
</div>
</div>
</div>
</div>
</div>
<hr />
<h3><span class="font-weight-bold mr-2">Total:</span>${{grandTotal}} </h3>
</div>
</div>
</div>
</div>
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AddInvoiceComponent } from './add-invoice.component';
describe('AddInvoiceComponent', () => {
let component: AddInvoiceComponent;
let fixture: ComponentFixture<AddInvoiceComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AddInvoiceComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AddInvoiceComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
});
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl, FormArray, NgForm } from '@angular/forms';
import { order, InvoiceList } from '../invoice';
import { InvoiceService } from '../invoice.service';
import { Router } from '@angular/router';
@Component({
selector: 'app-add-invoice',
templateUrl: './add-invoice.component.html',
styleUrls: ['./add-invoice.component.css']
})
export class AddInvoiceComponent implements OnInit {
// selected = 'option1';
// date = new Date();
addForm: FormGroup;
rows: FormArray;
invoice: InvoiceList = new InvoiceList();
///////////////////////////////////////////////////////////
subTotal = 0;
vat = 0;
grandTotal = 0;
constructor(private fb: FormBuilder, private invoiceService: InvoiceService,private router: Router) {
this.invoice.id =
Math.max.apply(Math, this.invoiceService.getInvoiceList().map(function (o) { return o.id; })) + 1;
this.invoice.status = 'Pending'
///////////////////////////////////////////////////////////
this.addForm = this.fb.group({
});
this.rows = this.fb.array([]);
this.addForm.addControl('rows', this.rows);
this.rows.push(this.createItemFormGroup());
}
ngOnInit(): void {
}
////////////////////////////////////////////////////////////////////////////////////
onAddRow() {
this.rows.push(this.createItemFormGroup());
}
onRemoveRow(rowIndex: number) {
let totalCostOfItem = this.addForm.get('rows')?.value[rowIndex].unitPrice *
this.addForm.get('rows')?.value[rowIndex].units;
this.subTotal = this.subTotal - totalCostOfItem;
this.vat = this.subTotal / 10;
this.grandTotal = this.subTotal + this.vat;
this.rows.removeAt(rowIndex);
}
createItemFormGroup(): FormGroup {
return this.fb.group({
itemName: ['', Validators.required],
units: ['', Validators.required],
unitPrice: ['', Validators.required],
itemTotal: ['0']
});
}
itemsChanged() {
let total: number = 0;
for (let t = 0; t < (<FormArray>this.addForm.get('rows')).length; t++) {
if (this.addForm.get('rows')?.value[t].unitPrice != '' && this.addForm.get('rows')?.value[t].units) {
total = (this.addForm.get('rows')?.value[t].unitPrice * this.addForm.get('rows')?.value[t].units) + total;
}
}
this.subTotal = total;
this.vat = this.subTotal / 10;
this.grandTotal = this.subTotal + this.vat;
}
////////////////////////////////////////////////////////////////////
saveDetail() {
this.invoice.grandTotal = this.grandTotal;
this.invoice.totalCost = this.subTotal;
this.invoice.vat = this.vat;
for (let t = 0; t < (<FormArray>this.addForm.get('rows')).length; t++) {
let o: order = new order();
o.itemName = this.addForm.get('rows')?.value[t].itemName;
o.unitPrice = this.addForm.get('rows')?.value[t].unitPrice;
o.units = this.addForm.get('rows')?.value[t].units;
o.unitTotalPrice = o.units * o.unitPrice;
this.invoice.orders.push(o);
}
this.invoiceService.addInvoice(this.invoice);
alert('New Invoice Added !!');
this.router.navigate(['/apps/invoice']);
}
}
<div class="card card-body">
<form #invoiceForm='ngForm'>
<div class="row mb-3">
<div class="col-md-6">
<h4 class="mb-0">Invoice Id : # <span name="id" [(ngModel)]='invoice.id' ngDefaultControl>
{{invoice.id}}</span></h4>
</div>
<div class="col-md-6 mt-3 mt-md-0">
<div class="row justify-content-end">
<div class="col-lg-3 col-md-4 col-6">
<a routerLink='/apps/invoice' class="btn btn-outline-danger shadow-sm font-medium btn-block">
Cancel
</a>
</div>
<div class="col-lg-3 col-md-4 col-6">
<button type="button" class="btn btn-outline-success shadow-sm font-medium btn-block"
(click)=saveDetail()>Save</button>
</div>
</div>
</div>
</div>
<div class="d-flex align-items-center border-top pt-3 pb-3 border-bottom">
<div>
<h5>Order Status : </h5>
<select class="form-control mt-2" name="satus" [(ngModel)]='invoice.status'>
<option value="Pending">Pending</option>
<option value="Shipped">Shipped</option>
<option value="Delivered">Delivered</option>
</select>
</div>
<div class="ml-auto">
<h5>Order Date</h5>
<span name="date" [(ngModel)]='invoice.orderDate'
ngDefaultControl>{{invoice.orderDate | date: 'dd-MM-yyyy'}}</span>
</div>
</div>
<div class="row mt-4">
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" placeholder="Bill From" name="from"
[(ngModel)]='invoice.billFrom'>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" placeholder="Bill To" name="to"
[(ngModel)]='invoice.billTo'>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<textarea class="form-control" rows="3" placeholder="Enter From Address" name="fromAddress"
[(ngModel)]='invoice.billFromAddress'></textarea>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<textarea class="form-control" rows="3" placeholder="Enter To Address" name="toAddress"
[(ngModel)]='invoice.billToAddress'></textarea>
</div>
</div>
</div>
</form>
<form [formGroup]="addForm">
<div class="table-responsive">
<table id="tblAdd" class="table table-hover table-bordered no-wrap v-middle">
<thead>
<tr>
<th class="border-bottom-0">#</th>
<th class="border-bottom-0">Item Name</th>
<th class="border-bottom-0">Unit Price</th>
<th class="border-bottom-0">Units</th>
<th class="border-bottom-0">Unit Total Price</th>
<th class="border-bottom-0"></th>
</tr>
</thead>
<tbody formArrayName="item" *ngFor="let a of addForm.get('item')?.controls;let i=index">
<tr [formGroupName]="i">
<td>
{{i+1}}
</td>
<td>
<input type="text" [id]="'txtNameControl'+i" class="form-control"
placeholder="Enter Item Name" formControlName="itemName" (input)="itemsChanged()">
</td>
<td>
<input type="number" [id]="'txtCostControl'+i" class="form-control"
placeholder="Enter Item Price" formControlName="itemCost" (input)="itemsChanged()">
</td>
<td>
<input type="number" [id]="'txtTotalControl'+i" class="form-control"
placeholder="Enter Item" formControlName="itemSold" (input)="itemsChanged()">
</td>
<td>
<input type="number" formControlName="itemTotal" [id]="'txtitemTotalControl'+i"
[value]="addForm.get('item').value[this.i].itemCost * addForm.get('item').value[this.i].itemSold"
class="form-control" disabled />
</td>
<td>
<button type="button" *ngIf="addForm.get('item')?.length > 1" class="btn btn-danger btn-sm"
(click)="btnRemoveClick(i)">
<span class="glyphicon glyphicon-remove">Delete</span>
</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="text-right">
<button type="button" class="btn btn-info" (click)="btnAddItemClick()"
[disabled]="addForm.get('item')?.invalid">Add Item</button>
<div class="border-top mt-3 pt-3">
<h5><span>Sub total </span> : {{subTotal}}</h5>
</div>
<div class="border-top mt-3 pt-3">
<h5>Total Vat:</h5>
<div class="row justify-content-end">
<div class="col-lg-2 col-md-4">
<div class="input-group mb-3">
<input type="number" class="form-control" value="10">
<div class="input-group-append">
<span class="input-group-text">%</span>
<span class="input-group-text bg-white font-medium">: {{vat}}</span>
</div>
</div>
</div>
</div>
</div>
<hr />
<h3><span class="font-weight-bold mr-2">Total:</span>${{grandTotal}} </h3>
</div>
</form>
</div>
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { EditInvoiceComponent } from './edit-invoice.component';
describe('EditInvoiceComponent', () => {
let component: EditInvoiceComponent;
let fixture: ComponentFixture<EditInvoiceComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ EditInvoiceComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EditInvoiceComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
});
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { InvoiceService } from '../invoice.service';
import { InvoiceList, order } from '../invoice';
import { FormGroup, FormArray, FormBuilder, Validators } from '@angular/forms';
@Component({
selector: 'app-edit-invoice',
templateUrl: './edit-invoice.component.html',
styleUrls: ['./edit-invoice.component.css']
})
export class EditInvoiceComponent implements OnInit {
id: any;
invoice: InvoiceList;
addForm: FormGroup;
subTotal = 0;
vat = 0;
grandTotal = 0;
constructor(activatedRouter: ActivatedRoute, private invoiceService: InvoiceService,
private router: Router, private fb: FormBuilder) {
this.id = activatedRouter.snapshot.paramMap.get('id');
this.invoice = this.invoiceService.getInvoiceList().filter(x => x.id === +this.id)[0];
this.subTotal = this.invoice.totalCost;
this.vat = this.invoice.vat;
this.grandTotal = this.invoice.grandTotal;
this.addForm = this.fb.group({
item: this.fb.array([
this.itemControl()
]),
});
this.fillAddControls();
}
ngOnInit(): void {
}
itemControl(): FormGroup {
return this.fb.group({
itemName: ['', Validators.required],
itemCost: ['', Validators.required],
itemSold: ['', Validators.required],
itemTotal: ['0']
})
}
fillAddControls() {
this.addForm.setControl('item', this.setItem(this.invoice.orders));
}
setItem(order: any): FormArray {
const fa = new FormArray([]);
order.forEach((s: any) => {
fa.push(this.fb.group({
itemName: s.itemName,
itemCost: s.unitPrice,
itemSold: s.units,
itemTotal: s.unitTotalPrice
}));
});
return fa;
}
btnAddItemClick(): void {
(<FormArray>this.addForm.get('item')).push(this.itemControl());
}
btnRemoveClick(i: number): void {
let totalCostOfItem = this.addForm.get('item')?.value[i].itemCost * this.addForm.get('item')?.value[i].itemSold;
this.subTotal = this.subTotal - totalCostOfItem;
this.vat = this.subTotal / 10;
this.grandTotal = this.subTotal + this.vat;
(<FormArray>this.addForm.get('item')).removeAt(i);
}
//////////////////////////////////////////////////////////////////////////////
itemsChanged() {
let total: number = 0;
for (let t = 0; t < (<FormArray>this.addForm.get('item')).length; t++) {
if (this.addForm.get('item')?.value[t].itemCost != '' && this.addForm.get('item')?.value[t].itemSold) {
total = (this.addForm.get('item')?.value[t].itemCost * this.addForm.get('item')?.value[t].itemSold) + total;
}
}
this.subTotal = total;
this.vat = this.subTotal / 10;
this.grandTotal = this.subTotal + this.vat;
}
saveDetail() {
this.invoice.grandTotal = this.grandTotal;
this.invoice.totalCost = this.subTotal;
this.invoice.vat = this.vat;
this.invoice.orders = [];
for (let t = 0; t < (<FormArray>this.addForm.get('item')).length; t++) {
let o: order = new order();
o.itemName = this.addForm.get('item')?.value[t].itemName;
o.unitPrice = this.addForm.get('item')?.value[t].itemCost;
o.units = this.addForm.get('item')?.value[t].itemSold;
o.unitTotalPrice = o.units * o.unitPrice;
this.invoice.orders.push(o);
}
this.invoiceService.updateInvoice(this.invoice.id, this.invoice);
alert('Invoice Updated !!');
this.router.navigate(['/apps/invoice']);
}
}
import { InvoiceList } from './invoice';
export const invoceLists: InvoiceList[] = [
{
id: 101,
billFrom: 'Pineapple Inc.',
billFromEmail: 'first@xabz.com',
billFromAddress: 'Ganesh glory,Godrej garden city,Ahmedabad.',
billFromPhone: 979796786,
billFromFax: 13,
billTo: 'Redq Inc.',
billToEmail: "toFirst@agth.com",
billToAddress: 'Godrej garden city,Ahmedabad.',
billToPhone: 757575233,
billToFax: 76,
orders: [{
itemName: 'Courge',
unitPrice: 10,
units: 9,
unitTotalPrice: 90
},
],
orderDate: new Date(),
totalCost: 90,
vat: 9,
grandTotal: 99,
status: 'Shipped',
completed: false,
isSelected: false
},
{
id: 102,
billFrom: 'Pineapple.',
billFromEmail: 'first@xabz.com',
billFromAddress: 'Ganesh glory,Godrej garden city,Ahmedabad.',
billFromPhone: 979796786,
billFromFax: 13,
billTo: 'ME Inc.',
billToEmail: "toFirst@agth.com",
billToAddress: 'Godrej garden city,Ahmedabad.',
billToPhone: 757575233,
billToFax: 76,
orders: [{
itemName: 'Courge',
unitPrice: 10,
units: 9,
unitTotalPrice: 90
},
],
orderDate: new Date(),
totalCost: 90,
vat: 9,
grandTotal: 99,
status: 'Delivered',
completed: false,
isSelected: false
},
{
id: 103,
billFrom: 'Incorporation.',
billFromEmail: 'first@xabz.com',
billFromAddress: 'Ahmedabad.',
billFromPhone: 979796786,
billFromFax: 13,
billTo: 'Redirwed.',
billToEmail: "toFirst@agth.com",
billToAddress: 'Godrej garden city,Ahmedabad.',
billToPhone: 757575233,
billToFax: 76,
orders: [
{
itemName: 'Courge',
unitPrice: 10,
units: 9,
unitTotalPrice: 90
},
],
orderDate: new Date(),
totalCost: 90,
vat: 9,
grandTotal: 99,
status: 'Pending',
completed: false,
isSelected: false
},
{
id: 104,
billFrom: 'PineappleTimes .',
billFromEmail: 'first@xabz.com',
billFromAddress: 'Ganesh glory,Godrej garden city,Ahmedabad.',
billFromPhone: 979796786,
billFromFax: 13,
billTo: 'RFc.',
billToEmail: "toFirst@agth.com",
billToAddress: 'Godrej garden city,Ahmedabad.',
billToPhone: 757575233,
billToFax: 76,
orders: [{
itemName: 'Courge',
unitPrice: 10,
units: 9,
unitTotalPrice: 90
},
],
orderDate: new Date(),
totalCost: 90,
vat: 9,
grandTotal: 99,
status: 'Shipped',
completed: false,
isSelected: false
},
{
id: 105,
billFrom: 'Fortune Creation',
billFromEmail: 'first@xabz.com',
billFromAddress: 'Ganesh glory,Godrej garden city,Ahmedabad.',
billFromPhone: 979796786,
billFromFax: 13,
billTo: 'Soft solution.',
billToEmail: "toFirst@agth.com",
billToAddress: 'Godrej garden city,Ahmedabad.',
billToPhone: 757575233,
billToFax: 76,
orders: [{
itemName: 'Courge',
unitPrice: 10,
units: 9,
unitTotalPrice: 90
},
],
orderDate: new Date('2020-10-15'),
totalCost: 90,
vat: 9,
grandTotal: 99,
status: 'Delivered',
completed: false,
isSelected: false
},
{
id: 106,
billFrom: 'PineappleTimes .',
billFromEmail: 'first@xabz.com',
billFromAddress: 'Ganesh glory,Godrej garden city,Ahmedabad.',
billFromPhone: 979796786,
billFromFax: 13,
billTo: 'RFc.',
billToEmail: "toFirst@agth.com",
billToAddress: 'Godrej garden city,Ahmedabad.',
billToPhone: 757575233,
billToFax: 76,
orders: [{
itemName: 'Courge',
unitPrice: 10,
units: 9,
unitTotalPrice: 90
},
],
orderDate: new Date(),
totalCost: 90,
vat: 9,
grandTotal: 99,
status: 'Shipped',
completed: false,
isSelected: false
},
{
id: 107,
billFrom: 'Fortune Creation',
billFromEmail: 'first@xabz.com',
billFromAddress: 'Ganesh glory,Godrej garden city,Ahmedabad.',
billFromPhone: 979796786,
billFromFax: 13,
billTo: 'Soft solution.',
billToEmail: "toFirst@agth.com",
billToAddress: 'Godrej garden city,Ahmedabad.',
billToPhone: 757575233,
billToFax: 76,
orders: [{
itemName: 'Courge',
unitPrice: 10,
units: 9,
unitTotalPrice: 90
},
],
orderDate: new Date('2020-10-15'),
totalCost: 90,
vat: 9,
grandTotal: 99,
status: 'Delivered',
completed: false,
isSelected: false
}
];
\ No newline at end of file
import { TestBed } from '@angular/core/testing';
import { InvoiceService } from './invoice.service';
describe('InvoiceService', () => {
let service: InvoiceService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(InvoiceService);
});
// it('should be created', () => {
// expect(service).toBeTruthy();
// });
});
\ No newline at end of file
import { Injectable } from '@angular/core';
import { from } from 'rxjs';
import { InvoiceList } from './invoice';
import { invoceLists } from './invoice-data';
@Injectable()
export class InvoiceService {
private invoiceList: InvoiceList[] = [];
private getInvoice() {
return from(invoceLists);
}
constructor() {
this.getInvoice().subscribe((data) =>
this.invoiceList.push(data)
);
}
public getInvoiceList() {
return this.invoiceList;
}
public deleteInvoice(id: number) {
this.invoiceList = this.invoiceList.filter(CId => CId.id !== id);
}
public addInvoice(invoice: InvoiceList) {
this.invoiceList.splice(0, 0, invoice);
}
public updateInvoice(id: number, invoice: InvoiceList) {
let invoiceDetail = this.getInvoiceList().filter(x => x.id === id)[0];
invoiceDetail = invoice;
}
// public getInvoiceOriginalLst() {
// this.getInvoice().subscribe((data)=>
// this.invoiceLst.push(data)
// );
// return this.invoiceLst;
// }
}
\ No newline at end of file
export class order {
constructor(
public itemName: string = '',
public unitPrice: number = 0,
public units: number = 0,
public unitTotalPrice: number = 0) {
}
}
export class InvoiceList {
constructor(
public id: number = 0,
public billFrom: string = '',
public billFromEmail: string = 'from@mail.com',
public billFromAddress: string = '',
public billFromPhone: number = 758269842,
public billFromFax: number = 0,
public billTo: string = '',
public billToEmail: string = 'to@mail.com',
public billToAddress: string = '',
public billToPhone: number = 58258855,
public billToFax: number = 0,
public orders: order[] = [],
public orderDate: Date = new Date,
public totalCost: number = 0,
public vat: number = 0,
public grandTotal: number = 0,
public status: string = '',
public completed: boolean = false,
public isSelected: boolean = false) {
}
}
\ No newline at end of file
<div class="card mb-0">
<div class="card-body">
<div class="d-md-flex align-items-center">
<div class="form-group mb-0">
<input type="text" placeholder="Search Invoice" class="form-control" [(ngModel)]='searchTerm'>
</div>
<div class="ml-auto mt-4 mt-md-0">
<a routerLink='/apps/addinvoice'>
<button type="button" class="btn btn-info"> <i class="mr-2 mdi mdi-plus"></i> Add Invoice</button>
</a>
</div>
</div>
</div>
</div>
<div class="card pt-3">
<div class="table-responsive">
<table class="table table-borderless table-hover v-middle no-wrap">
<thead>
<tr class="border-bottom">
<th scope="col">
<input type="checkbox" [(ngModel)]="isMasterSel" name="list_name" value="h1"
(change)="checkUncheckAll()" />
</th>
<th scope="col">Id</th>
<th scope="col">Bill From</th>
<th scope="col">Bill To</th>
<th scope="col">Total Cost</th>
<th scope="col">Status</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr class="border-bottom "
*ngFor="let invoice of compInvoice|slice: (page-1) * pageSize : (page-1) * pageSize + pageSize; index as i">
<td class="py-4">
<input type="checkbox" [(ngModel)]="invoice.isSelected" name="list_name" value="{{invoice.id}}"
(change)="isAllSelected()" />
</td>
<td class="py-4">{{ invoice.id }} </td>
<td class="py-4">
<ngb-highlight [result]="invoice.billFrom" [term]="searchTerm"></ngb-highlight>
</td>
<td class="py-4">
<ngb-highlight [result]="invoice.billTo" [term]="searchTerm"></ngb-highlight>
</td>
<td class="py-4">
<ngb-highlight [result]="invoice.grandTotal | number" [term]="searchTerm"></ngb-highlight>
</td>
<td class="py-4">
<span class="badge badge-info px-3 font-medium" *ngIf="invoice.status==='Shipped'">
<ngb-highlight [result]="invoice.status" [term]="searchTerm"></ngb-highlight>
</span>
<span class="badge badge-danger px-3 font-medium" *ngIf="invoice.status==='Pending'">
<ngb-highlight [result]="invoice.status" [term]="searchTerm"></ngb-highlight>
</span>
<span class="badge badge-success px-3 font-medium" *ngIf="invoice.status==='Delivered'">
<ngb-highlight [result]="invoice.status" [term]="searchTerm"></ngb-highlight>
</span>
</td>
<td class="py-4">
<!-- <a routerLink='/apps/viewinvoice/'>View</a> -->
<a [routerLink]="['/apps/viewinvoice/',invoice.id]" class="text-info mx-2">
<i-feather name="eye" class="feather-sm"></i-feather>
</a>
<a href="javascript:void(0)" class="text-danger mx-2 pl-3 border-left"
(click)="deleteInvoice(invoice.id)">
<i-feather name="trash-2" class="feather-sm"></i-feather>
</a>
</td>
</tr>
</tbody>
</table>
</div>
<div class="card-body">
<div class="d-flex justify-content-center">
<ngb-pagination [(page)]="page" [pageSize]="pageSize" [collectionSize]="totalLengthOfCollection">
</ngb-pagination>
</div>
</div>
</div>
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ListInvoicesComponent } from './list-invoices.component';
describe('ListInvoicesComponent', () => {
let component: ListInvoicesComponent;
let fixture: ComponentFixture<ListInvoicesComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ListInvoicesComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ListInvoicesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
});
import { Component } from '@angular/core';
import { InvoiceList } from '../invoice';
import { InvoiceService } from '../invoice.service';
@Component({
selector: 'app-list-invoices',
templateUrl: './list-invoices.component.html',
styleUrls: ['./list-invoices.component.css']
})
export class ListInvoicesComponent {
compInvoice: InvoiceList[];
// checkbox
isMasterSel: boolean;
checkedCategoryList: any;
///////////////////////////
// pagination
page = 1;
pageSize = 5;
totalLengthOfCollection: number;
constructor(public invoiceService: InvoiceService) {
this.compInvoice = this.invoiceService.getInvoiceList();
// pagination
this.totalLengthOfCollection = this.invoiceService.getInvoiceList().length;
// checkbox
this.isMasterSel = false;
this.getCheckedItemList();
}
deleteInvoice(id: number): void {
if (confirm('Are you sure to delete this ! ')) {
this.compInvoice = this.compInvoice.filter(invoice => invoice.id !== id);
this.totalLengthOfCollection = this.compInvoice.length;
this.invoiceService.deleteInvoice(id);
}
}
// check-box.
checkUncheckAll() {
for (var i = 0; i < this.compInvoice.length; i++) {
this.compInvoice[i].isSelected = this.isMasterSel;
}
this.getCheckedItemList();
}
isAllSelected() {
this.isMasterSel = this.compInvoice.every(function (item: any) {
return item.isSelected == true;
})
this.getCheckedItemList();
}
getCheckedItemList() {
this.checkedCategoryList = [];
for (var i = 0; i < this.compInvoice.length; i++) {
if (this.compInvoice[i].isSelected)
this.checkedCategoryList.push(this.compInvoice[i]);
}
this.checkedCategoryList = JSON.stringify(this.checkedCategoryList);
}
/////////////////
_searchTerm: string = '';
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this._searchTerm = val;
this.compInvoice = this.filter(val);
this.totalLengthOfCollection = this.compInvoice.length;
}
filter(v: string) {
return this.invoiceService.getInvoiceList().filter(x => x.billTo.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.billFrom.toLowerCase().indexOf(v.toLowerCase()) !== -1 || x.status.toLowerCase().indexOf(v.toLowerCase()) !== -1 || x.totalCost !== -1);
}
}
<div class="card">
<!-- card Header-->
<div class="p-3">
<div class="d-md-flex align-items-center">
<div class="btn-group">
<a routerLink='/apps/invoice'
class="btn btn-default bg-white text-info d-flex align-items-center shadow-sm mr-2">
<i class="mdi mdi-chevron-left font-20 mr-1"></i> <span>Back</span>
</a>
<a [routerLink]="['/apps/editinvoice/',invoiceDetail.id]"
class="btn btn-default bg-white text-info d-flex align-items-center shadow-sm mr-2">
<i class="mdi mdi-note-plus-outline font-20"></i>
<span class="ml-2">Edit</span>
</a>
</div>
<div class="ml-auto mt-3 mt-md-0">
<h4 class="mb-0">Invoice Id : #{{invoiceDetail.id}}</h4>
</div>
</div>
</div>
<!-- card Body-->
<div class="card-body">
<div class="row">
<div class="col-md-6 text-left">
<h5>Order Status:</h5>
<span class="badge badge-info font-medium px-3">{{invoiceDetail.status}}</span>
</div>
<div class="col-md-6 text-left text-md-right">
<h5 class="mt-2">Order Date:</h5>
<span>
<i class="mdi mdi-calendar mr-1 text-dark font-18"></i>
{{invoiceDetail.orderDate| date:'fullDate'}}
</span>
</div>
</div>
<hr />
<div class="row">
<div class="col-md-6 text-left">
<h5>Bill From:</h5>
<span>{{invoiceDetail.billFrom}}</span>
<span class="d-block">{{invoiceDetail.billFromEmail}}</span>
<span class="d-block">{{invoiceDetail.billFromAddress}}</span>
<span class="d-block">{{invoiceDetail.billFromPhone}}</span>
</div>
<div class="col-md-6 text-right">
<h5>Bill To:</h5>
<span class="d-block">{{invoiceDetail.billTo}}</span>
<span class="d-block">
{{invoiceDetail.billToEmail}}
</span>
<span class="d-block">
{{invoiceDetail.billToAddress}}
</span>
<span class="d-block">{{invoiceDetail.billToPhone}}</span>
</div>
</div>
<div class="mt-4">
<div class="table-responsive">
<table class="table table-bordered table-hover no-wrap v-middle">
<thead>
<tr>
<th class="border-bottom-0">Item Name</th>
<th class="border-bottom-0 text-center">Unit Price</th>
<th class="border-bottom-0 text-center">Unit</th>
<th class="border-bottom-0 text-info text-center">Total Price</th>
</tr>
</thead>
<tbody *ngFor="let order of invoiceDetail.orders">
<tr>
<td>{{ order.itemName }} </td>
<td class="text-center">{{ order.unitPrice }} </td>
<td class="text-center">{{ order.units }}</td>
<td class="text-center">{{ order.unitTotalPrice }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="text-right mt-4">
<h5><span>Subtotal amount: $</span> {{invoiceDetail.totalCost}}</h5>
<h5><span>Vat: $</span>{{invoiceDetail.vat}}</h5>
<hr />
<h3><span class="font-weight-bold mr-2">Total:</span>${{invoiceDetail.grandTotal}} </h3>
</div>
</div>
</div>
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ViewInvoiceComponent } from './view-invoice.component';
describe('ViewInvoiceComponent', () => {
let component: ViewInvoiceComponent;
let fixture: ComponentFixture<ViewInvoiceComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ViewInvoiceComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ViewInvoiceComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
});
import { Component, OnInit } from '@angular/core';
import { InvoiceService } from '../invoice.service';
import { InvoiceList } from '../invoice';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-view-invoice',
templateUrl: './view-invoice.component.html',
styleUrls: ['./view-invoice.component.css']
})
export class ViewInvoiceComponent implements OnInit {
id: any;
invoiceDetail: InvoiceList;
constructor(activatedRouter: ActivatedRoute, private invoiceService: InvoiceService) {
this.id = activatedRouter.snapshot.paramMap.get('id');
this.invoiceDetail = this.invoiceService.getInvoiceList().filter(x => x.id === +this.id)[0];
}
ngOnInit() {
}
}
<div class="card">
<div class="modal-header">
<a routerLink="/apps/jobs/" class="btn btn-primary"> Back to Jobs </a>
</div>
<div class="modal-body">
<form [formGroup]="applyDetail" (ngSubmit)="onSubmit()">
<div class="form-group">
<h4 class="card-title">Personal Detail</h4>
</div>
<div class="form-group">
<label class="col-sm-4 col-form-label">Full Name</label>
<input type="text" class="form-control" formControlName="fullName" />
</div>
<div class="form-group">
<label class="col-sm-4 col-form-label">Email</label>
<input type="text" class="form-control" formControlName="email" />
</div>
<div class="form-group">
<label class="col-sm-4 col-form-label">Phone Number</label>
<input type="text" class="form-control" formControlName="phone" />
</div>
<div class="form-group">
<label class="col-sm-4 col-form-label">Address</label>
<input type="text" class="form-control" formControlName="address" />
</div>
<div class="modal-footer">
<button
type="submit"
class="btn btn-primary"
[disabled]="applyDetail.invalid"
>
Save
</button>
</div>
</form>
</div>
</div>
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { JobApplyComponent } from './job-apply.component';
describe('JobApplyComponent', () => {
let component: JobApplyComponent;
let fixture: ComponentFixture<JobApplyComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ JobApplyComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(JobApplyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-job-apply',
templateUrl: './job-apply.component.html',
styleUrls: ['./job-apply.component.css']
})
export class JobApplyComponent implements OnInit {
applyDetail: FormGroup;
constructor(public fb: FormBuilder) {
this.applyDetail = this.fb.group({
fullName: ['', Validators.required],
email: ['', Validators.required],
phone: ['', Validators.required],
address: ['', Validators.required],
});
}
ngOnInit(): void {
}
onSubmit() {
debugger;
}
}
import { Job } from "./job-type";
export const jobData: Job[] = [
{
id: 101,
image: "assets/images/job/ui-ux-job.png",
title: "UI/UX IT Frontend Developer",
location: "Salt Lake City, UT",
description:
"We are looking for an experienced and creative designer and/or frontend engineer with expertise in accessibility to join our team , 3+ years of experience working in as a Frontend Engineer or comparable role",
qualification: [
"Have shipped multiple iOS, Android, and/or web products.",
"5+ years UI/UX experience.",
"Ability to autonomously pursue elegant solutions to open-ended problems.",
"Proven ability to create interactive prototypes.",
"Ability to create and maintain flow charts, wire frames, prototypes, and mockups.",
"Ability to effectively work on more than one project at a time.",
],
jobType: "Full time",
icon: "",
featured: false,
jobNature: "Designer",
},
{
id: 102,
image: "assets/images/job/react-job.png",
title: "React/React Native Developer",
location: "San Diego, CA",
description:
"We are looking for an experienced and creative designer and/or frontend engineer with expertise in accessibility to join our team , 3+ years of experience working in as a Frontend Engineer or comparable role",
qualification: [
"Have shipped multiple iOS, Android, and/or web products.",
"5+ years UI/UX experience.",
"Ability to autonomously pursue elegant solutions to open-ended problems.",
"Proven ability to create interactive prototypes.",
"Ability to create and maintain flow charts, wire frames, prototypes, and mockups.",
"Ability to effectively work on more than one project at a time.",
],
jobType: "Full time",
icon: "",
featured: true,
jobNature: "React",
},
{
id: 103,
image: "assets/images/job/senior-job.png",
title: "Senior UX designer",
location: "Minneapolis, MN",
description:
"We are looking for an experienced and creative designer and/or frontend engineer with expertise in accessibility to join our team , 3+ years of experience working in as a Frontend Engineer or comparable role",
qualification: [
"Have shipped multiple iOS, Android, and/or web products.",
"5+ years UI/UX experience.",
"Ability to autonomously pursue elegant solutions to open-ended problems.",
"Proven ability to create interactive prototypes.",
"Ability to create and maintain flow charts, wire frames, prototypes, and mockups.",
"Ability to effectively work on more than one project at a time.",
],
jobType: "Part time",
icon: "",
featured: false,
jobNature: "Senior designer",
},
{
id: 104,
image: "assets/images/job/design-job.png",
title: "Front end web developer",
location: "Cisco, Lelystad, Netherlands",
description:
"We are looking for an experienced and creative designer and/or frontend engineer with expertise in accessibility to join our team , 3+ years of experience working in as a Frontend Engineer or comparable role",
qualification: [
"Have shipped multiple iOS, Android, and/or web products.",
"5+ years UI/UX experience.",
"Ability to autonomously pursue elegant solutions to open-ended problems.",
"Proven ability to create interactive prototypes.",
"Ability to create and maintain flow charts, wire frames, prototypes, and mockups.",
"Ability to effectively work on more than one project at a time.",
],
jobType: "Full time",
icon: "",
featured: true,
jobNature: "Designer",
},
{
id: 105,
image: "assets/images/job/ui-ux-job.png",
title: "Graphic designer",
location: "Infosys, Lelystad, Netherlands",
description:
"We are looking for an experienced and creative designer and/or frontend engineer with expertise in accessibility to join our team , 3+ years of experience working in as a Frontend Engineer or comparable role",
qualification: [
"Have shipped multiple iOS, Android, and/or web products.",
"5+ years UI/UX experience.",
"Ability to autonomously pursue elegant solutions to open-ended problems.",
"Proven ability to create interactive prototypes.",
"Ability to create and maintain flow charts, wire frames, prototypes, and mockups.",
"Ability to effectively work on more than one project at a time.",
],
jobType: "Internship",
icon: "",
featured: false,
jobNature: "Designer",
},
{
id: 106,
image: "assets/images/job/ang-job.png",
title: "Angular Developer",
location: "(L6) Salt Lake City, UT",
description:
"We are looking for an experienced and creative designer and/or frontend engineer with expertise in accessibility to join our team , 3+ years of experience working in as a Frontend Engineer or comparable role",
qualification: [
"Have shipped multiple iOS, Android, and/or web products.",
"5+ years UI/UX experience.",
"Ability to autonomously pursue elegant solutions to open-ended problems.",
"Proven ability to create interactive prototypes.",
"Ability to create and maintain flow charts, wire frames, prototypes, and mockups.",
"Ability to effectively work on more than one project at a time.",
],
jobType: "Internship",
icon: "",
featured: false,
jobNature: "Angular",
},
{
id: 107,
image: "assets/images/job/senior-job.png",
title: "JAVA Developer",
location: "(L6) Salt Lake City, UT",
description:
"We are looking for an experienced and creative designer and/or frontend engineer with expertise in accessibility to join our team , 3+ years of experience working in as a Frontend Engineer or comparable role",
qualification: [
"Have shipped multiple iOS, Android, and/or web products.",
"5+ years UI/UX experience.",
"Ability to autonomously pursue elegant solutions to open-ended problems.",
"Proven ability to create interactive prototypes.",
"Ability to create and maintain flow charts, wire frames, prototypes, and mockups.",
"Ability to effectively work on more than one project at a time.",
],
jobType: "Internship",
icon: "",
featured: false,
jobNature: "java",
},
{
id: 108,
image: "assets/images/job/react-job.png",
title: "React devoloper",
location: "Infosys, Lelystad, Netherlands",
description:
"We are looking for an experienced and creative designer and/or frontend engineer with expertise in accessibility to join our team , 3+ years of experience working in as a Frontend Engineer or comparable role",
qualification: [
"Have shipped multiple iOS, Android, and/or web products.",
"5+ years UI/UX experience.",
"Ability to autonomously pursue elegant solutions to open-ended problems.",
"Proven ability to create interactive prototypes.",
"Ability to create and maintain flow charts, wire frames, prototypes, and mockups.",
"Ability to effectively work on more than one project at a time.",
],
jobType: "Part time",
icon: "",
featured: false,
jobNature: "React",
},
{
id: 109,
image: "assets/images/job/ui-ux-job.png",
title: "Business Managment",
location: "Infosys, Lelystad, Netherlands",
description:
"We are looking for an experienced and creative designer and/or frontend engineer with expertise in accessibility to join our team , 3+ years of experience working in as a Frontend Engineer or comparable role",
qualification: [
"Have shipped multiple iOS, Android, and/or web products.",
"5+ years UI/UX experience.",
"Ability to autonomously pursue elegant solutions to open-ended problems.",
"Proven ability to create interactive prototypes.",
"Ability to create and maintain flow charts, wire frames, prototypes, and mockups.",
"Ability to effectively work on more than one project at a time.",
],
jobType: "Part time",
icon: "",
featured: false,
jobNature: "Business",
},
{
id: 110,
image: "assets/images/job/senior-job.png",
title: "Market Analysis",
location: "Infosys, Lelystad, Netherlands",
description:
"We are looking for an experienced and creative designer and/or frontend engineer with expertise in accessibility to join our team , 3+ years of experience working in as a Frontend Engineer or comparable role",
qualification: [
"Have shipped multiple iOS, Android, and/or web products.",
"5+ years UI/UX experience.",
"Ability to autonomously pursue elegant solutions to open-ended problems.",
"Proven ability to create interactive prototypes.",
"Ability to create and maintain flow charts, wire frames, prototypes, and mockups.",
"Ability to effectively work on more than one project at a time.",
],
jobType: "Internship",
icon: "",
featured: false,
jobNature: "Marketing",
},
{
id: 111,
image: "assets/images/job/ang-job.png",
title: "Senior Angular Developer",
location: "Infosys, Lelystad, Netherlands",
description:
"We are looking for an experienced and creative designer and/or frontend engineer with expertise in accessibility to join our team , 3+ years of experience working in as a Frontend Engineer or comparable role",
qualification: [
"Have shipped multiple iOS, Android, and/or web products.",
"5+ years UI/UX experience.",
"Ability to autonomously pursue elegant solutions to open-ended problems.",
"Proven ability to create interactive prototypes.",
"Ability to create and maintain flow charts, wire frames, prototypes, and mockups.",
"Ability to effectively work on more than one project at a time.",
],
jobType: "Internship",
icon: "",
featured: false,
jobNature: "Designer",
},
];
<div>
<div class="card">
<div class="card-body">
<div class="d-md-flex align-items-center pb-3 border-bottom">
<div class="d-flex align-items-center">
<img
[src]="jobDetail.image"
alt="pic"
class="img-fluid rounded-lg flex-shrink-0"
width="50"
/>
<div class="ml-3">
<h4 class="card-title">{{ jobDetail.title }}</h4>
<h6 class="card-subtitle mb-0">{{ jobDetail.location }}</h6>
</div>
</div>
<div class="ml-auto mt-2 mt-md-0">
<a routerLink="/apps/jobs" class="btn btn-primary mr-2">
Back to Jobs
</a>
<a routerLink="/apps/apply-job" class="btn btn-success">
Apply for Job
</a>
</div>
</div>
<h4 class="mt-4 card-title">Job Description</h4>
<p>{{ jobDetail.description }}</p>
<h4 class="card-title pt-2 border-top">Qualifications</h4>
<ul class="list-unstyled">
<li *ngFor="let qua of jobDetail.qualification" class="py-1">
<i class="mdi mdi-radiobox-marked text-info"></i>
{{ qua }}
</li>
</ul>
</div>
</div>
<h4 class="card-title mt-4 pb-2 border-bottom">Related Jobs</h4>
<div *ngIf="similarJobs.length === 0">
<div class="card">
<div class="card-body">
<span>No matching job found !!</span>
</div>
</div>
</div>
<div class="row justify-content-center">
<div
class="col-md-6 d-flex align-items-stretch"
*ngFor="let job of similarJobs"
>
<div class="card w-100">
<div class="card-body">
<div *ngIf="job.featured">
<button
class="btn btn-circle btn-warning featured-btn d-flex align-items-center justify-content-center"
>
<i class="mdi mdi-star font-18"></i>
</button>
</div>
<div class="d-md-flex align-items-start mb-3">
<img
[src]="job.image"
alt="pic"
width="80"
class="rounded-lg flex-shrink-0"
/>
<div class="ml-md-3 ml-0 mt-2 mt-md-0">
<a
[routerLink]="['/apps/job-detail/', job.id]"
class="card-title font-16"
>
{{ job.title }}
</a>
<p class="mb-1">{{ job.location }}</p>
<p>
<span
*ngIf="job.jobType === 'Full time'"
class="badge badge-danger px-2 font-medium"
><i class="fas fa-circle font-10 mr-1"></i>Full time</span
>
<span
*ngIf="job.jobType === 'Part time'"
class="badge badge-success px-2 font-medium"
><i class="fas fa-circle font-10 mr-1"></i>Part time</span
>
<span
*ngIf="job.jobType === 'Internship'"
class="badge badge-primary px-2 font-medium"
><i class="fas fa-circle font-10 mr-1"></i>Internship</span
>
</p>
</div>
</div>
{{ job.description }}
</div>
</div>
</div>
</div>
</div>
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { JobDetailComponent } from './job-detail.component';
describe('JobDetailComponent', () => {
let component: JobDetailComponent;
let fixture: ComponentFixture<JobDetailComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ JobDetailComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(JobDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { ServicejobService } from '../servicejob.service';
import { ActivatedRoute, Router } from '@angular/router';
import { Job } from '../job-type';
@Component({
selector: 'app-job-detail',
templateUrl: './job-detail.component.html',
styleUrls: ['./job-detail.component.css']
})
export class JobDetailComponent implements OnInit {
id: any;
jobDetail: Job;
similarJobs: Job[] = [];
constructor(activatedRouter: ActivatedRoute, private service: ServicejobService, public router: Router) {
this.id = activatedRouter.snapshot.paramMap.get('id');
this.jobDetail = this.service.getJobs().filter(x => x.id === +this.id)[0];
this.similarJobs = this.service.getJobs().filter(x => x.id === +this.id);
}
ngOnInit(): void {
this.similarJobs = this.service.getJobs().filter(x => x.jobNature === this.jobDetail.jobNature);
this.similarJobs = this.similarJobs.filter(x => x !== this.jobDetail);
}
}
export class Job {
id: number = 0;
image: string = '';
title: string = '';
location: string = '';
description: string = '';
qualification: string[] = [];
jobType: string = '';
icon: string = '';
featured: boolean = false;
jobNature:string='';
}
\ No newline at end of file
<!-- Mobile toggle button -->
<a
[ngClass]="showSidebar ? 'ti-close' : 'ti-menu'"
class="btn btn-success show-left-part d-block d-lg-none"
href="javascript:void(0)"
(click)="mobileSidebar()"
></a>
<div class="main-part" style="height: calc(100vh - 175px)">
<!-- left part -->
<div
class="left-part bg-white fixed-left-part"
[ngClass]="{ 'show-panel': showSidebar }"
>
<div class="position-relative" style="height: 100%">
<div
class="p-l-15 p-r-25 py-3 d-flex align-items-center mt-1 border-bottom"
>
<div>
<img
src="assets/images/users/8.jpg"
width="45"
alt="user"
class="rounded-circle"
/>
</div>
<div class="text-dark m-b-0 m-l-15 font-18">
Bruce Banner
<p class="m-b-0 font-12">
<i class="fa fa-circle text-success font-10 m-r-5"></i>
<span>Online</span>
</p>
</div>
</div>
<div class="p-3">
<button
type="button"
class="btn btn-info btn-block"
(click)="openModal(AddJobItem)"
>
Add Job
</button>
<div class="form-group mt-4">
<input
type="text"
class="form-control"
placeholder="Search"
[(ngModel)]="searchTerm"
/>
</div>
<div class="form-group">
<input
type="text"
class="form-control"
placeholder="Location"
[(ngModel)]="locationsearch"
/>
</div>
</div>
<!-- listing filter -->
<ul class="mailbox list-style-none">
<li>
<div
class="message-center"
style="height: calc(100vh - 450px)"
[perfectScrollbar]="config"
>
<div class="px-3 pb-3">
<h6 class="font-weight-normal text-muted text-uppercase mb-0">
Filter
</h6>
</div>
<div *ngFor="let item of itemsList">
<a class="message-item border-0 d-flex align-items-center py-3">
<div class="custom-control custom-radio">
<input
type="radio"
class="custom-control-input"
[(ngModel)]="radioSelected"
name="list_name"
value="{{ item.value }}"
(change)="onItemChange(item)"
/>
<label class="custom-control-label">{{ item.name }}</label>
</div>
</a>
</div>
</div>
</li>
</ul>
</div>
</div>
<!-- right part -->
<div class="right-part bg-white">
<div class="position-relative" style="height: 100%">
<div
class="d-md-flex align-items-center p-4 border-bottom mail-pagination"
>
<h4 class="card-title mb-0">Jobs</h4>
<div class="ml-auto mt-3 mt-md-0">
<ngb-pagination
[(page)]="page"
[pageSize]="pageSize"
[collectionSize]="filjobs.length"
>
</ngb-pagination>
</div>
</div>
<!-- listing of jobs -->
<div
class="position-relative"
style="height: calc(100vh - 260px)"
[perfectScrollbar]="config"
>
<div
*ngFor="
let job of filjobs
| slice: (page - 1) * pageSize:(page - 1) * pageSize + pageSize
"
>
<div class="card border-bottom">
<div class="card-body">
<div *ngIf="job.featured">
<button
class="btn btn-circle btn-warning featured-btn d-flex align-items-center justify-content-center"
>
<i class="mdi mdi-star font-18"></i>
</button>
</div>
<div class="row">
<div
class="col-md-2 col-xl-1 col-4 mb-3 mb-md-0 d-flex align-items-center justify-content-start"
>
<img
[src]="job.image"
alt="pic"
class="img-fluid rounded-lg"
/>
</div>
<div class="col-md-10 col-xl-11">
<a
[routerLink]="['/apps/job-detail/', job.id]"
class="card-title font-16"
>
{{ job.title }}
</a>
<p class="mb-0">{{ job.location }}</p>
<p>
<span
*ngIf="job.jobType === 'Full time'"
class="badge badge-danger px-2 font-medium"
><i class="fas fa-circle font-10 mr-1"></i>Full time</span
>
<span
*ngIf="job.jobType === 'Part time'"
class="badge badge-success px-2 font-medium"
><i class="fas fa-circle font-10 mr-1"></i>Part time</span
>
<span
*ngIf="job.jobType === 'Internship'"
class="badge badge-primary px-2 font-medium"
><i class="fas fa-circle font-10 mr-1"></i
>Internship</span
>
</p>
{{ job.description }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #AddJobItem let-modal>
<div class="modal-header">
<h5 class="modal-title">Add Jobs</h5>
<button
type="button"
class="close"
(click)="closeBtnClick()"
aria-label="Close"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form [formGroup]="jobAdd" (ngSubmit)="onSubmit()">
<div class="form-group row">
<label for="name" class="col-sm-4 col-form-label">Job Image</label>
<div class="col-sm-8">
<input
type="file"
style="display: none"
(change)="preview(filevar.files)"
#filevar
/>
<img
[src]="selectedImage"
class="rounded-circle image cursor-pointer"
alt=""
height="100px"
width="100px"
(click)="filevar.click()"
/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">Job Title</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Title" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">Job Loction</label>
<div class="col-sm-8">
<select class="form-control" formControlName="Location">
<option value="" disabled>Choose location</option>
<option *ngFor="let loc of location" [ngValue]="loc">
{{ loc }}
</option>
</select>
<!-- <input type="text" class="form-control" formControlName="Location"> -->
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">Description</label>
<div class="col-sm-8">
<input
type="email"
class="form-control"
formControlName="Description"
/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">Qualification</label>
<div class="col-sm-8">
<textarea
class="form-control"
formControlName="Qualification"
rows="4"
cols="50"
>
</textarea>
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">Job Type</label>
<div class="col-sm-8">
<select class="form-control" formControlName="JobType">
<option value="" disabled>Choose type of job</option>
<option *ngFor="let jt of jobtype" [ngValue]="jt">{{ jt }}</option>
</select>
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">Job In</label>
<div class="col-sm-8">
<select class="form-control" formControlName="Nature">
<option value="" disabled>Choose job in</option>
<option *ngFor="let ji of jobin" [ngValue]="ji">{{ ji }}</option>
</select>
<!-- <input type="text" class="form-control" formControlName="Nature"> -->
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">Job Icon</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Icon" />
</div>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
(click)="closeBtnClick()"
>
Close
</button>
<button
type="submit"
class="btn btn-primary"
[disabled]="jobAdd.invalid"
>
Save
</button>
</div>
</form>
</div>
</ng-template>
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { JobsListComponent } from './jobs-list.component';
describe('JobsListComponent', () => {
let component: JobsListComponent;
let fixture: ComponentFixture<JobsListComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ JobsListComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(JobsListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from "@angular/core";
import { Job } from "../job-type";
import { ServicejobService } from "../servicejob.service";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
import { PerfectScrollbarConfigInterface } from "ngx-perfect-scrollbar";
export class Item {
name: string = "";
value: string = "";
}
export const ITEMS: Item[] = [
{
name: "All",
value: "all",
},
{
name: "Part Time",
value: "Part time",
},
{
name: "Full Time",
value: "Full time",
},
{
name: "Internship",
value: "Internship",
},
];
@Component({
selector: "app-jobs-list",
templateUrl: "./jobs-list.component.html",
styleUrls: ["./jobs-list.component.css"],
})
export class JobsListComponent implements OnInit {
public showSidebar = false;
mobileSidebar() {
this.showSidebar = !this.showSidebar;
}
public config: PerfectScrollbarConfigInterface = {};
jobs: Job[];
filjobs: Job[];
_searchTerm = "";
_locationsearch = "";
page = 1;
pageSize = 2;
itemsList: Item[] = ITEMS;
radioSelected: string = "";
jobAdd: FormGroup;
selectedImage: any = "assets/images/job/noimage.png";
jobtype: any = ["Full time", "Part time", "Internship"];
location: string[] = [
"Netherlands",
"Salt Lake City",
"San Diego",
"Minneapolis",
"Banglore",
"New Jerssy",
];
jobin: string[] = [
"Designer",
"Marketing",
"Business",
"React",
"java",
"Angular",
];
constructor(
public service: ServicejobService,
public fb: FormBuilder,
private modalService: NgbModal
) {
this.jobs = service.getJobs();
this.filjobs = this.jobs;
//
this.itemsList = ITEMS;
this.radioSelected = "all";
this.jobAdd = this.fb.group({
Title: ["", Validators.required],
Location: ["", Validators.required],
Description: ["", Validators.required],
Qualification: ["", Validators.required],
Icon: ["", Validators.required],
JobType: ["", Validators.required],
Nature: ["", Validators.required],
});
}
ngOnInit(): void {
this.selectedImage = "assets/images/job/noimage.png";
}
// ============================================================================
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this.radioSelected = "all";
this._searchTerm = val;
this.filjobs = this.filter(val);
}
filter(v: string) {
return this.jobs.filter(
(x) => x.title.toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
// ==============================================================================
get locationsearch(): string {
return this._locationsearch;
}
set locationsearch(val: string) {
this.radioSelected = "all";
this._locationsearch = val;
this.filjobs = this.filterLoc(val);
}
filterLoc(v: string) {
return this.jobs.filter(
(x) => x.location.toLowerCase().indexOf(v.toLowerCase()) !== -1
);
}
// ===========================================================================================
onItemChange(item: any) {
debugger;
if (item.value === "all") {
this.filjobs = this.jobs;
} else {
this.filjobs = this.jobs.filter((x) => x.jobType === item.value);
}
}
//==========================================================================================
openModal(targetModal: any) {
this.modalService.open(targetModal, {
centered: true,
backdrop: "static",
});
}
closeBtnClick() {
this.modalService.dismissAll();
this.ngOnInit();
}
onSubmit() {
debugger;
let j = new Job();
j.id =
Math.max.apply(
Math,
this.service.getJobs().map(function (o) {
return o.id;
})
) + 1;
j.title = this.jobAdd?.get("Title")?.value;
j.location = this.jobAdd?.get("Location")?.value;
j.description = this.jobAdd?.get("Description")?.value;
j.qualification = this.jobAdd?.get("Qualification")?.value;
j.image = this.selectedImage;
j.jobType = this.jobAdd?.get("JobType")?.value;
j.icon = this.jobAdd?.get("Icon")?.value;
j.jobNature = this.jobAdd?.get("Nature")?.value;
this.jobs?.splice(0, 0, j);
//this.service.addEcommerceData(product);
this.modalService.dismissAll();
this.ngOnInit();
}
preview(files: any) {
if (files.length === 0) {
return;
}
const mimeType = files[0].type;
if (mimeType.match(/image\/*/) == null) {
return;
}
const reader = new FileReader();
reader.readAsDataURL(files[0]);
reader.onload = (_event) => {
this.selectedImage = reader.result;
};
}
}
import { Injectable } from '@angular/core';
import { Job } from './job-type';
import { jobData } from './job-data';
@Injectable()
export class ServicejobService {
jobs: Job[] = jobData;
public getJobs() {
return this.jobs;
}
}
<ng-template #content let-modal>
<div class="modal-header">
<h4 class="modal-title">Product</h4>
<button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
</div>
</ng-template>
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComposeComponent } from './compose.component';
describe('ComposeComponent', () => {
let component: ComposeComponent;
let fixture: ComponentFixture<ComposeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ComposeComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ComposeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
});
import { Component, OnInit } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-compose',
templateUrl: './compose.component.html',
styleUrls: ['./compose.component.css']
})
export class ComposeComponent implements OnInit {
content: NgbModal = Object.create(null);
constructor(public modal: NgbModal) {
}
ngOnInit(): void {
this.openModal(this.content);
}
openModal(content: NgbModal) {
this.modal.open(content, { size: 'lg' });
}
closeModal() {
this.modal.dismissAll();
}
}
<div *ngIf='ms.selectedMail'
class="d-flex align-items-center px-3 py-2 border-bottom bg-light">
<div class="d-flex align-items-center">
<button class="mr-3 d-block d-lg-none btn btn-info btn-sm">
<i class="fas fa-arrow-left" (click)="removeClass()"></i>
</button>
<span> <i class="fas fa-bookmark"
[ngStyle]="{'color':ms.selectedMail.filter.indexOf('Important') != -1 ? '#ffbc34' : '' }"
(click)='iconsClick("Important")'></i></span>
<span class="ml-3"> <i class="fas fa-star"
[ngStyle]="{'color':ms.selectedMail.filter.indexOf('Star') != -1 ? '#ffbc34' : '' }"
(click)='iconsClick("Star")'></i></span>
</div>
<div class="ml-auto">
<div ngbDropdown class="d-inline-block">
<button class="btn btn-secondary btn-sm" id="dropdownBasic1" ngbDropdownToggle><i class="mdi mdi-tag"></i><i
class="fas fa-caret-down ml-1"></i></button>
<div ngbDropdownMenu aria-labelledby="dropdownBasic1">
<label ngbDropdownItem>
<span *ngIf="ms.selectedMail.label.indexOf('Personal') != -1">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck1"
(click)="labelClick('Personal')" checked>
<label class="custom-control-label" for="customCheck1">Personal</label>
</div>
</span>
<span *ngIf="ms.selectedMail.label.indexOf('Personal') === -1">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck1"
(click)="labelClick('Personal')">
<label class="custom-control-label" for="customCheck1">Personal</label>
</div>
</span>
</label>
<label ngbDropdownItem>
<span *ngIf="ms.selectedMail.label.indexOf('Work') != -1">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck2"
(click)="labelClick('Work')" checked>
<label class="custom-control-label" for="customCheck2">Work</label>
</div>
</span>
<span *ngIf="ms.selectedMail.label.indexOf('Work') === -1">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck2"
(click)="labelClick('Work')">
<label class="custom-control-label" for="customCheck2">Work</label>
</div>
</span>
</label>
<label ngbDropdownItem>
<span *ngIf="ms.selectedMail.label.indexOf('Payment') != -1">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck3"
(click)="labelClick('Payment')" checked>
<label class="custom-control-label" for="customCheck3">Payment</label>
</div>
</span>
<span *ngIf="ms.selectedMail.label.indexOf('Payment') === -1">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck3"
(click)="labelClick('Payment')">
<label class="custom-control-label" for="customCheck3">Payment</label>
</div>
</span>
</label>
<label ngbDropdownItem>
<span *ngIf="ms.selectedMail.label.indexOf('Invoice') != -1">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck4"
(click)="labelClick('Invoice')" checked>
<label class="custom-control-label" for="customCheck4">Invoice</label>
</div>
</span>
<span *ngIf="ms.selectedMail.label.indexOf('Invoice') == -1">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck4"
(click)="labelClick('Invoice')">
<label class="custom-control-label" for="customCheck4">Invoice</label>
</div>
</span>
</label>
<label ngbDropdownItem>
<span *ngIf="ms.selectedMail.label.indexOf('Account') != -1">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck5"
(click)="labelClick('Account')" checked>
<label class="custom-control-label" for="customCheck5">Accounts</label>
</div>
</span>
<span *ngIf="ms.selectedMail.label.indexOf('Account') == -1">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck5"
(click)="labelClick('Account')">
<label class="custom-control-label" for="customCheck5">Accounts</label>
</div>
</span>
</label>
</div>
</div>
<div ngbDropdown class="d-inline-block ml-1">
<button class="btn btn-sm" id="dropdownBasic1" ngbDropdownToggle>
<i class="fa fa-ellipsis-v"></i>
</button>
<div ngbDropdownMenu aria-labelledby="dropdownBasic1">
<button ngbDropdownItem (click)="ddlRemoveClick('Read')">
<i class="far fa-envelope mr-1 text-info font-14"></i>
<span *ngIf='ms.selectedMail.seen'>Mark as unread</span>
<span *ngIf='!ms.selectedMail.seen'>Mark as read</span>
</button>
<button ngbDropdownItem (click)="ddlRemoveClick('Spam')"><i
class="fas fa-history text-primary mr-1 font-14"></i>
Spam</button>
<button ngbDropdownItem (click)="ddlRemoveClick('Trash')"><i
class="ti-trash fas text-danger mr-1 font-14"></i>Trash</button>
</div>
</div>
</div>
</div>
<spam *ngIf='ms.selectedMail'>
<div class="d-flex align-items-center p-3 border-bottom">
<h4 class="mb-0">{{ms.selectedMail.Subject}}
<span *ngFor="let l of ms.selectedMail.label" class="ml-2">
<span *ngIf='l==="Personal"' class="badge badge-pill badge-danger ml-1 font-12 font-medium"> PERSONAL
</span>
<span *ngIf='l==="Work"' class="badge badge-pill badge-info ml-1 font-12 font-medium"> WORK </span>
<span *ngIf='l==="Payment"' class="badge badge-pill badge-primary ml-1 font-12 font-medium"> PAYMENTS
</span>
<span *ngIf='l==="Invoice"' class="badge badge-pill badge-warning text-white ml-1 font-12 font-medium">
INVOICES
</span>
<span *ngIf='l==="Account"' class="badge badge-pill badge-cyan text-white ml-1 font-12 font-medium">
ACCOUNTS
</span>
</span></h4>
</div>
<div class="p-3">
<div class="mb-3 d-flex align-items-center">
<img [src]="ms.selectedUser.imagePath" class="rounded-circle" alt="userimg" width="35" height="35">
<div class="ml-2">
<h5 class="mb-0">{{ms.selectedUser.name}}</h5>
<span class="text-muted">To me,</span>
</div>
</div>
<div class="mb-4">
{{ms.selectedMail.Message}}
</div>
<div class="mb-3">
<div *ngIf='ms.replyShow'>
<textarea id="w3mission" rows="4" class="form-control" placeholder="Type your reply here"> </textarea>
<div class="d-flex align-items-center justify-content-between py-2 px-3 bg-light">
<div>
<a href="javascript:void(0)" class="link"><i class="icon-link font-16"></i></a>
<a href="javascript:void(0)" class="link"><i class="fas fa-smile font-16 ml-3"></i></a>
<a href="javascript:void(0)" class="link"><i class="fas fa-camera font-16 ml-3"></i></a>
</div>
<div>
<button type="button" class="btn btn-info" (click)='sendButtonClick()'><i
class="fas fa-arrow-left"></i></button>
<button type="button" class="btn btn-danger ml-2"><i class="fas fa-trash mr-1"></i></button>
<button type="button" class="btn btn-secondary ml-2"><i class=" fas fa-share mr-1"></i>Send</button>
</div>
</div>
</div>
<div *ngIf='!ms.replyShow'>
<button type="button" class="btn btn-outline-info btn-sm" (click)='reply()'>
<i class="fas fa-reply"></i> Reply
</button>
<button type="button" class="btn btn-outline-info ml-1 btn-sm" (click)='reply()'>
<i class="fas fa-reply-all"></i> Reply All
</button>
<button type="button" class="btn btn-outline-info ml-1 btn-sm" (click)='reply()'>
<i class="fas fa-share"></i> Forward
</button>
</div>
</div>
</div>
</spam>
import { Component, OnInit, Input } from '@angular/core';
import { getUser } from '../user-data';
import { MailGlobalVariable } from '../mail.service';
import { MailService } from '../mailService';
import { Router } from '@angular/router';
@Component({
selector: 'app-detail',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.css']
})
export class DetailComponent implements OnInit {
constructor(public ms: MailGlobalVariable,
public mailService: MailService, public router: Router) {
}
ngOnInit() {
}
labelClick(type: string) {
this.labels(type);
}
labels(label: string) {
if (this.ms.selectedMail) {
if (this.ms.selectedMail.label.indexOf(label) === -1) {
this.ms.selectedMail.label.push(label);
} else {
this.ms.selectedMail.label =
this.ms.selectedMail.label.filter(str => str !== label);
}
}
}
iconsClick(name: string) {
this.icons(name);
}
icons(icon: string) {
if (this.ms.selectedMail) {
if (this.ms.selectedMail.filter.indexOf(icon) !== -1) {
this.ms.selectedMail.filter = this.ms.selectedMail.filter.filter(fil => fil !== icon);
} else {
this.ms.selectedMail.filter.push(icon);
}
}
}
ddlRemoveClick(st: string) {
if (st === 'Spam' && this.ms.selectedMail) {
this.ms.selectedMail.mailbox = 'Spam';
if (this.ms.selectedMail) {
this.ms.spamList.push(this.ms.selectedMail);
}
this.ms.selectedMail = Object.create(null);
this.resetCount();
} else if (st === 'Trash' && this.ms.selectedMail) {
this.ms.selectedMail.mailbox = 'Trash';
if (this.ms.selectedMail) {
this.ms.trashList.push(this.ms.selectedMail);
}
this.ms.selectedMail = Object.create(null);
this.resetCount();
} else if (st === 'Read' && this.ms.selectedMail) {
if (this.ms.selectedMail.seen) {
this.ms.selectedMail.seen = false;
this.global();
} else if (this.ms.selectedMail?.seen) {
this.ms.selectedMail.seen = true;
this.global();
}
}
}
resetCount() {
this.ms.inboxList = this.mailService.getInbox();
this.ms.sentList = this.mailService.getSent();
this.ms.draftList = this.mailService.getDraft();
this.ms.spamList = this.mailService.getSpam();
this.ms.trashList = this.mailService.getTrash();
this.ms.mailList = this.ms.inboxList;
this.ms.users = [];
for (const mail of this.ms.mailList) {
// tslint:disable-next-line: no-non-null-assertion
this.ms.users.push(getUser(mail.fromId)!);
}
this.ms.collectionSize = this.ms.inboxList.length;
this.ms.selectedMail =null;
this.ms.topLable = 'Inbox';
this.ms.type = 'inbox';
this.global();
// this.router.navigate(['mail/inbox']);
}
global() {
this.ms.inboxCount = this.mailService.getInbox().
filter(inbox => inbox.mailbox === 'Inbox' && inbox.seen === false).length;
this.ms.spamCount = this.mailService.getSpam().length;
this.ms.draftCount = this.mailService.getDraft().length;
}
reply() {
this.ms.replyShow = true;
}
sendButtonClick() {
this.ms.replyShow = false;
}
removeClass() {
this.ms.addClass = false;
}
}
export class Category {
id = 0;
name: string | null = null;
icon: string | null = null;
count = 0;
color?: string | null = null;
}
export const mailbox: Category[] = [
{
id: 1,
name: 'Inbox',
icon: 'fas fa-inbox',
count: 5
},
{
id: 2,
name: 'Sent',
icon: 'fas fa-paper-plane',
count: 0
},
{
id: 3,
name: 'Draft',
icon: 'fas fa-box',
count: 5
},
{
id: 4,
name: 'Spam',
icon: 'fas fa-history',
count: 0
},
{
id: 5,
name: 'Trash',
icon: 'fas fa-trash',
count: 5
}
];
export const filter: Category[] = [
{
id: 501,
name: 'Star',
icon: 'fas fa-star',
count: 0
},
{
id: 502,
name: 'Important',
icon: 'fas fa-bookmark',
count: 0
}
];
export const label: Category[] = [
{
id: 701,
name: 'Personal',
icon: 'fas fa-tags',
count: 0,
color: '#f62d51'
},
{
id: 702,
name: 'Work',
icon: 'fas fa-tags',
count: 0,
color: '#2962ff'
},
{
id: 703,
name: 'Payment',
icon: 'fas fa-tags',
count: 0,
color: '#7460ee'
},
{
id: 704,
name: 'Invoice',
icon: 'fas fa-tags',
count: 0,
color: '#ffbc34'
},
{
id: 705,
name: 'Account',
icon: 'fas fa-tags',
count: 0,
color: '#4fc3f7'
}
];
<!-- Mobile toggle button -->
<a
[ngClass]="showSidebar ? 'ti-close' : 'ti-menu'"
class="btn btn-success show-left-part d-block d-lg-none"
href="javascript:void(0)"
(click)="mobileSidebar()"
></a>
<div class="main-part" style="height: calc(100vh - 175px)">
<div
class="left-part bg-white fixed-left-part"
[ngClass]="{ 'show-panel': showSidebar }"
>
<div class="position-relative" style="height: 100%">
<div
class="p-l-15 p-r-25 py-3 d-flex align-items-center mt-1 border-bottom"
>
<div>
<img
src="assets/images/users/8.jpg"
width="45"
alt="user"
class="rounded-circle"
/>
</div>
<div class="text-dark m-b-0 m-l-15 font-18">
Bruce Banner
<p class="m-b-0 font-12">
<i class="fa fa-circle text-success font-10 m-r-5"></i>
<span>Online</span>
</p>
</div>
</div>
<div class="p-3">
<button
type="button"
class="btn btn-info btn-block"
(click)="openModal(content)"
>
Compose
</button>
</div>
<ul class="mailbox list-style-none">
<li>
<div
class="message-center"
style="height: calc(100vh - 340px)"
[perfectScrollbar]="config"
>
<div class="p-3">
<h6 class="font-weight-normal text-muted text-uppercase mb-0">
Mailbox
</h6>
</div>
<div *ngFor="let mail of mailboxes">
<a
class="message-item border-0 d-flex align-items-center py-3"
(click)="mailboxesChanged(mail.name)"
>
<span>
<i [class]="mail.icon"></i>
</span>
<h5 class="ml-3 mb-0 font-weight-normal">{{ mail.name }}</h5>
<div class="ml-auto">
<span
*ngIf="mail.name === 'Inbox'"
class="badge badge-info badge-pill font-medium px-3 d-flex align-items-center"
>{{ ms.inboxCount }}</span
>
<span
class="badge badge-danger font-medium badge-pill px-3 d-flex align-items-center"
*ngIf="mail.name === 'Draft'"
>{{ ms.draftCount }}</span
>
<span
class="badge badge-warning text-white font-medium badge-pill px-3 d-flex align-items-center"
*ngIf="mail.name === 'Spam'"
>{{ ms.spamCount }}</span
>
</div>
</a>
</div>
<div class="p-3 border-top">
<h6 class="font-weight-normal text-muted text-uppercase mb-0">
FILTERS
</h6>
</div>
<div *ngFor="let fil of filters">
<a
class="message-item border-0 d-flex align-items-center py-3"
(click)="filtersClick(fil.name)"
>
<span>
<i [class]="fil.icon"></i>
</span>
<h5 class="ml-3 mb-0">{{ fil.name }}</h5>
</a>
</div>
<div class="p-3 border-top">
<h6 class="font-weight-normal text-muted text-uppercase mb-0">
LABELS
</h6>
</div>
<div *ngFor="let lab of labels">
<a
class="message-item border-0 d-flex align-items-center py-3"
(click)="labelChange(lab.name)"
>
<span>
<i [class]="lab.icon" [style.color]="lab.color"></i>
</span>
<h5 class="ml-3 mb-0">{{ lab.name }}</h5>
</a>
</div>
</div>
</li>
</ul>
</div>
</div>
<div class="right-part">
<div class="card mb-0">
<div class="row no-gutters">
<div class="col-lg-6 col-md-12 col-xl-4 border-right">
<div class="position-relative" style="height: 100%">
<div
class="d-flex align-items-center justify-content-between px-3 py-4 border-bottom"
>
<div>
<span class="font-16 font-medium">{{ ms.topLable }}</span>
</div>
<div class="mail-pagination">
<ngb-pagination
[collectionSize]="ms.collectionSize"
[(page)]="ms.page"
[pageSize]="ms.pageSize"
>
</ngb-pagination>
</div>
</div>
<div
class="position-relative"
style="height: calc(100vh - 258px)"
[perfectScrollbar]="config"
>
<div
*ngFor="
let mail of ms.mailList
| slice
: (ms.page - 1) * ms.pageSize
: (ms.page - 1) * ms.pageSize + ms.pageSize;
let i = index
"
(click)="mailSelected(mail)"
>
<div class="p-3 border-bottom cursor-pointer">
<div class="d-flex align-items-start">
<img
[src]="ms.users[i].imagePath"
class="rounded-circle"
alt="* *"
width="35"
height="35"
/>
<div class="ml-3">
<div class="d-flex align-items-center">
<h5 class="mb-0">{{ ms.users[i].name }}</h5>
<span
*ngIf="mail.filter.indexOf('Important') !== -1"
class="ml-2"
>
<i class="fas fa-bookmark font-12 text-warning"></i>
</span>
<span
*ngIf="mail.filter.indexOf('Star') !== -1"
class="ml-2"
>
<i class="fas fa-star font-12 text-warning"></i>
</span>
</div>
<p class="text-muted">
{{ mail.Subject | slice: 0:25 }}..
</p>
</div>
<div class="ml-auto">
<div class="text-right">
<span class="text-muted d-block">{{
mail.date | date: "dd-MMMM"
}}</span>
</div>
</div>
</div>
<p class="mb-0">
<span class="font-weight-bold" *ngIf="!mail.seen">
{{ mail.Message | slice: 0:200 }}..
</span>
<span *ngIf="mail.seen">
{{ mail.Message | slice: 0:200 }}..
</span>
</p>
</div>
</div>
</div>
</div>
</div>
<div
class="col-lg-6 col-md-12 col-xl-8 detail-part"
[class.movetodetail]="ms.addClass"
>
<div *ngIf="ms.selectedMail === null" class="h-100 d-none d-lg-block">
<div class="d-flex align-items-center justify-content-center h-100">
<div class="text-center">
<i class="far fa-envelope display-5"></i>
<h3>Select to read.</h3>
</div>
</div>
</div>
<div *ngIf="ms.selectedMail != null">
<div
class="position-relative"
style="height: calc(100vh - 180px)"
[perfectScrollbar]="config"
>
<router-outlet></router-outlet>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ----------------------------------------------------------------------------- -->
<!-- Compose Modal -->
<!-- ----------------------------------------------------------------------------- -->
<ng-template #content let-modal>
<div class="modal-header bg-info">
<h4 class="modal-title text-white">New Message</h4>
<button
type="button"
class="close"
aria-label="Close"
(click)="modal.dismiss('Cross click')"
>
<span aria-hidden="true" class="text-white">&times;</span>
</button>
</div>
<div class="modal-body">
<form action="">
<div class="form-group">
<label for="toEmail">To</label>
<input type="text" class="form-control" id="toEmail" name="toEmail" />
</div>
<div class="form-group">
<label for="subject">Subject</label>
<input type="text" class="form-control" id="subject" name="subject" />
</div>
<div class="form-group">
<textarea
class="form-control"
rows="5"
id="comment"
placeholder="Insert text here..."
></textarea>
</div>
<div
class="d-flex align-items-center justify-content-between py-2 px-3 bg-light"
>
<div>
<a href="javascript:void(0)" class="link"
><i class="icon-link font-16"></i
></a>
<a href="javascript:void(0)" class="link"
><i class="fas fa-smile font-16 ml-3"></i
></a>
<a href="javascript:void(0)" class="link"
><i class="fas fa-camera font-16 ml-3"></i
></a>
</div>
<div>
<button type="button" class="btn btn-danger ml-3">
<i class="fas fa-trash mr-1"></i>Discard
</button>
<button type="button" class="btn btn-warning ml-3">
<i class="fa-box fas mr-1"></i>Save as draft
</button>
<button type="button" class="btn btn-secondary ml-3" disabled>
Send
</button>
</div>
</div>
</form>
</div>
</ng-template>
<!-- -->
import { Component, OnInit } from '@angular/core';
import { Category, mailbox, filter, label } from './categories';
import { MailGlobalVariable } from '../mail.service';
import { MailService } from '../mailService';
import { getUser } from '../user-data';
import { mailboxList } from '../mailbox-data';
import { Mailbox } from '../mailbox';
import { Router } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { PerfectScrollbarConfigInterface } from 'ngx-perfect-scrollbar';
@Component({
selector: 'app-listing',
templateUrl: './listing.component.html',
styleUrls: ['./listing.component.css']
})
export class ListingComponent implements OnInit {
public config: PerfectScrollbarConfigInterface = {};
mailboxes: Category[] = mailbox;
filters: Category[] = filter;
labels: Category[] = label;
public showSidebar = false;
constructor(public ms: MailGlobalVariable,
public mailService: MailService, public router: Router, public modal: NgbModal) {
if (this.ms.type === null || this.ms.type === '' || this.ms.type === undefined) {
this.router.navigate(['apps/mail/inbox']);
}
this.ms.type = 'inbox';
}
ngOnInit(): void {
this.ms.mailList = this.mailService.getInbox();
this.ms.collectionSize = this.ms.mailList.length;
for (const mail of this.mailService.getInbox()) {
// tslint:disable-next-line: no-non-null-assertion
this.ms.users!.push!(getUser!(mail.fromId)!);
}
this.ms.topLable = 'Inbox';
this.global();
}
global() {
this.ms.inboxCount = this.mailService.getInbox().
filter(inbox => inbox.mailbox === 'Inbox' && inbox.seen === false).length;
this.ms.spamCount = this.mailService.getSpam().length;
this.ms.draftCount = this.mailService.getDraft().length;
}
mailboxesChanged(type: string) {
if (type === 'Inbox') {
this.ms.mailList = this.mailService.getInbox();
this.ms.collectionSize = this.mailService.getInbox().length;
this.changeCaterories(type);
this.ms.type = 'inbox';
this.router.navigate(['apps/mail/inbox']);
} else if (type === 'Sent') {
this.ms.mailList = this.mailService.getSent();
this.ms.collectionSize = this.mailService.getSent().length;
this.changeCaterories(type);
this.ms.type = 'sent';
this.router.navigate(['apps/mail/sent']);
} else if (type === 'Draft') {
this.ms.mailList = this.mailService.getDraft();
this.ms.collectionSize = this.mailService.getDraft().length;
this.changeCaterories(type);
this.ms.type = 'draft';
this.router.navigate(['apps/mail/draft']);
} else if (type === 'Spam') {
this.ms.mailList = this.mailService.getSpam();
this.ms.collectionSize = this.mailService.getSpam().length;
this.changeCaterories(type);
this.ms.type = 'spam';
this.router.navigate(['apps/mail/spam']);
} else if (type === 'Trash') {
this.ms.mailList = this.mailService.getTrash();
this.ms.collectionSize = this.mailService.getTrash().length;
this.changeCaterories(type);
this.ms.type = 'trash';
this.router.navigate(['apps/mail/trash']);
}
}
changeCaterories(category: string) {
this.ms.users = [];
for (const mail of this.ms.mailList) {
// tslint:disable-next-line: no-non-null-assertion
this.ms.users.push(getUser(mail.fromId)!);
}
this.ms.selectedMail = null;
this.ms.topLable = category;
}
mailSelected(mail: Mailbox) {
this.ms.selectedMail = null;
this.ms.selectedMail = mail;
this.ms.selectedMail.seen = true;
mail.seen = true;
this.ms.addClass = true;
// tslint:disable-next-line: no-non-null-assertion
this.ms.selectedUser = getUser(mail.fromId)!;
this.global();
if (this.ms.type === 'inbox') {
this.router.navigate(['apps/mail/inbox', mail.MailId]);
}
if (this.ms.type === 'sent') {
this.router.navigate(['apps/mail/sent', mail.MailId]);
}
if (this.ms.type === 'draft') {
this.router.navigate(['apps/mail/draft', mail.MailId]);
}
if (this.ms.type === 'spam') {
this.router.navigate(['apps/mail/spam', mail.MailId]);
}
if (this.ms.type === 'trash') {
this.router.navigate(['apps/mail/trash', mail.MailId]);
}
if (this.ms.type === 'star') {
this.router.navigate(['apps/mail/star', mail.MailId]);
}
if (this.ms.type === 'important') {
this.router.navigate(['apps/mail/important', mail.MailId]);
}
if (this.ms.type === 'Personal') {
this.router.navigate(['apps/mail/personal', mail.MailId]);
}
if (this.ms.type === 'Work') {
this.router.navigate(['apps/mail/work', mail.MailId]);
}
if (this.ms.type === 'Payment') {
this.router.navigate(['apps/mail/payment', mail.MailId]);
}
if (this.ms.type === 'Invoice') {
this.router.navigate(['apps/mail/invoice', mail.MailId]);
}
if (this.ms.type === 'Account') {
this.router.navigate(['apps/mail/account', mail.MailId]);
}
}
filtersClick(type: string) {
if (type === 'Star') {
this.filterss(type);
this.ms.type = 'star';
this.router.navigate(['apps/mail/star']);
} else if (type === 'Important') {
this.filterss(type);
this.ms.type = 'important';
this.router.navigate(['apps/mail/important']);
}
}
// tslint:disable-next-line: no-shadowed-variable
filterss(filter: string) {
this.ms.mailList = [];
for (const mail of mailboxList) {
for (const fil of mail.filter) {
if (fil === filter) {
this.ms.mailList.push(mail);
}
}
}
this.ms.users = [];
for (const mail of this.ms.mailList) {
// tslint:disable-next-line: no-non-null-assertion
this.ms.users.push(getUser(mail.fromId)!);
}
this.ms.collectionSize = this.ms.mailList.length;
this.ms.topLable = filter;
this.ms.selectedMail = null;
}
labelChange(type: string) {
if (type === 'Personal') {
this.labelss(type);
this.router.navigate(['apps/mail/personal']);
} else if (type === 'Work') {
this.labelss(type);
this.router.navigate(['apps/mail/work']);
} else if (type === 'Payment') {
this.labelss(type);
this.router.navigate(['apps/mail/payments']);
} else if (type === 'Account') {
this.labelss(type);
this.router.navigate(['apps/mail/accounts']);
} else if (type === 'Invoice') {
this.labelss(type);
this.router.navigate(['apps/mail/invoices']);
} else if (type === 'Forum') {
this.labelss(type);
this.router.navigate(['apps/mail/forum']);
}
}
labelss(type: string) {
this.ms.mailList = [];
for (const mail of mailboxList) {
// tslint:disable-next-line: no-shadowed-variable
for (const label of mail.label) {
if (label === type) {
this.ms.mailList.push(mail);
}
}
}
this.ms.users = [];
for (const mail of this.ms.mailList) {
// tslint:disable-next-line: no-non-null-assertion
this.ms.users.push(getUser(mail.fromId)!);
}
this.ms.collectionSize = this.ms.mailList.length;
this.ms.selectedMail = null;
this.ms.topLable = type;
this.ms.type = type;
}
openModal(content: string) {
this.modal.open(content, { size: 'lg' });
}
mobileSidebar() {
this.showSidebar = !this.showSidebar;
}
}
import { MailboxComponent } from './mailbox.component';
import { ListingComponent } from './listing/listing.component';
import { DetailComponent } from './detail/detail.component';
import { ComposeComponent } from './compose/compose.component';
export const routes = [
{
path: '',
component: MailboxComponent,
children: [
{ path: '', redirectTo: 'apps/mail/inbox', pathMatch: 'full' },
{ path: ':type', component: ListingComponent },
{ path: 'compose', component: ComposeComponent },
{ path: ':type/:id', component: DetailComponent }
]
}
];
import { Injectable } from '@angular/core';
import { Mailbox } from './mailbox';
import { mailboxList } from './mailbox-data';
import { User } from './user-data';
@Injectable()
export class MailGlobalVariable {
public page = 1;
public pageSize = 6;
public collectionSize = 0;
public topLable = '';
public mailList: Mailbox[] = [];
public selectedMail: Mailbox | null = null;
public selectedUser: User | null = null;
public users: User[] = [];
public inboxList: Mailbox[] = [];
public sentList: Mailbox[] = [];
public draftList: Mailbox[] = [];
public spamList: Mailbox[] = [];
public trashList: Mailbox[] = [];
public isShow = false;
inboxCount = 0;
spamCount = 0;
draftCount = 0;
replyShow = false;
addClass = true;
type = '';
}
@Injectable()
export class MailService {
public getInbox() {
return mailboxList.filter(mail => mail.mailbox === 'Inbox');
}
public getSent() {
return mailboxList.filter(mail => mail.mailbox === 'Sent');
}
public getDraft() {
return mailboxList.filter(mail => mail.mailbox === 'Draft');
}
public getSpam() {
return mailboxList.filter(mail => mail.mailbox === 'Spam');
}
public getTrash() {
return mailboxList.filter(mail => mail.mailbox === 'Trash');
}
}
import { Injectable } from '@angular/core';
import { mailboxList } from './mailbox-data';
@Injectable()
export class MailService {
public getInbox() {
return mailboxList.filter(mail => mail.mailbox === 'Inbox');
}
public getSent() {
return mailboxList.filter(mail => mail.mailbox === 'Sent');
}
public getDraft() {
return mailboxList.filter(mail => mail.mailbox === 'Draft');
}
public getSpam() {
return mailboxList.filter(mail => mail.mailbox === 'Spam');
}
public getTrash() {
return mailboxList.filter(mail => mail.mailbox === 'Trash');
}
}
import { Mailbox } from './mailbox';
export const mailboxList: Mailbox[] = [
{
MailId: 'bb428c03-1bc6-4f3d-9d5e-268ec44eebc3',
fromId: '899d0e31-b71e-4d95-a8a0-6a8bceb314bd',
Subject: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.',
date: new Date(),
Message: '1.The phrase Lorem ipsum dolor sit amet consectetuer appears in Microsoft Word online Help. This phrase has the appearance of an intelligent Latin idiom. Actually, it is nonsense.',
readStatus: true,
seen: true,
mailbox: 'Inbox',
filter: ['Star'],
label: ['Account', 'Personal']
},
{
MailId: 'a19bf9fc-e877-49e7-a75a-b089a2c35f18',
fromId: '3782c174-1f2c-4dc4-b75d-0bedf400e023',
Subject: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.',
date: new Date(),
Message: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.',
readStatus: true,
seen: true,
mailbox: 'Inbox',
filter: ['Important'],
label: []
},
{
MailId: '910d7e0a-f3b0-47a7-bb53-9036ed717298',
fromId: 'eef93cb1-7766-4413-a5cf-ecbf71fa3674',
Subject: 'consectetuer adipiscing elit.',
date: new Date(),
Message: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.',
readStatus: false,
seen: false,
mailbox: 'Inbox',
filter: [],
label: ['Invoice']
},
{
MailId: 'c79cb60a-baf8-4349-b9c3-88d567b965a2',
fromId: '899d0e31-b71e-4d95-a8a0-6a8bceb314bd',
Subject: 'Aenean commodo ligula eget dolor. Aenean massa.',
date: new Date(),
Message: 'The phrase Lorem ipsum dolor sit amet consectetuer appears. This phrase has the appearance of an intelligent Latin idiom. Actually, it is nonsense.',
readStatus: false,
seen: false,
mailbox: 'Inbox',
filter: [],
label: ['Personal']
},
{
MailId: '910d7e0a-f3b0-47a7-bb53-9036ed717298',
fromId: 'a41c6c4a-9cb1-45d1-8c6f-091044ba51ff',
Subject: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.Aenean commodo ligula eget dolor. Aenean massa.',
date: new Date(),
Message: 'The phrase Lorem ipsum dolor sit amet consectetuer appears in Microsoft Word online Help. This phrase has the appearance of an intelligent Latin idiom. Actually, it is nonsense.',
readStatus: false,
seen: false,
mailbox: 'Inbox',
filter: ['Star', 'Important'],
label: []
},
{
MailId: '35bddac1-1046-4c96-a1ac-ffd75def7f5a',
fromId: 'a41c6c4a-9cb1-45d1-8c6f-091044ba51ff',
Subject: 'Lorem ipsum dolor sit amet,Aenean commodo ligula eget dolor. Aenean massa.',
date: new Date(),
Message: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.',
readStatus: true,
seen: true,
mailbox: 'Inbox',
filter: [],
label: []
},
{
MailId: '0c914dfd-be0d-4d46-b963-47bcb064154f',
fromId: '3782c174-1f2c-4dc4-b75d-0bedf400e023',
Subject: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.Aenean commodo ligula eget dolor. Aenean massa.',
date: new Date(),
Message: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.',
readStatus: false,
seen: false,
mailbox: 'Draft',
filter: [],
label: ['Work']
},
{
MailId: '11538c3a-f2a7-4a7c-a237-4e61aa96423b',
fromId: 'a41c6c4a-9cb1-45d1-8c6f-091044ba51ff',
Subject: 'Lorem ipsum dolor sit amet,Aenean commodo ligula eget dolor. Aenean massa.',
date: new Date(),
Message: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.',
readStatus: false,
seen: false,
mailbox: 'Inbox',
filter: [],
label: ['Personal', 'Invoice']
},
{
MailId: '0f0a5482-8e4f-42a0-b3bb-1f96bc04d85a',
fromId: 'a41c6c4a-9cb1-45d1-8c6f-091044ba51ff',
Subject: 'Aenean commodo ligula eget dolor,Aenean commodo ligula eget dolor. Aenean massa.',
date: new Date(),
Message: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.',
readStatus: false,
seen: false,
mailbox: 'Inbox',
filter: [],
label: ['Account']
},
{
MailId: '2b0e4083-00e4-48fd-9cb3-05434767ca66',
fromId: '36a1ead7-57a0-4275-8a21-956194ab7cdf',
Subject: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor.',
date: new Date(),
Message: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.',
readStatus: false,
seen: false,
mailbox: 'Sent',
filter: [],
label: ['Work']
},
{
MailId: 'bf7ab76b-c076-4992-a580-13b1859cd395',
fromId: 'eef93cb1-7766-4413-a5cf-ecbf71fa3674',
Subject: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.Aenean commodo ligula eget dolor. Aenean massa.',
date: new Date(),
Message: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa..',
readStatus: false,
seen: false,
mailbox: 'Sent',
filter: [],
label: ['Payment']
}
];
.pointerCursor{
cursor: pointer;
}
.pointerCursor div:hover{
color: blue;
}
\ No newline at end of file
<div id="main">
<app-listing></app-listing>
</div>
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
import { MailGlobalVariable } from './mail.service';
@Component({
selector: 'app-mailbox',
templateUrl: './mailbox.component.html',
styleUrls: ['./mailbox.component.css']
})
export class MailboxComponent implements OnInit {
constructor(public ms: MailGlobalVariable) { }
ngOnInit(): void { }
}
export class Mailbox {
constructor(
public MailId: string,
public fromId: string,
public Subject: string,
public Message: string,
public date: Date,
public readStatus: boolean,
public seen: boolean,
public mailbox: string,
public filter: string[],
public label: string[]
) { }
}
export class User {
userId: string | null = null;
name: string | null = null;
email: string | null = null;
username: string | null = null;
jobTitle: string | null = null;
phone: string | null = null;
imagePath: string | null = null;
address: any = null;
}
export const users: User[] = [
{
userId: '65a6eb21-67b5-45c3-9af7-faca2d9b60d4',
name: 'Dessie',
email: 'Dessie7937@gmail.com',
username: 'Dessie79',
jobTitle: 'Web Developer',
phone: '1-360-812-9380 x511',
imagePath: '/assets/images/users/2.jpg',
address: ''
},
{
userId: 'ee272550-36e8-4fe2-889d-c1ee701c5863',
name: 'Hortense',
email: 'Hortense99.Jakubowski@yahoo.com',
jobTitle: 'Project Manager',
username: 'Hortense99',
phone: '712.916.2569 x0663',
imagePath: '/assets/images/users/3.jpg',
address: {
street: '9046 Allen Ferry',
suite: 'Suite 429',
city: 'Angushaven',
state: 'Michigan',
country: 'Costa Rica',
zipcode: '92378-7065',
geo: {
lat: '78.1292',
lng: '-134.6632'
}
}
},
{
userId: '77f4b102-9df5-43ba-966a-6f816806c5e2',
name: 'Pat',
jobTitle: 'Product Manager',
email: 'Pat_Zulauf81.Bartell86@gmail.com',
username: 'Pat_Zulauf81',
phone: '(058) 200-7342',
imagePath: '/assets/images/users/4.jpg',
address: {
street: '62268 Favian Coves',
suite: 'Suite 993',
city: 'Baumbachstad',
state: 'New Mexico',
country: 'Montserrat',
zipcode: '44440',
geo: {
lat: '-34.7835',
lng: '148.8907'
}
}
},
{
userId: '36a1ead7-57a0-4275-8a21-956194ab7cdf',
name: 'Solon',
jobTitle: 'Web Developer',
email: 'Solon.Bauch4_Rath@hotmail.com',
username: 'Solon.Bauch4',
phone: '789-914-4904 x173',
imagePath: '/assets/images/users/5.jpg',
address: {
street: '8153 Favian Walk',
suite: 'Apt. 495',
city: 'East Preston',
state: 'Idaho',
country: 'Iceland',
zipcode: '24555',
geo: {
lat: '-42.5691',
lng: '-2.5791'
}
}
},
{
userId: 'b5899bef-d01e-42d8-af2d-edfb16b6b21e',
name: 'Calista',
jobTitle: 'Programmer',
email: 'Calista_Mertz1757@hotmail.com',
username: 'Calista_Mertz17',
phone: '961-703-4134',
imagePath: '/assets/images/users/6.jpg',
address: {
street: '886 Wendy Circles',
suite: 'Apt. 933',
city: 'Lake Loy',
state: 'Rhode Island',
country: 'South Africa',
zipcode: '65261',
geo: {
lat: '-58.9245',
lng: '-43.6330'
}
}
},
{
userId: '7d910620-84e1-49fc-951e-d375587b8189',
name: 'Jackeline',
jobTitle: 'Sales Executive',
email: 'Jackeline.Abshire_Dach@yahoo.com',
username: 'Jackeline.Abshire',
phone: '(326) 903-5706 x6854',
imagePath: '/assets/images/users/7.jpg',
address: {
street: '416 Cathy Spur',
suite: 'Apt. 431',
city: 'North Camila',
state: 'Pennsylvania',
country: 'Libyan Arab Jamahiriya',
zipcode: '31751',
geo: {
lat: '64.0673',
lng: '154.7671'
}
}
},
{
userId: 'afdb5033-5bcc-4cec-b932-353a83410b44',
name: 'Jamey',
jobTitle: 'PHP Developer',
email: 'Jamey_Grant_Cruickshank73@gmail.com',
username: 'Jamey_Grant',
phone: '545-939-2404 x32373',
imagePath: '/assets/images/users/8.jpg',
address: {
street: '38372 Mante Glen',
suite: 'Suite 090',
city: 'Robertsside',
state: 'Texas',
country: 'Equatorial Guinea',
zipcode: '86558-7214',
geo: {
lat: '-55.0222',
lng: '-100.5977'
}
}
},
{
userId: '60d07662-bfec-42c7-b044-c81bc4ff8c7a',
name: 'Barton',
email: 'Barton85_Emard@gmail.com',
jobTitle: 'Web Developer',
username: 'Barton85',
phone: '(979) 560-8322 x174',
imagePath: '/assets/images/users/agent.jpg',
address: {
street: '185 Florine Spurs',
suite: 'Suite 178',
city: 'Port Carrollburgh',
state: 'Alaska',
country: 'Saint Barthelemy',
zipcode: '30126',
geo: {
lat: '24.0545',
lng: '-88.8499'
}
}
},
{
userId: '5c44b666-baca-4f18-a3cb-23068c6edc14',
name: 'Gloria',
jobTitle: 'Assets',
email: 'Gloria78.Nicolas83@hotmail.com',
username: 'Gloria78',
phone: '188.890.3246',
imagePath: '/assets/images/users/agent2.jpg',
address: {
street: '643 Arch Mews',
suite: 'Apt. 171',
city: 'Wymanland',
state: 'Indiana',
country: 'Jersey',
zipcode: '73594-9840',
geo: {
lat: '-70.9980',
lng: '-151.6234'
}
}
},
{
userId: '46d6f992-5729-4588-b7f8-ce74f21157ba',
name: 'Olin',
jobTitle: 'Finaice',
email: 'Olin.Robel49.Schowalter24@yahoo.com',
username: 'Olin.Robel49',
phone: '1-982-234-7756',
imagePath: '/assets/images/users/d1.jpg',
address: {
street: '0813 Mayer Greens',
suite: 'Apt. 551',
city: 'Bergstromburgh',
state: 'Ohio',
country: 'Anguilla',
zipcode: '42502-9731',
geo: {
lat: '-48.2520',
lng: '60.6556'
}
}
},
{
userId: 'bd30e201-cceb-410e-8497-a4072bc399f5',
name: 'Rollin',
jobTitle: 'Supporting',
email: 'Rollin43_Fay@yahoo.com',
username: 'Rollin43',
phone: '477-651-5715 x502',
imagePath: '/assets/images/users/d2.jpg',
address: {
street: '5704 Spinka Causeway',
suite: 'Suite 388',
city: 'Pollyburgh',
state: 'Arizona',
country: 'Virgin Islands, U.S.',
zipcode: '45048',
geo: {
lat: '55.3046',
lng: '3.8129'
}
}
},
{
userId: 'da95e977-cd54-4077-a767-1b7f33ef6919',
name: 'Murl',
email: 'Murl_Abshire41_Lakin@hotmail.com',
username: 'Murl_Abshire41',
jobTitle: 'Web Developer',
phone: '107-733-1219 x0615',
imagePath: '/assets/images/users/d3.jpg',
address: {
street: '4880 Tanner Circles',
suite: 'Apt. 994',
city: 'Bauchside',
state: 'Ohio',
country: 'Uganda',
zipcode: '11259',
geo: {
lat: '11.6209',
lng: '-45.1766'
}
}
},
{
userId: '6124d4e8-77ed-4b34-868d-d312bfab5de2',
name: 'Breanna',
jobTitle: 'Web Developer',
email: 'Breanna.Bartoletti21@hotmail.com',
username: 'Breanna.Bartoletti',
phone: '645.045.0876 x35882',
imagePath: '/assets/images/users/d4.jpg',
address: {
street: '431 Grimes Common',
suite: 'Apt. 530',
city: 'East Lunahaven',
state: 'Virginia',
country: 'Hungary',
zipcode: '12012-3038',
geo: {
lat: '29.7991',
lng: '-70.4033'
}
}
},
{
userId: 'eef93cb1-7766-4413-a5cf-ecbf71fa3674',
name: 'Maya',
email: 'Maya55_Dickens16@yahoo.com',
username: 'Maya55',
jobTitle: 'Web Developer',
phone: '199.260.3770 x2815',
imagePath: 'assets/images/users/d5.jpg',
address: {
street: '58581 Guillermo Springs',
suite: 'Suite 574',
city: 'Cloydville',
state: 'Delaware',
country: 'Saint Barthelemy',
zipcode: '95633-3394',
geo: {
lat: '-57.5740',
lng: '104.5634'
}
}
},
{
userId: '899d0e31-b71e-4d95-a8a0-6a8bceb314bd',
name: 'Santiago',
jobTitle: 'Web Developer',
email: 'Santiago41_Crooks15@yahoo.com',
username: 'Santiago41',
phone: '1-489-921-2159 x8655',
imagePath: 'assets/images/users/profile.png',
address: {
street: '7868 Windler Dam',
suite: 'Suite 876',
city: 'Port Emmetfurt',
state: 'Alabama',
country: 'Belarus',
zipcode: '63739-4581',
geo: {
lat: '-28.7166',
lng: '-167.7070'
}
}
},
{
userId: 'a41c6c4a-9cb1-45d1-8c6f-091044ba51ff',
name: 'Leonardo',
jobTitle: 'Web Developer',
email: 'Leonardo10.Macejkovic@yahoo.com',
username: 'Leonardo10',
phone: '445-761-1519',
imagePath: 'assets/images/users/1.jpg',
address: {
street: '146 Lemke Mountains',
suite: 'Apt. 407',
city: 'North Toyfort',
state: 'Connecticut',
country: 'Senegal',
zipcode: '90211-1855',
geo: {
lat: '-56.3849',
lng: '-167.1372'
}
}
},
{
userId: '3782c174-1f2c-4dc4-b75d-0bedf400e023',
name: 'Lora',
jobTitle: 'Web Developer',
email: 'Lora_Kessler586@hotmail.com',
username: 'Lora_Kessler5',
phone: '315-215-2852 x69280',
imagePath: 'assets/images/users/1.jpg',
address: {
street: '4018 Willms Turnpike',
suite: 'Suite 573',
city: 'Leuschkemouth',
state: 'Kentucky',
country: 'Dominican Republic',
zipcode: '70964',
geo: {
lat: '80.2384',
lng: '38.1323'
}
}
}
];
export function getUser(uid: string): User | undefined {
return users.find(u => u.userId === uid);
}
import { Injectable } from '@angular/core';
import { Note } from './note';
import { notes } from './notes-data';
@Injectable()
export class NoteService {
public notes: Note[] = notes;
public getNotes() {
return this.notes;
}
}
export class Note {
color = '';
title = '';
datef: Date | null = null;
}
import { Note } from './note';
export const notes: Note[] = [
{
color: 'info',
title: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
datef: new Date('1/3/2020')
}, {
color: 'danger',
title: 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit,',
datef: new Date('1/2/2020')
}, {
color: 'warning',
title: 'consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur?',
datef: new Date('1/1/2020')
}
];
<a [ngClass]="(showSidebar)?'ti-close':'ti-menu'" class="btn btn-success show-left-part d-block d-md-none"
href="javascript:void(0)" (click)="mobileSidebar()"></a>
<div class="main-part">
<div class="left-part bg-white overflow-auto fixed-left-part" [ngClass]="{'show-panel': showSidebar}">
<div class="position-relative">
<div class="p-l-15 p-r-25 py-3 d-flex align-items-center border-bottom">
<input class="form-control" type="text" name="search" placeholder="Search Notes" [(ngModel)]="searchText" />
</div>
<div>
<div class="notes-list" *ngIf="notes.length > 0; else elseBlock">
<div *ngFor='let note of notes | filter:searchText' class="notes-item" (click)="onSelect(note);"
[class.selected]="note === selectedNote">
<div class="d-flex py-3 border-bottom pr-3 position-relative">
<div>
<span class="note-color bg-{{note.color}}"></span>
<span class="note-title text-truncate">{{note.title}}</span>
<small class="note-time">{{note.datef | date}}</small>
</div>
<span (click)="removenote(note)" class="ml-auto remove-note">x</span>
</div>
</div>
</div>
<ng-template #elseBlock>
<p class="mb-0 text-center font-18 font-bold mt-5">No Notes Found</p>
</ng-template>
</div>
</div>
</div>
<div class="right-part bg-white overflow-auto">
<div class="card mb-0">
<div class="p-l-15 p-r-25 py-3 d-flex align-items-center border-bottom">
<div class="w-50" *ngIf="selectedNote">
<button type="button" class="btn btn-{{clrName}} mr-2" placement="right" [ngbPopover]="popContent"
[autoClose]="'outside'" popoverTitle="Choose colors">
</button>
<span>Choose color for note</span>
</div>
<ng-template #popContent>
<ul class="pl-0 mb-0">
<li *ngFor="let c of colors" class="btn btn-sm rounded btn-{{c.colorName}} mr-2"
(click)="onSelectColor(c.colorName);">&nbsp;</li>
</ul>
</ng-template>
<div class="ml-auto">
<button type="button" id="btnAddNote" class="btn btn-primary" (click)="addNoteClick()">Add Notes</button>
</div>
</div>
<div class="bg-white">
<div class="" *ngIf="notes.length > 0">
<textarea [(ngModel)]="selectedNote.title" rows="5" class="form-control note-content"
placeholder="name"> </textarea>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
.note-color {
position: absolute;
width: 5px;
height: 100%;
left: 0;
top: 0;
}
.notes-item.selected {
background-color: #e9ecef;
}
.note-title {
width: 200px;
font-size: 16px;
}
.note-title,
.note-time {
margin-left: 15px;
display: block;
}
.note-content {
border: none;
resize: none;
padding-top: 15px;
padding-left: 15px;
height: 100%;
}
.remove-note,
.notes-item {
cursor: pointer;
}
import { Component, OnInit } from '@angular/core';
import { Note } from './note';
import { NoteService } from './note.service';
@Component({
selector: 'app-notes',
templateUrl: './notes.component.html',
styleUrls: ['./notes.component.scss']
})
export class NotesComponent implements OnInit {
public showSidebar = false;
notes = this.noteService.getNotes();
selectedNote: Note = Object.create(null);
searchText = '';
clrName = 'warning';
colors = [{ colorName: 'info' }, { colorName: 'warning' }, { colorName: 'danger' }, { colorName: 'success' }];
constructor(public noteService: NoteService) {
}
mobileSidebar() {
this.showSidebar = !this.showSidebar;
}
ngOnInit() {
this.onLoad();
}
onLoad() {
this.selectedNote = this.notes[0];
}
onSelect(note: Note) {
this.selectedNote = note;
this.clrName = this.selectedNote.color;
}
onSelectColor(colorName: string) {
this.clrName = colorName;
this.selectedNote.color = this.clrName;
}
removenote(note: Note) {
const index: number = this.notes.indexOf(note);
if (index !== -1) {
this.notes.splice(index, 1);
this.selectedNote = this.notes[0];
}
}
addNoteClick() {
this.notes.push({
color: this.clrName,
title: 'this is New notes',
datef: new Date()
});
}
}
<div class="card">
<div class="card-body" cdkDropListGroup>
<div class="mb-3">
<button class="btn btn-primary" (click)="openModal(taskModal, null)">Create Task</button>
</div>
<div class="taskboard page-height p-0">
<div class="taskboard-wrapper todos">
<div class="taskboard-list">
<h6 class="taskboard-header font-weight-bold mt-2">Todos</h6>
<div class="taskboard-cards" cdkDropList (cdkDropListDropped)="drop($event)" [cdkDropListData]="todos">
<div class="taskboard-task cursor-pointer" cdkDrag *ngFor="let todo of todos">
<div class="taskboard-task-title font-medium">{{ todo.title }}</div>
<small class="card-text text-muted">{{ todo.desc }}</small>
<div class="mt-2 d-flex justify-content-start align-items-center">
<a href="javascript:void(0)" class="link" (click)="openModal(taskModal, todo)">
<i-feather name="eye" class="feather-xs"></i-feather>
</a>
<a href="javascript:void(0)" class="text-danger ml-2" (click)="deleteTask(todo.id)">
<i-feather name="trash-2" class="feather-xs"></i-feather>
</a>
</div>
</div>
</div>
</div>
</div>
<div class="taskboard-wrapper inprocess">
<div class="taskboard-list">
<h6 class="taskboard-header font-weight-bold mt-2">In Process</h6>
<div class="taskboard-cards" cdkDropList (cdkDropListDropped)="drop($event)" [cdkDropListData]="process">
<div class="taskboard-task cursor-pointer" cdkDrag *ngFor="let inprocess of process">
<div class="taskboard-task-title font-medium">{{ inprocess.title }}</div>
<small class="card-text text-muted">{{ inprocess.desc }}</small>
<div class="mt-2 d-flex justify-content-start align-items-center">
<a href="javascript:void(0)" class="link" (click)="openModal(taskModal, inprocess)">
<i-feather name="eye" class="feather-xs"></i-feather>
</a>
<a href="javascript:void(0)" class="text-danger ml-2" (click)="deleteTask(inprocess.id)">
<i-feather name="trash-2" class="feather-xs"></i-feather>
</a>
</div>
</div>
</div>
</div>
</div>
<div class="taskboard-wrapper pending">
<div class="taskboard-list">
<h6 class="taskboard-header font-weight-bold mt-2">Pending todos</h6>
<div class="taskboard-cards" cdkDropList (cdkDropListDropped)="drop($event)" [cdkDropListData]="pendings">
<div class="taskboard-task cursor-pointer" cdkDrag *ngFor="let pendingtask of pendings">
<div class="taskboard-task-title font-medium">{{ pendingtask.title }}</div>
<small class="card-text text-muted">{{ pendingtask.desc }}</small>
<div class="mt-2 d-flex justify-content-start align-items-center">
<a href="javascript:void(0)" class="link" (click)="openModal(taskModal, pendingtask)">
<i-feather name="eye" class="feather-xs"></i-feather>
</a>
<a href="javascript:void(0)" class="text-danger ml-2" (click)="deleteTask(pendingtask.id)">
<i-feather name="trash-2" class="feather-xs"></i-feather>
</a>
</div>
</div>
</div>
</div>
</div>
<div class="taskboard-wrapper taskdone">
<div class="taskboard-list">
<h6 class="taskboard-header font-weight-bold mt-2">Task Done</h6>
<div class="taskboard-cards" cdkDropList (cdkDropListDropped)="drop($event)" [cdkDropListData]="done">
<div class="taskboard-task cursor-pointer" cdkDrag *ngFor="let taskdone of done">
<div class="taskboard-task-title font-medium">{{ taskdone.title }}</div>
<small class="card-text text-muted">{{ taskdone.desc }}</small>
<div class="mt-2 d-flex justify-content-start align-items-center">
<a href="javascript:void(0)" class="link" (click)="openModal(taskModal, taskdone)">
<i-feather name="eye" class="feather-xs"></i-feather>
</a>
<a href="javascript:void(0)" class="text-danger ml-2" (click)="deleteTask(taskdone.id)">
<i-feather name="trash-2" class="feather-xs"></i-feather>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #taskModal let-modal>
<div class="modal-header">
<h3 class="modal-title font-weight-bold" id="taskLabel">Task</h3>
<button type="button" class="close" (click)="closeBtnClick()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<form [formGroup]="task" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="form-group row">
<label for="name" class="col-sm-4 col-form-label">Task Title</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Title" id="title">
</div>
</div>
<div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">Description</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Description" id="description">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-dark" (click)="closeBtnClick()">Close</button>
<button type="submit" class="btn btn-primary" [disabled]="task.invalid">Save</button>
</div>
</form>
</ng-template>
:host {
padding: 0 !important;
height: 100%;
}
.cursor-pointer {
cursor: move;
}
.cdk-drag-preview {
box-sizing: border-box;
background-color: #fff;
padding: 10px 15px;
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
}
.gu-mirror {
background-color: white;
border-radius: 0.125rem;
padding: 0.5rem;
opacity: 1;
}
.cdk-drag-animating {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder) {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
.feather-xs {
width: 17px !important;
height: 17px !important;
}
.taskboard .todos .taskboard-list {
background-color: #e3f3fd;
}
.taskboard .inprocess .taskboard-list {
background-color: #fff8ec;
}
.taskboard .pending .taskboard-list {
background-color: #f9e7eb;
}
.taskboard .taskdone .taskboard-list {
background-color: #e8fdf8;
}
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-taskboard',
templateUrl: './taskboard.component.html',
styleUrls: ['./taskboard.component.scss']
})
export class TaskboardComponent implements OnInit {
task: FormGroup | null = null;
todoToEdit: any = null;
constructor(private fb: FormBuilder, private modalService: NgbModal) {
}
ngOnInit() {
this.task = this.fb.group({
Title: ['', Validators.required],
Description: ['', Validators.required],
});
}
todos = [
{
id: 101,
title: 'QA Testing',
desc: 'Etiam porta sem malesuada magna mollis euismod.',
class: '',
},
{
id: 102,
title: 'Layout design',
desc:
'Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.',
class: 'task-status-danger',
},
{
id: 103,
title: 'Fix navigation menu',
desc: 'Donec sed odio dui.',
class: 'task-status-info',
},
{
id: 104,
title: 'Update bootstrap 4',
desc: 'Aenean lacinia bibendum nulla sed consectetur.',
class: '',
},
{
id: 105,
title: 'Run build tools',
desc:
'Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.',
class: '',
},
{
id: 106,
title: 'List article ideas',
desc:
'Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.',
class: 'task-status-success',
},
{
id: 107,
title: 'Reactjs fixes',
desc: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
class: '',
},
{
id: 108,
title: 'Implement SSL',
desc: 'Etiam porta sem malesuada magna mollis euismod.',
class: 'task-status-warning',
},
];
process = [
{
id: 201,
title: 'QOS Assessment',
desc: 'Maecenas sed diam eget risus varius blandit sit amet non magna.',
class: '',
},
{
id: 202,
title: 'Schedule new tasks',
desc: 'Sed posuere consectetur est at lobortis.',
class: 'task-status-warning',
},
{
id: 203,
title: 'Add dashboard variants',
desc: 'Nulla vitae elit libero, a pharetra augue.',
class: '',
},
{
id: 204,
title: 'Extended color scheme support',
desc: 'Morbi leo risus, porta ac consectetur ac, vestibulum ateros.',
class: '',
},
{
id: 205,
title: 'Merge unit tests',
desc: 'Maecenas sed diam eget risus varius blandit sit amet non magna.',
class: 'task-status-info',
},
{
id: 206,
title: 'Test final version',
desc:
'Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.',
class: '',
},
];
pendings = [
{
id: 301,
title: 'Integrate Angular 4',
desc: 'Nulla vitae elit libero, a pharetra augue.',
class: '',
},
{
id: 302,
title: 'Additional fields',
desc: 'Donec id elit non mi porta gravida at eget metus.',
class: '',
},
{
id: 303,
title: 'Draggable task board',
desc: 'Sed posuere consectetur est at lobortis.',
class: 'task-status-danger',
},
{
id: 304,
title: 'Setup CI server',
desc: 'Maecenas faucibus mollis interdum.',
class: 'task-status-danger',
},
{
id: 305,
title: 'Assign new tasks',
desc: 'Nullam quis risus eget urna mollis ornare vel eu leo.',
class: '',
},
{
id: 306,
title: 'Contact administrator',
desc:
'Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.',
class: '',
},
{
id: 307,
title: 'Commit changes',
desc: 'Aenean lacinia bibendum nulla sed consectetur.',
class: '',
},
];
done = [
{
id: 401,
title: 'Store new files',
desc: 'Sed posuere consectetur est at lobortis.',
class: 'task-status-info',
},
{
id: 402,
title: 'Build landing page',
desc: 'Maecenas sed diam eget risus varius blandit sit amet non magna.',
class: '',
},
{
id: 403,
title: 'Setup basic layout',
desc: 'Vestibulum id ligula porta felis euismod semper.',
class: '',
},
{
id: 404,
title: 'Graphical fixes',
desc: 'Morbi leo risus, porta ac consectetur ac, vestibulum at eros.',
class: '',
},
{
id: 405,
title: 'Email alerts',
desc: 'Donec sed odio dui.',
class: 'task-status-warning',
},
];
drop(event: CdkDragDrop<string[]>) {
if (event.previousContainer === event.container) {
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
} else {
transferArrayItem(event.previousContainer.data,
event.container.data,
event.previousIndex,
event.currentIndex);
}
}
openModal(targetModal: NgbModal, data: any) {
this.modalService.open(targetModal, {
centered: true,
backdrop: 'static'
});
if (data != null) {
this.todoToEdit = data;
this.task?.patchValue({
Title: data.title,
Description: data.desc
});
}
}
onSubmit() {
if (this.todoToEdit === null) {
this.todos.push({
id: this.todos.length + 1,
title: this.task?.get('Title')?.value,
desc: this.task?.get('Description')?.value,
class: '',
});
alert('Task added !');
}
else {
let index = -5;
if (this.todos.indexOf(this.todoToEdit) !== -1) {
index = this.todos.indexOf(this.todoToEdit)
}
else if (this.process.indexOf(this.todoToEdit) !== -1) {
index = this.process.indexOf(this.todoToEdit)
}
else if (this.pendings.indexOf(this.todoToEdit) !== -1) {
index = this.pendings.indexOf(this.todoToEdit)
}
else if (this.done.indexOf(this.todoToEdit) !== -1) {
index = this.done.indexOf(this.todoToEdit)
}
if (index !== -5) {
this.todoToEdit.title = this.task?.get('Title')?.value;
this.todoToEdit.desc = this.task?.get('Description')?.value;
this.todos[index] = this.todoToEdit;
}
}
this.closeBtnClick();
}
deleteTask(taskId: any) {
if (confirm('Are you sure to delete it ?')) {
this.todos = this.todos.filter(task => task.id !== taskId);
this.process = this.process.filter(task => task.id !== taskId);
this.pendings = this.pendings.filter(task => task.id !== taskId);
this.done = this.done.filter(task => task.id !== taskId);
}
}
closeBtnClick() {
this.todoToEdit = null;
this.modalService.dismissAll();
this.ngOnInit();
}
}
import { Injectable} from '@angular/core';
import {NgbDateAdapter, NgbDateParserFormatter} from '@ng-bootstrap/ng-bootstrap';
import { NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
/**
* This Service handles how the date is represented in scripts i.e. ngModel.
*/
@Injectable()
export class CustomAdapter extends NgbDateAdapter<string> {
readonly DELIMITER = '-';
fromModel(value: string | null): NgbDateStruct | null {
if (value) {
const date = value.split(this.DELIMITER);
return {
day : parseInt(date[0], 10),
month : parseInt(date[1], 10),
year : parseInt(date[2], 10)
};
}
return null;
}
toModel(date: NgbDateStruct | null): string | null {
return date ? date.day + this.DELIMITER + date.month + this.DELIMITER + date.year : null;
}
}
/**
* This Service handles how the date is rendered and parsed from keyboard i.e. in the bound input field.
*/
@Injectable()
export class CustomDateParserFormatter extends NgbDateParserFormatter {
readonly DELIMITER = '/';
parse(value: string): NgbDateStruct | null {
if (value) {
const date = value.split(this.DELIMITER);
return {
day : parseInt(date[0], 10),
month : parseInt(date[1], 10),
year : parseInt(date[2], 10)
};
}
return null;
}
format(date: NgbDateStruct | null): string {
return date ? date.day + this.DELIMITER + date.month + this.DELIMITER + date.year : '';
}
}
import { TaskSection } from './tasks';
export const sectionWiseTask: TaskSection[] =
[
{
Id: 101,
status: false,
title: 'Design the solution',
priority: 'normal',
dueDate: '25-05-2020',
notes: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.',
sectionTaskType: 'section',
border: false
},
{
Id: 102,
status: true,
title: 'Identify resources to be monitored.',
priority: 'low',
dueDate: '25-05-2020',
notes: 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using.',
sectionTaskType: 'task',
border: false
},
{
Id: 103,
status: false,
title: 'Define users and workflow',
priority: 'low',
dueDate: '25-05-2020',
notes: 'Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for \'lorem ipsum\' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).',
sectionTaskType: 'task',
border: false
},
{
Id: 104,
status: false,
title: 'Identify event sources by resource type.',
priority: 'high',
dueDate: '25-05-2020',
notes: 'Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words',
sectionTaskType: 'task',
border: false
},
{
Id: 105,
status: false,
title: 'Define the relationship between resources and business systems.',
priority: 'normal',
dueDate: '25-05-2020',
notes: 'If you are going to use a passage of Lorem Ipsum, you need to be sure there isn\'t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet.',
sectionTaskType: 'task',
border: false
},
{
Id: 106,
status: true,
title: 'Identify tasks and URLs by resource type.',
priority: 'high',
dueDate: '25-05-2020',
notes: 'It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.',
sectionTaskType: 'task',
border: false
},
{
Id: 107,
status: false,
title: 'Prepare for implementation',
priority: 'normal',
dueDate: '31-05-2015',
notes: 'The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33.',
sectionTaskType: 'section',
border: false
},
{
Id: 108,
status: true,
title: 'Identify the implementation team.',
priority: 'low',
dueDate: '14-01-2018',
notes: 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using.',
sectionTaskType: 'task',
border: false
},
{
Id: 109,
status: false,
title: 'Order the server hardware for production assurance (QA).',
priority: 'low',
dueDate: '15-11-2019',
notes: 'Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.',
sectionTaskType: 'task',
border: false
},
{
Id: 110,
status: false,
title: 'Order console machines.',
priority: 'low',
dueDate: '09-01-2015',
notes: 'Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?',
sectionTaskType: 'task',
border: false
},
{
Id: 111,
status: true,
title: 'Order prerequisite software.',
priority: 'normal',
dueDate: '21-12-2016',
notes: 'But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness.',
sectionTaskType: 'task',
border: false
},
{
Id: 112,
status: true,
title: 'Identify production LPARs.',
priority: 'high',
dueDate: '19-01-2019',
notes: 'Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise',
sectionTaskType: 'task',
border: false
}
];
import { Injectable } from '@angular/core';
import { sectionWiseTask } from './tasks-data';
@Injectable({
providedIn: 'root'
})
export class TasksService {
public sidebarShow = false;
constructor() { }
public getSectionWiseTask() {
return sectionWiseTask;
}
}
.cursor{
cursor: pointer;
}
.custom-checkbox-width {
width: 16px;
height: 16px;
}
.text-decoration-linethrougth {
text-decoration: line-through;
}
.border-md-left {
border-left: 3px solid blue;
}
.border-md-left-none {
border-left: 0;
}
.drag-list .drag-icon {
visibility: hidden;
}
.drag-list:hover .drag-icon {
visibility: visible;
}
@media (max-width: 767px) {
.drag-list .drag-icon {
visibility: visible;
}
}
.cdk-drag-animating {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder) {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
<!-- -------------------------------------------------------------------------------------- -->
<!-- Right sidebar of task -->
<!-- -------------------------------------------------------------------------------------- -->
<div class="app-sidebar card" id="rightMenu">
<div *ngIf='selectedST !== null'>
<!-- -------------------------------------------------------------------------------------- -->
<!-- Header of sidebar -->
<!-- -------------------------------------------------------------------------------------- -->
<div class="d-flex p-3 border-bottom card-header">
<div *ngIf='selectedST' class="d-flex align-items-center">
<input type="checkbox" class="custom-checkbox-width" [(ngModel)]='selectedST.status'
(change)="checkboxValue($event,selectedST)">
<label *ngIf='selectedST.status' class="ml-3 mb-0 text-dark font-medium">MARK AS INCOMPLETE</label>
<label *ngIf='!selectedST.status' class="ml-3 mb-0 text-dark font-medium">MARK AS COMPLETE</label>
</div>
<div class="ml-auto">
<a href="javascript:void(0)" class="text-danger" (click)='closeRightMenu()'>
<i-feather name="x" class="feather-sm"></i-feather>
</a>
</div>
</div>
<!-- ./ Header of sidebar -->
<!-- -------------------------------------------------------------------------------------- -->
<!-- Body of sidebar -->
<!-- -------------------------------------------------------------------------------------- -->
<div class="p-4">
<form *ngIf='selectedST'>
<div class="form-group">
<label>{{titleTaskSection}} Title</label>
<textarea class="form-control" name="title" rows="3" [(ngModel)]='selectedST.title'></textarea>
</div>
<div class="form-group row">
<div class="col">
<label> Priority</label>
<select class="form-control" name="priority" [(ngModel)]='selectedST.priority'>
<option value="low">Low</option>
<option value="normal">Normal</option>
<option value="high">High</option>
</select>
</div>
<div class="col">
<label>Due Date</label>
<div class="form-group">
<div class="input-group">
<input class="form-control" placeholder="Due Date" name="d2" #c2="ngModel"
[(ngModel)]="selectedST.dueDate" ngbDatepicker #d2="ngbDatepicker">
<div class="input-group-append">
<button class="btn btn-outline-secondary calendar" (click)="d2.toggle()"
type="button">
<i-feather name="calendar" class="feather-sm"></i-feather>
</button>
</div>
</div>
</div>
</div>
</div>
<div class="form-group">
<label>Notes</label>
<textarea class="form-control" name="notes" rows="5" [(ngModel)]='selectedST.notes'></textarea>
</div>
<div class="form-group">
<button type="button" class="btn btn-success btn-block" (click)='closeRightMenu()'>
<i-feather name="save" class="feather-sm mr-2"></i-feather>
Save
{{titleTaskSection}}
</button>
</div>
<div class="form-group">
<button type="button" class="btn btn-danger btn-block" (click)='deleteClick(selectedST)'>
<i-feather name="trash-2" class="feather-sm mr-2"></i-feather>
Delete
{{titleTaskSection}}
</button>
</div>
</form>
</div>
<!-- ./ Body of sidebar -->
</div>
</div>
<!-- -------------------------------------------------------------------------------------- -->
<!-- Task header -->
<!-- -------------------------------------------------------------------------------------- -->
<div class="d-md-flex align-items-center mt-2 bg-white p-3">
<div>
<h3 class="mb-0">Tasks</h3>
</div>
<div class="ml-auto">
<!-- Add Task -->
<button type="button" class="btn btn-cyan text-white" (click)='addTaskSection("task")'>
<i-feather name="plus" class="feather-sm mr-2"></i-feather>
Add Task
</button>
<!-- Add new section -->
<button type="button" class="btn btn-dark ml-3" (click)='addTaskSection("section")'>
<i-feather name="plus" class="feather-sm mr-2"></i-feather> Add
Section
</button>
</div>
</div>
<!-- -------------------------------------------------------------------------------------- -->
<!-- Listing of no. of Tasks -->
<!-- -------------------------------------------------------------------------------------- -->
<div class="d-md-flex align-items-center justify-content-between border-top border-bottom bg-white p-2">
<!-- No. of Incomplete task -->
<a href="javascript:void(0)" class="d-flex align-items-center p-2 rounded-pill bg-light">
<span class="badge badge-danger badge-pill px-3 font-weight-bold font-14">{{count}}</span>
<h5 class="mb-0 ml-1 text-dark"> Incomplete Task(s)
</h5>
</a>
<!-- No. of complete task -->
<a href="javascript:void(0)" class="d-flex align-items-center p-2 rounded-pill bg-light mt-3 mt-md-0">
<span class="badge badge-success badge-pill px-3 font-weight-bold font-14">{{completedcount}}</span>
<h5 class="mb-0 ml-1 text-dark"> Complete Task(s)
</h5>
</a>
<!-- No. of Total task -->
<a href="javascript:void(0)" class="d-flex align-items-center p-2 rounded-pill bg-light mt-3 mt-md-0">
<span class="badge badge-info badge-pill px-3 font-weight-bold font-14">{{totalcount}}</span>
<h5 class="mb-0 ml-1 text-dark"> Total Task(s)
</h5>
</a>
</div>
<!-- -------------------------------------------------------------------------------------- -->
<!-- Listing of available tasks -->
<!-- -------------------------------------------------------------------------------------- -->
<div cdkDropList (cdkDropListDropped)="drop($event)" class="bg-white">
<div cdkDrag *ngFor='let st of sectionTask;let i=index' class="drag-list">
<!-- If the section is available and on click add border on left side -->
<div *ngIf="st.sectionTaskType==='section'">
<div class="bg-light text-dark cursor p-3 d-flex align-items-center" (click)='sectionTaskSelected(st)'
[ngStyle]="{'border-left':st.border ? '3px solid #2962ff' : 'none' }">
<i class="mdi mdi-drag-vertical font-20 drag-icon my-n2"></i>
<div class="font-weight-bold font-18">{{st.title}}</div>
</div>
</div>
<!-- ./If the section is available and on click add border on left side -->
<!-- If the list is available and on click add border on left side -->
<div *ngIf="st.sectionTaskType==='task'" class="d-md-flex align-items-center p-3 cursor border-bottom"
[ngStyle]="{'border-left':st.border ? '3px solid #2962ff' : 'none' }">
<div class="cursor d-flex align-items-center">
<div class="flex-shrink-0 d-flex align-items-center">
<i class="mdi mdi-drag-vertical font-20 drag-icon my-n2"></i>
<!-- checkbox -->
<!-- <input type="checkbox" class="mr-2 custom-checkbox-width" [checked]='st.status'
(change)="checkboxValue($event,st)"> -->
<span class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="check{{i}}" [checked]='st.status'
(change)="checkboxValue($event,st)">
<label class="custom-control-label" for="check{{i}}">
</label>
</span>
</div>
<!-- If task is completed [Title] -->
<span *ngIf='st.status' (click)='sectionTaskSelected(st)'>
<span class="text-muted font-16 text-decoration-linethrougth">{{st.title}}</span>
</span>
<!-- If task is not completed [Title] -->
<div *ngIf='!st.status' (click)='sectionTaskSelected(st)'>
<span class="font-16"> {{st.title}}</span>
</div>
</div>
<!-- priority of tasks -->
<div class="ml-auto mt-3 mt-md-0" (click)='sectionTaskSelected(st)'>
<div class="d-flex align-items-center justify-content-center">
<span *ngIf="st.priority==='low'" class="mr-3 text-success font-medium text-center">
<i class="fas fa-caret-down mr-1 font-18 d-block"></i> low
</span>
<span *ngIf="st.priority==='high'" class="mr-3 text-danger font-medium text-center">
<i class="fas fa-caret-up mr-1 font-18 d-block"></i> high
</span>
<div class="ml-auto text-center border-left pl-3">
<div class="text-center">
<i-feather name="calendar" class="feather-sm mr-1"></i-feather>
</div>
<span class="font-weight-normal text-muted">{{st.dueDate }}</span>
</div>
</div>
</div>
</div>
<!-- ./ If the list is available and on click add border on left side -->
</div>
</div>
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
import { TasksService } from './tasks-service.service';
import { TaskSection } from './tasks';
import { moveItemInArray } from '@angular/cdk/drag-drop';
import { CustomAdapter, CustomDateParserFormatter } from './date.service';
import { NgbDateAdapter, NgbDateParserFormatter } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-tasks',
templateUrl: './tasks.component.html',
styleUrls: ['./tasks.component.css'],
providers: [
{ provide: NgbDateAdapter, useClass: CustomAdapter },
{ provide: NgbDateParserFormatter, useClass: CustomDateParserFormatter }
]
})
export class TasksComponent implements OnInit {
sectionTask: TaskSection[] | null = null;
selectedST: TaskSection | undefined = Object.create(null);
count = 0;
totalcount = 0;
completedcount = 0;
titleTaskSection = '';
borderClass = false;
constructor(public ts: TasksService) {
this.sectionTask = ts.getSectionWiseTask();
this.remainingTasks();
this.totalcount = this.sectionTask.filter(st => st.sectionTaskType === 'task').length;
this.completedcount = this.sectionTask.filter(st => st.sectionTaskType === 'task' && st.status).length;
}
ngOnInit(): void {
}
addTaskSection(funtion: string) {
if ((document.getElementById('rightMenu')as HTMLFormElement).style.width === '300px') {
this.closeRightMenu();
return;
}
(document.getElementById('rightMenu')as HTMLFormElement).style.width = '300px';
if (funtion === 'task') {
this.titleTaskSection = 'Task';
const task = new TaskSection();
task.status = false;
task.sectionTaskType = 'task';
task.title = 'Task';
task.priority = 'normal';
this.sectionTask?.splice(0, 0, task);
this.sectionTask?.push(task);
this.selectedST = this.sectionTask?.find(tk => tk === task);
} else {
this.titleTaskSection = 'Section';
const section: TaskSection = new TaskSection();
section.status = false;
section.sectionTaskType = 'section';
section.title = 'Section';
section.priority = 'normal';
this.sectionTask?.splice(0, 0, section);
this.sectionTask?.push(section);
this.selectedST = this.sectionTask?.find(sec => sec === section);
}
this.remainingTasks();
}
sectionTaskSelected(selected: TaskSection) {
if ((document.getElementById('rightMenu')as HTMLFormElement).style.width === '300px') {
this.closeRightMenu();
return;
}
(document.getElementById('rightMenu')as HTMLFormElement).style.width = '300px';
if (selected.sectionTaskType === 'section') {
this.titleTaskSection = 'Section';
} else {
this.titleTaskSection = 'Task';
}
this.selectedST = selected;
this.selectedST.border = true;
}
closeRightMenu() {
(document.getElementById('rightMenu')as HTMLFormElement).style.width = '0';
if (this.selectedST !== undefined) {
this.selectedST.border = false;
}
this.selectedST = undefined;
}
remainingTasks() {
this.count = 0;
if (this.sectionTask) {
for (const st of this.sectionTask) {
if (st.sectionTaskType === 'task') {
if (!st.status) {
this.count++;
}
}
}
}
}
checkboxValue($event: any, st: TaskSection) {
st.status = $event.currentTarget.checked;
this.remainingTasks();
}
deleteClick(object: TaskSection) {
if (this.sectionTask !== null) {
this.sectionTask = this.sectionTask.filter(tks => tks !== object);
}
this.remainingTasks();
this.closeRightMenu();
}
drop(event: any) {
if (this.sectionTask !== null) {
moveItemInArray(this.sectionTask, event.previousIndex, event.currentIndex);
}
}
}
export class TaskSection {
public Id = 202;
public status = false;
public title = '';
public priority = '';
public dueDate = '';
public notes = '';
public border = false;
public sectionTaskType = '';
}
<div class="row">
<div class="col-lg-8">
<div class="card">
<div class="card-body">
<h4 class="card-title">Ticket</h4> Hi There, i was wondering, do you provide a service to build custom pages. I need some pages
for a ticket system similar to the one you have. Please advise if you provide this service and i will send
through my requirements. Regards.
</div>
</div>
<div class="card">
<div class="card-body">
<h4 class="card-title">Ticket Replies</h4>
<ul class="list-unstyled m-t-40">
<li class="media">
<img class="m-r-15" src="assets/images/users/2.jpg" width="60" alt="Generic placeholder image">
<div class="media-body">
<h5 class="mt-0 mb-1">User Name</h5> Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante
sollicitudin. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum
nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
</div>
</li>
<hr>
<li class="media my-4">
<img class="m-r-15" src="assets/images/users/1.jpg" width="60" alt="Generic placeholder image">
<div class="media-body">
<h5 class="mt-0 mb-1">Agent Name</h5> Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante
sollicitudin. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum
nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
</div>
</li>
<hr>
<li class="media">
<img class="m-r-15" src="assets/images/users/2.jpg" width="60" alt="Generic placeholder image">
<div class="media-body">
<h5 class="mt-0 mb-1">User Name</h5> Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante
sollicitudin. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum
nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
</div>
</li>
<hr>
<li class="media">
<img class="m-r-15" src="assets/images/users/2.jpg" width="60" alt="Generic placeholder image">
<div class="media-body">
<h5 class="mt-0 mb-1">User Name</h5> Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante
sollicitudin. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum
nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
</div>
</li>
<hr>
<li class="media my-4">
<img class="m-r-15" src="assets/images/users/1.jpg" width="60" alt="Generic placeholder image">
<div class="media-body">
<h5 class="mt-0 mb-1">Agent Name</h5> Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante
sollicitudin. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum
nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
</div>
</li>
<hr>
<li class="media">
<img class="m-r-15" src="assets/images/users/2.jpg" width="60" alt="Generic placeholder image">
<div class="media-body">
<h5 class="mt-0 mb-1">User Name</h5> Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante
sollicitudin. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum
nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
</div>
</li>
</ul>
</div>
</div>
<div class="card">
<div class="card-body">
<h4 class="m-b-20">Write a reply</h4>
<form method="post">
<quill-editor [style]="{height: '200px'}"></quill-editor>
<button type="button" class="m-t-20 btn waves-effect waves-light btn-success">Reply</button>
<button type="button" class="m-t-20 btn waves-effect waves-light btn-info">Reply & close</button>
</form>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="card">
<div class="card-body">
<h4 class="card-title">Ticket Info</h4>
</div>
<div class="card-body bg-light">
<div class="row text-center">
<div class="col-6 m-t-10 m-b-10">
<span class="label label-warning">In Progress</span>
</div>
<div class="col-6 m-t-10 m-b-10">
May 2, 2018 9:49
</div>
</div>
</div>
<div class="card-body">
<h5 class="p-t-20">Ticket Creator</h5>
<span>User Name</span>
<h5 class="m-t-30">Support Staff</h5>
<span>Agent Name</span>
<br/>
<button type="button" class="m-t-20 btn waves-effect waves-light btn-success">Update</button>
</div>
</div>
<div class="card">
<div class="card-body text-center">
<h4 class="card-title">User Info</h4>
<div class="profile-pic m-b-20 m-t-20">
<img src="assets/images/users/5.jpg" width="150" class="rounded-circle" alt="user">
<h4 class="m-t-20 m-b-0">Daniel Kristeen</h4>
<a href="mailto:danielkristeen@gmail.com">danielkristeen@gmail.com</a>
</div>
<div class="row text-center m-t-40">
<div class="col-4">
<h3 class="font-bold">4</h3>
<h6>Total</h6>
</div>
<div class="col-4">
<h3 class="font-bold">2</h3>
<h6>Open</h6>
</div>
<div class="col-4">
<h3 class="font-bold">3</h3>
<h6>Closed</h6>
</div>
</div>
</div>
<div class="p-25 border-top m-t-15">
<div class="row text-center">
<div class="col-6 border-right">
<a href="#" class="link d-flex align-items-center justify-content-center font-medium">
<i class="mdi mdi-message font-20 m-r-5"></i>Message</a>
</div>
<div class="col-6">
<a href="#" class="link d-flex align-items-center justify-content-center font-medium">
<i class="mdi mdi-developer-board font-20 m-r-5"></i>Portfolio</a>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-body">
<h4 class="card-title">Ticket Statestics</h4>
<div id="visitor" style="height:290px; width:100%;" class="m-t-20"></div>
</div>
</div>
</div>
</div>
\ No newline at end of file
import { Component, AfterViewInit } from '@angular/core';
import * as c3 from 'c3';
@Component({
templateUrl: './ticketdetails.component.html'
})
export class TicketdetailsComponent implements AfterViewInit {
constructor() {}
ngAfterViewInit() {
const chart = c3.generate({
bindto: '#visitor',
data: {
columns: [['Open', 4], ['Closed', 2], ['In progress', 2], ['Other', 0]],
type: 'donut'
},
donut: {
label: {
show: false
},
title: 'Tickets',
width: 35
},
legend: {
hide: true
},
color: {
pattern: ['#40c4ff', '#2961ff', '#ff821c', '#7e74fb']
}
});
}
}
import { Pipe, PipeTransform, NgZone, ChangeDetectorRef, OnDestroy } from '@angular/core';
@Pipe({
name: 'timeAgo',
pure: false
})
export class TimeAgoPipe implements PipeTransform, OnDestroy {
private timer: number | null = 0;
constructor(private changeDetectorRef: ChangeDetectorRef, private ngZone: NgZone) { }
transform(value: string) {
this.removeTimer();
const d = new Date(value);
const now = new Date();
const seconds = Math.round(Math.abs((now.getTime() - d.getTime()) / 1000));
const timeToUpdate = (Number.isNaN(seconds)) ? 1000 : this.getSecondsUntilUpdate(seconds) * 1000;
this.timer = this.ngZone.runOutsideAngular(() => {
if (typeof window !== 'undefined') {
return window.setTimeout(() => {
this.ngZone.run(() => this.changeDetectorRef.markForCheck());
}, timeToUpdate);
}
return null;
});
const minutes = Math.round(Math.abs(seconds / 60));
const hours = Math.round(Math.abs(minutes / 60));
const days = Math.round(Math.abs(hours / 24));
const months = Math.round(Math.abs(days / 30.416));
const years = Math.round(Math.abs(days / 365));
if (Number.isNaN(seconds)) {
return '';
} else if (seconds <= 45) {
return 'few seconds ago';
} else if (seconds <= 90) {
return 'a minute ago';
} else if (minutes <= 45) {
return minutes + ' minutes ago';
} else if (minutes <= 90) {
return 'an hour ago';
} else if (hours <= 22) {
return hours + ' hours ago';
} else if (hours <= 36) {
return 'a day ago';
} else if (days <= 25) {
return days + ' days ago';
} else if (days <= 45) {
return 'a month ago';
} else if (days <= 345) {
return months + ' months ago';
} else if (days <= 545) {
return 'a year ago';
} else { // (days > 545)
return years + ' years ago';
}
}
ngOnDestroy(): void {
this.removeTimer();
}
private removeTimer() {
if (this.timer) {
window.clearTimeout(this.timer);
this.timer = null;
}
}
private getSecondsUntilUpdate(seconds: number) {
const min = 60;
const hr = min * 60;
const day = hr * 24;
if (seconds < min) { // less than 1 min, update every 2 secs
return 2;
} else if (seconds < hr) { // less than an hour, update every 30 secs
return 30;
} else if (seconds < day) { // less then a day, update every 5 mins
return 300;
} else { // update every hour
return 3600;
}
}
}
<h2 mat-dialog-title>Row Action :: <strong>{{action}}</strong></h2>
<mat-dialog-content class="mat-typography" *ngIf="action != 'Delete'; else elseTemplate">
<form #userForm="ngForm">
<mat-form-field>
<input type="text" matInput required id="creator" name="creator" [(ngModel)]="local_data.creator"
placeholder="created by">
</mat-form-field>
<mat-form-field>
<input type="text" matInput required id="title" name="title" [(ngModel)]="local_data.title"
placeholder="ticket title">
</mat-form-field>
<mat-form-field>
<input type="text" matInput required id="assignee" name="assignee" [(ngModel)]="local_data.assignee"
placeholder="assigned to">
</mat-form-field>
<mat-form-field>
<mat-label>Status</mat-label>
<select matNativeControl required name="status" [(ngModel)]="local_data.status">
<option value="Pending">Pending</option>
<option value="Open">Open</option>
<option value="Closed">Closed</option>
</select>
</mat-form-field>
<mat-form-field>
<input type="text" matInput required id="product" name="product" [(ngModel)]="local_data.product"
placeholder="product name">
</mat-form-field>
<mat-form-field>
<input type="date" matInput required id="date" name="date" [(ngModel)]="local_data.date" placeholder="date">
</mat-form-field>
</form>
</mat-dialog-content>
<ng-template #elseTemplate>
Sure to delete <b>{{local_data.title}}</b>?
</ng-template>
<div mat-dialog-actions align="end">
<button mat-button (click)="doAction()" color="warn">{{action}}</button>
<button mat-button (click)="closeDialog()" mat-flat-button>Cancel</button>
</div>
import { Ticket } from './ticket';
export const ticketsList: Ticket[] = [
{
Id: 1,
ticketTitle: 'Sed ut perspiciatis unde omnis iste',
ticketDescription: 'ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos',
Status: 'Closed',
Label: 'danger',
AgentName: 'Liam',
Date: new Date('02-15-2020')
},
{
Id: 2,
ticketTitle: 'Consequuntur magni dolores eos qui ratione',
ticketDescription: 'ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos',
Status: 'Pending',
Label: 'warning',
AgentName: 'Steve',
Date: new Date('02-15-2020')
},
{
Id: 3,
ticketTitle: 'Exercitationem ullam corporis',
ticketDescription: 'ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos',
Status: 'Open',
Label: 'success',
AgentName: 'Jack',
Date: new Date('02-15-2020')
},
{
Id: 4,
ticketTitle: 'Sed ut perspiciatis unde omnis iste',
ticketDescription: 'ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos',
Status: 'Closed',
Label: 'danger',
AgentName: 'Steve',
Date: new Date('02-15-2020')
},
{
Id: 5,
ticketTitle: 'Exercitationem ullam corporis',
ticketDescription: 'ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos',
Status: 'Closed',
Label: 'danger',
AgentName: 'Liam',
Date: new Date('02-15-2020')
},
{
Id: 6,
ticketTitle: 'Consequuntur magni dolores eos qui ratione',
ticketDescription: 'ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos',
Status: 'Pending',
Label: 'warning',
AgentName: 'Jack',
Date: new Date('02-15-2020')
},
{
Id: 7,
ticketTitle: 'Sed ut perspiciatis unde omnis iste',
ticketDescription: 'ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos',
Status: 'Open',
Label: 'success',
AgentName: 'Steve',
Date: new Date('02-15-2020')
},
{
Id: 8,
ticketTitle: 'Consequuntur magni dolores eos qui ratione',
ticketDescription: 'ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos',
Status: 'Closed',
Label: 'danger',
AgentName: 'John',
Date: new Date('02-15-2020')
}
];
export class Ticket {
Id = 0;
Status: string | null = null;
Label: string | null = null;
ticketTitle: string | null = null;
ticketDescription: string | null = null;
AgentName: string | null = null;
Date: Date | null = null;
}
import { Injectable } from '@angular/core';
import { Ticket } from './ticket';
export const tickets: Ticket[] = [
{
id: 77,
creator: 'Eric Pratt',
title: 'Elegant Theme Side Menu Open show OnClick',
assignee: 'Alice Bohr',
status: 'Pending',
labelbg: 'warning',
product: 'Elegant Admin',
date: '2018-05-01'
},
{
id: 78,
creator: 'Steve',
title: 'Xtreme theme dropdown issue',
assignee: 'Jonathan',
status: 'Open',
labelbg: 'success',
product: 'Xtreme Admin',
date: '2018-05-03'
},
{
id: 79,
creator: 'Mark',
title: 'Header issue in material admin',
assignee: 'Smith J',
status: 'Closed',
labelbg: 'danger',
product: 'Material Admin',
date: '2018-05-02'
},
{
id: 80,
creator: 'John Doe',
title: 'Sidebar issue in Nice admin',
assignee: 'Vincent',
status: 'Pending',
labelbg: 'warning',
product: 'Nice Admin',
date: '2018-05-06'
},
{
id: 81,
creator: 'Jennifer',
title: 'Elegant Theme Side Menu show OnClick',
assignee: 'Chris Martin',
status: 'Open',
labelbg: 'success',
product: 'Elagant Admin',
date: '2018-05-04'
},
{
id: 82,
creator: 'Harper',
title: 'Header issue in admin pro admin',
assignee: 'James F',
status: 'Closed',
labelbg: 'danger',
product: 'Adminpro Admin',
date: '2018-05-03'
},
{
id: 83,
creator: 'Billy John',
title: 'Elegant Theme Side Menu OnClick',
assignee: 'Jonathan',
status: 'Pending',
labelbg: 'warning',
product: 'Elegant Admin',
date: '2018-05-05'
},
{
id: 84,
creator: 'Allen Brook',
title: 'adminpress Theme Side Menu not opening',
assignee: 'Smith J',
status: 'Open',
labelbg: 'success',
product: 'Adminpress Admin',
date: '2018-05-04'
},
{
id: 85,
creator: 'Olivia Hart',
title: 'Charts not proper in xtreme admin',
assignee: 'Markus',
status: 'Closed',
labelbg: 'danger',
product: 'Xtreme Admin',
date: '2018-05-02'
},
{
id: 86,
creator: 'Luis Orys',
title: 'Psd not availabel with package',
assignee: 'Jane',
status: 'Closed',
labelbg: 'danger',
product: 'Material Admin',
date: '2018-05-03'
}
];
@Injectable()
export class ticketListGlobal {
getData(): Ticket[] {
return tickets;
}
}
<div fxLayout="row wrap">
<!-- column -->
<div fxFlex.gt-sm="25" fxFlex.gt-xs="100" fxFlex="100">
<mat-card>
<div class="box p-20 bg-info text-center" (click)="btnCategoryClick('')">
<h1 class="font-light text-white m-0">{{totalCount}}</h1>
<h6 class="text-white m-0">Total Tickets</h6>
</div>
</mat-card>
</div>
<!-- column -->
<!-- column -->
<div fxFlex.gt-sm="25" fxFlex.gt-xs="100" fxFlex="100">
<mat-card>
<div class="box p-20 bg-warning text-center" (click)="btnCategoryClick('Pending')">
<h1 class="font-light text-white m-0">{{pending}}</h1>
<h6 class="text-white m-0">Pending</h6>
</div>
</mat-card>
</div>
<!-- column -->
<!-- column -->
<div fxFlex.gt-sm="25" fxFlex.gt-xs="100" fxFlex="100">
<mat-card>
<div class="box p-20 bg-success text-center" (click)="btnCategoryClick('Open')">
<h1 class="font-light text-white m-0">{{Open}}</h1>
<h6 class="text-white m-0">Open</h6>
</div>
</mat-card>
</div>
<!-- column -->
<!-- column -->
<div fxFlex.gt-sm="25" fxFlex.gt-xs="100" fxFlex="100">
<mat-card>
<div class="box p-20 bg-danger text-center" (click)="btnCategoryClick('Closed')">
<h1 class="font-light text-white m-0">{{Closed}}</h1>
<h6 class="text-white m-0">Closed</h6>
</div>
</mat-card>
</div>
<!-- column -->
</div>
<div fxLayout="row wrap">
<div fxFlex="100">
<mat-card>
<mat-card-content>
<div fxLayout="row wrap" class="align-items-center">
<div fxFlex.gt-md="25" fxFlex.gt-lg="25" fxFlex="100">
<mat-form-field>
<input matInput (keyup)="applyFilter($event)" placeholder="Filter">
</mat-form-field>
</div>
<div fxFlex.gt-md="75" class="text-right">
<button mat-raised-button (click)="openDialog('Add',{})" color="primary">Add Ticket</button>
</div>
</div>
</mat-card-content>
</mat-card>
</div>
</div>
<div fxLayout="row wrap">
<div fxFlex="100">
<mat-card>
<mat-card-content>
<div class="table-responsive">
<table mat-table [dataSource]="dataSourcefilter" class="table ticket-list no-wrap">
<ng-container matColumnDef="creator">
<th mat-header-cell *matHeaderCellDef> Creator </th>
<td mat-cell *matCellDef="let element"> {{element.creator}} </td>
</ng-container>
<ng-container matColumnDef="title">
<th mat-header-cell *matHeaderCellDef> Title </th>
<td mat-cell *matCellDef="let element"> {{element.title}} </td>
</ng-container>
<ng-container matColumnDef="assignee">
<th mat-header-cell *matHeaderCellDef> Assignee </th>
<td mat-cell *matCellDef="let element"> {{element.assignee}} </td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef> Status </th>
<td mat-cell *matCellDef="let element"> {{element.status}} </td>
</ng-container>
<ng-container matColumnDef="product">
<th mat-header-cell *matHeaderCellDef> Product </th>
<td mat-cell *matCellDef="let element"> {{element.product}} </td>
</ng-container>
<ng-container matColumnDef="date">
<th mat-header-cell *matHeaderCellDef> Date </th>
<td mat-cell *matCellDef="let element"> {{element.date}} </td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef> Action </th>
<td mat-cell *matCellDef="let element" class="action-link">
<a (click)="openDialog('Update',element)" class="m-r-10 cursor-pointer">
<i-feather name="edit-2" class="feather-sm"></i-feather>
</a>
<a (click)="openDialog('Delete',element)" class="m-r-10 cursor-pointer">
<i-feather name="trash-2" class="feather-sm text-danger"></i-feather>
</a>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
</mat-card-content>
</mat-card>
</div>
</div>
\ No newline at end of file
import { Component, Inject, Optional, ViewChild } from '@angular/core';
import { MatTable, MatTableDataSource } from '@angular/material/table';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { ticketListGlobal } from './ticketListGlobal.service';
import { Ticket } from './ticket';
@Component({
templateUrl: './ticketlist.component.html'
})
export class TicketlistComponent {
@ViewChild(MatTable, { static: true }) table: MatTable<any> = Object.create(null);
displayedColumns: string[] = ['creator', 'title', 'assignee', 'status', 'product', 'date', 'action'];
searchText = '';
dataSource = new MatTableDataSource(this.ticketService.getData());
dataSourcefilter: null | any = this.dataSource;
totalCount = 0;
Open = 0;
Closed = 0;
pending = 0;
constructor(public dialog: MatDialog, public ticketService: ticketListGlobal) {
this.btnCountStatus();
}
btnCategoryClick(val: string): void {
this.dataSourcefilter = this.dataSource;
if (val !== '') {
this.dataSourcefilter = this.dataSource;
this.dataSourcefilter = this.dataSource.data.filter((o: Ticket) => o.status === val);
} else {
this.dataSourcefilter = this.dataSource;
}
}
btnCountStatus(): void {
this.totalCount = this.dataSource.data.length;
this.Open = this.dataSource.data.filter((o: Ticket) => o.status === 'Open').length;
this.Closed = this.dataSource.data.filter((o: Ticket) => o.status === 'Closed').length;
this.pending = this.dataSource.data.filter((o: Ticket) => o.status === 'Pending').length;
}
openDialog(action: string, obj: any): void {
obj.action = action;
const dialogRef = this.dialog.open(TicketDialogContent, {
data: obj
});
dialogRef.afterClosed().subscribe(result => {
if (result.event === 'Add') {
this.addRowData(result.data);
} else if (result.event === 'Update') {
this.updateRowData(result.data);
} else if (result.event === 'Delete') {
this.deleteRowData(result.data);
}
});
}
addRowData(row: any): void {
const d = new Date();
this.dataSource.data.push({
id: d.getTime(),
creator: row.creator,
title: row.title,
assignee: row.assignee,
status: row.status,
labelbg: row.labelbg,
product: row.product,
date: row.date,
});
this.btnCategoryClick('');
this.btnCountStatus();
this.table.renderRows();
}
deleteRowData(row: any): void {
this.dataSource.data = this.dataSource.data.filter((value, key) =>
value.id !== row.id
);
this.btnCategoryClick('');
this.btnCountStatus();
}
updateRowData(row: any): void {
const ticketSource = this.dataSource.data.find((up: Ticket) => up.id === row.id);
if (ticketSource !== undefined) {
ticketSource.creator = row.creator;
ticketSource.title = row.title;
ticketSource.assignee = row.assignee;
ticketSource.status = row.status;
ticketSource.labelbg = row.labelbg;
ticketSource.product = row.product;
ticketSource.date = row.date;
}
this.btnCategoryClick('');
this.btnCountStatus();
}
applyFilter(event: Event): void {
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
}
}
@Component({
// tslint:disable-next-line: component-selector
selector: 'dialog-content',
templateUrl: 'dialog-content.html',
})
export class TicketDialogContent {
action: string;
// tslint:disable-next-line: variable-name
local_data: any;
constructor(
public dialogRef: MatDialogRef<TicketDialogContent>,
public ticketService: ticketListGlobal,
@Optional() @Inject(MAT_DIALOG_DATA) public data: Ticket) {
this.local_data = { ...data };
this.action = this.local_data.action;
}
doAction(): void {
this.dialogRef.close({ event: this.action, data: this.local_data });
}
closeDialog(): void {
this.dialogRef.close({ event: 'Cancel' });
}
}
.ticket-desc {
width: 500px;
}
.ticket-desc p {
font-weight: 600;
font-size: 16px;
}
.ticket-desc small {
width: 400px;
display: block;
}
.cursor-pointer{
cursor: pointer;
}
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="row">
<!-- Column -->
<div class="col-md-6 col-lg-3 col-xlg-3">
<div class="card card-hover">
<div class="box bg-info cursor-pointer text-center" (click)="filterByStatus('All')">
<h1 class="font-light text-white">{{ticketsList.length}}</h1>
<h6 class="text-white">Total Tickets</h6>
</div>
</div>
</div>
<!-- Column -->
<div class="col-md-6 col-lg-3 col-xlg-3">
<div class="card card-hover">
<div class="box bg-warning cursor-pointer text-center" (click)="filterByStatus('Pending')">
<h1 class="font-light text-white">{{pending}}</h1>
<h6 class="text-white">Pending</h6>
</div>
</div>
</div>
<!-- Column -->
<div class="col-md-6 col-lg-3 col-xlg-3">
<div class="card card-hover">
<div class="box bg-success cursor-pointer text-center" (click)="filterByStatus('Open')">
<h1 class="font-light text-white">{{open}}</h1>
<h6 class="text-white">Open</h6>
</div>
</div>
</div>
<!-- Column -->
<div class="col-md-6 col-lg-3 col-xlg-3">
<div class="card card-hover">
<div class="box bg-danger cursor-pointer text-center" (click)="filterByStatus('Closed')">
<h1 class="font-light text-white">{{closed}}</h1>
<h6 class="text-white">Closed</h6>
</div>
</div>
</div>
<!-- Column -->
</div>
<div class="row mb-4">
<div class="col-md-6 col-lg-3 col-xl-2">
<input type="text" class="form-control form-control-lg" type="text" name="search" [(ngModel)]='searchTerm'
autocomplete="off" placeholder="Search here...">
</div>
<div class="col-md-6 col-lg-9 col-xl-10 text-md-right mt-4 mt-md-0">
<button class="btn btn-lg btn-cyan text-white" (click)="openModal(editTicketModal, null)">
<i class="fa fa-plus-square mr-2"></i>Add Ticket</button>
</div>
</div>
</div>
<div class="table-responsive">
<table class="table mb-0 no-wrap v-middle">
<tbody>
<tr *ngFor='let ticket of filterTickets|slice: (page-1) * pageSize : (page-1) * pageSize + pageSize'>
<td width="50" class="text-center">{{ticket.Id}}</td>
<td class="text-center" width="150">
<span class="label label-{{ ticket.Label }}">{{ ticket.Status }}</span>
</td>
<td class="ticket-desc">
<p class="mb-1">
<ngb-highlight [result]="ticket.ticketTitle" [term]="searchTerm"></ngb-highlight>
</p>
<small class="text-truncate">
<ngb-highlight [result]="ticket.ticketDescription" [term]="searchTerm"></ngb-highlight>
</small>
</td>
<td><small>Assign to:</small><br /> <strong>{{ticket.AgentName}}</strong></td>
<td>{{ticket.Date | timeAgo }}</td>
<td>
<a href="javascript: void(0);" (click)="openModal(editTicketModal, ticket)" class="link mr-2"
placement="top" ngbTooltip="Edit">
<!-- <i class="mdi mdi-pencil"></i> -->
<i-feather name="edit" class="feather-sm"></i-feather>
</a>
<a href="javascript: void(0);" class="link" (click)="deleteTicket(ticket.Id)" placement="top"
ngbTooltip="Delete">
<i-feather name="trash-2" class="feather-sm text-danger"></i-feather>
<!-- <i class="mdi mdi-delete"></i> -->
</a>
</td>
</tr>
</tbody>
</table>
</div>
<div class="d-flex justify-content-center mt-5">
<ngb-pagination [(page)]="page" [pageSize]="pageSize" [collectionSize]="totalLengthOfCollection">
</ngb-pagination>
</div>
</div>
</div>
</div>
<ng-template #editTicketModal let-modal>
<div class="modal-header">
<h5 class="modal-title" id="editUserLabel">Edit Ticket</h5>
<button type="button" class="close" (click)="closeBtnClick()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form [formGroup]="editTicket" (ngSubmit)="onSubmit()">
<div class="form-group row">
<label for="title" class="col-sm-4 col-form-label">Title</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="ticketTitle" id="title"
(input)=logValidationErrors(editTicket)>
<span class="help-block" *ngIf="formsErrors.ticketTitle">
{{formsErrors.ticketTitle}}
</span>
</div>
</div>
<div class="form-group row">
<label for="description" class="col-sm-4 col-form-label">Ticket Description</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="ticketDescription" id="description"
(input)=logValidationErrors(editTicket)>
<span class="help-block" *ngIf="formsErrors.ticketDescription">
{{formsErrors.ticketDescription}}
</span>
</div>
</div>
<div class="form-group row">
<label for="date" class="col-sm-4 col-form-label">Date</label>
<div class="col-sm-8">
<input type="date" class="form-control" formControlName="Date" id="date" [(ngModel)]="ticketDate"
(input)=logValidationErrors(editTicket)>
<span class="help-block" *ngIf="formsErrors.Date">
{{formsErrors.Date}}
</span>
</div>
</div>
<div class="form-group row">
<label for="status" class="col-sm-4 col-form-label">Status</label>
<div class="col-sm-8">
<select class="form-control" formControlName="Status" (blur)=logValidationErrors(editTicket)>
<option selected>Closed</option>
<option>Open</option>
<option>In Process</option>
</select>
<span class="help-block" *ngIf="formsErrors.Status">
{{formsErrors.Status}}
</span>
</div>
</div>
<div class="form-group row">
<label for="agent" class="col-sm-4 col-form-label">Assign To</label>
<div class="col-sm-8">
<select class="form-control" formControlName="AgentName" (blur)=logValidationErrors(editTicket)>
<option>Steve</option>
<option>Jack</option>
<option>John</option>
<option>Liam</option>
</select>
<span class="help-block" *ngIf="formsErrors.AgentName">
{{formsErrors.AgentName}}
</span>
</div>
</div>
<div class="form-group row mt-4">
<span class="col-sm-4 col-form-label"></span>
<div class="col-sm-8">
<button type="button" class="btn btn-secondary mr-2" (click)="closeBtnClick()">Close</button>
<button type="submit" class="btn btn-primary" [disabled]="editTicket.invalid">Save</button>
</div>
</div>
<div class="text-center"><small>New ticket will be shown on second page.</small></div>
</form>
</div>
</ng-template>
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
import { TicketService } from './tickets.service';
import { Ticket } from './ticket';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { DatePipe } from '@angular/common';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-tickets',
templateUrl: './tickets.component.html',
styleUrls: ['./tickets.component.css']
})
export class TicketsComponent implements OnInit {
closed = 0;
open = 0;
pending = 0;
ticketsList: Ticket[] = this.ticketService.getTickets();
filterTickets: Ticket[];
ticketDate: string | null = null;
ticketDetail: Ticket | null = null;
editTicket: FormGroup = Object.create(null);
page = 1;
pageSize = 5;
createButtonClick = true;
totalLengthOfCollection = 0;
_searchTerm = '';
constructor(private ticketService: TicketService, private fb: FormBuilder, private modalService: NgbModal, private datePipe: DatePipe) {
this.filterTickets = this.ticketsList;
this.totalLengthOfCollection = this.filterTickets.length;
}
ngOnInit() {
this.filterTickets = this.ticketsList;
if (this.ticketService) {
this.open = this.ticketService.getTickets().filter(x => x.Status === 'Open').length;
this.pending = this.ticketService.getTickets().filter(x => x.Status === 'Pending').length;
this.closed = this.ticketService.getTickets().filter(x => x.Status === 'Closed').length;
}
this.editTicket = this.fb.group({
Id: [''],
Status: ['', Validators.required],
ticketTitle: ['', Validators.required],
ticketDescription: ['', Validators.required],
AgentName: ['', Validators.required],
Date: [''],
});
}
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this._searchTerm = val;
this.filterTickets = this.filter(val);
this.totalLengthOfCollection = this.filterTickets.length;
}
ValidationMessage = {
Status: { required: 'Status is required.' },
ticketTitle: { required: 'Title is required.' },
ticketDescription: { required: 'Description is required.' },
AgentName: { required: 'Assign To is required.' },
Date: { required: 'Date is required.' },
};
formsErrors = {
};
filter(v: string) {
return this.ticketService.getTickets().filter(x => x.AgentName?.toLowerCase().indexOf(v.toLowerCase()) !== -1 ||
x.ticketTitle?.toLowerCase().indexOf(v.toLowerCase()) !== -1 || x.Status?.toLowerCase().indexOf(v.toLowerCase()) !== -1);
}
logValidationErrors(group: FormGroup) {
}
openModal(targetModal: NgbModal, ticket: Ticket | null) {
this.modalService.open(targetModal, {
centered: true,
backdrop: 'static'
});
if (ticket == null) {
this.createButtonClick = false;
}
if (ticket != null) {
// this.ticketDate = this.datePipe.transform(new Date(ticket.Date), 'yyyy-MM-dd');
this.ticketDetail = ticket;
this.editTicket.patchValue({
Id: ticket.Id,
Status: ticket.Status,
ticketTitle: ticket.ticketTitle,
ticketDescription: ticket.ticketDescription,
AgentName: ticket.AgentName,
Date: ticket.Date
});
}
}
onSubmit() {
if (this.ticketDetail != null) {
const index = this.ticketService.getTickets().indexOf(this.ticketDetail);
this.ticketDetail.Status = this.editTicket?.get('Status')?.value;
this.ticketDetail.ticketTitle = this.editTicket?.get('ticketTitle')?.value;
this.ticketDetail.ticketDescription = this.editTicket?.get('ticketDescription')?.value;
this.ticketDetail.AgentName = this.editTicket?.get('AgentName')?.value;
this.ticketDetail.Date = this.editTicket?.get('Date')?.value;
switch (this.ticketDetail.Status) {
case 'Pending':
this.ticketDetail.Label = 'warning';
break;
case 'Open':
this.ticketDetail.Label = 'success';
break;
case 'Closed':
this.ticketDetail.Label = 'danger';
break;
default:
}
this.ticketService.getTickets()[index] = this.ticketDetail;
} else {
this.ticketDetail = new Ticket();
this.ticketDetail.Id = Math.max.apply(Math, this.ticketService.getTickets().map(function (o) { return o.Id; })) + 1;
this.ticketDetail.Status = this.editTicket?.get('Status')?.value;
this.ticketDetail.ticketTitle = this.editTicket?.get('ticketTitle')?.value;
this.ticketDetail.ticketDescription = this.editTicket?.get('ticketDescription')?.value;
this.ticketDetail.AgentName = this.editTicket?.get('AgentName')?.value;
this.ticketDetail.Date = new Date();
switch (this.ticketDetail.Status) {
case 'Pending':
this.ticketDetail.Label = 'warning';
break;
case 'Open':
this.ticketDetail.Label = 'success';
break;
case 'Closed':
this.ticketDetail.Label = 'danger';
break;
default:
}
this.ticketService.getTickets().push(this.ticketDetail);
}
this.modalService.dismissAll();
this.ticketDate = '';
this.ticketDetail = null;
this.ngOnInit();
}
closeBtnClick() {
this.modalService.dismissAll();
this.ngOnInit();
}
deleteTicket(id: number): void {
this.filterTickets = this.filterTickets.filter(ticket => ticket.Id !== id);
this.ticketsList = this.ticketsList.filter(ticket => ticket.Id !== id);
if (this.ticketService) {
this.open = this.filterTickets.filter(x => x.Status === 'Open').length;
this.pending = this.filterTickets.filter(x => x.Status === 'Pending').length;
this.closed = this.filterTickets.filter(x => x.Status === 'Closed').length;
}
this.totalLengthOfCollection = this.filterTickets.length;
}
filterByStatus(type: string) {
this.filterTickets = this.ticketService.getTickets();
this.searchTerm = '';
if (type === 'All') {
this.filterTickets = this.ticketsList;
this.totalLengthOfCollection = this.ticketsList.length;
return this.filterTickets;
}
else {
this.filterTickets = this.filterTickets.filter(ticket => ticket.Status === type);
this.totalLengthOfCollection = this.filterTickets.length;
return this.filterTickets;
}
}
}
import { Injectable } from '@angular/core';
import { Ticket} from './ticket';
import { ticketsList } from './ticket-data';
@Injectable()
export class TicketService {
public tickets: Ticket[] = ticketsList;
public getTickets() {
return this.tickets;
}
}
import { ToDo } from './todo';
export const todos: ToDo[] = [
{
id: 1,
message: 'I have to go office.',
completionStatus: true,
edit: false,
date: new Date('02-06-2020')
},
{
id: 2,
message: 'let us work hard this time ! ',
completionStatus: false,
edit: false,
date: new Date('02-08-2020')
},
{
id: 3,
message: 'We will win if we give our best.',
completionStatus: true,
edit: false,
date: new Date('02-10-2020')
},
{
id: 4,
message: 'We will leave soon.',
completionStatus: false,
edit: false,
date: new Date('02-12-2020')
},
{
id: 5,
message: 'I am doing my best.',
completionStatus: false,
edit: false,
date: new Date('02-15-2020')
}
];
import { Injectable } from '@angular/core';
import { ToDo } from './todo';
import { todos } from './todo-data';
@Injectable()
export class TodoService {
public todos: ToDo[] = todos;
public getTodos() {
return this.todos;
}
}
export class ToDo {
id = 0;
public message = '';
public completionStatus = false;
public edit = false;
public date: Date | null = null;
}
<!-- Mobile toggle button -->
<a [ngClass]="(showSidebar)?'ti-close':'ti-menu'" class="btn btn-success show-left-part d-block d-md-none"
href="javascript:void(0)" (click)="mobileSidebar()"></a>
<div class="main-part">
<div class="left-part bg-white fixed-left-part" [ngClass]="{'show-panel': showSidebar}">
<div class="position-relative">
<div class="px-3 py-3 d-flex align-items-center border-bottom">
<p class="mb-0 py-1 text-center font-18 font-bold">{{ remainingList() }} tasks left</p>
</div>
<ul class="tasklist list-style-none">
<li class="task-item d-flex all border-bottom" [class.active]="selectedCategory === 'all'"
(click)="selectionlblClick('all')">
All <span class="badge badge-primary ml-auto pt-1">{{todos.length}}</span></li>
<li class="task-item d-flex incomplete border-bottom" [class.active]="selectedCategory === 'uncomplete'"
(click)="selectionlblClick('uncomplete')">
Incompleted <span class="badge badge-danger ml-auto pt-1">{{ remainingList() }}</span></li>
<li class="task-item d-flex complete border-bottom" [class.active]="selectedCategory === 'complete'"
(click)="selectionlblClick('complete')">
Completed <span class="badge badge-success ml-auto pt-1">{{todos.length - remainingList()}}</span>
</li>
</ul>
</div>
</div>
<div class="right-part bg-white">
<div class="card">
<div class="px-3 py-3 d-flex align-items-center border-bottom bg-light">
<div class="custom-control custom-checkbox flex-shrink-0">
<input type="checkbox" class="custom-control-input" id="all" (change)="allTodos()">
<label class="custom-control-label" for="all">Mark All</label>
</div>
<form [formGroup]="inputFg" class="d-flex align-items-center ml-auto">
<input type="text" #inputData [(ngModel)]="searchText" class="todo-input form-control mb-0 mx-2"
placeholder="Type here to add new todo..." formControlName='mess'
(keyup.enter)="addTodo(inputData.value)" />
<button type="button" [disabled]="!searchText" id="btnAddTodo" class="btn btn-primary flex-shrink-0"
(click)="addTodo(inputData.value)">Add Todo</button>
</form>
</div>
<div>
<div *ngFor="let todo of copyTodos;let i=index" class="todo-item py-3 pl-3 border-bottom">
<div class="todo-item-left d-flex w-100">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id={{todo.id}}
[(ngModel)]="todo.completionStatus">
<label class="custom-control-label" for={{todo.id}}></label>
</div>
<div class="todo-item-label w-100">
<span class="d-flex align-items-start" *ngIf="!todo.edit" (click)="editTodo(todo.id)">
<div>
<p class="mb-1">{{todo.message}}</p>
<p class="mb-0 font-12">{{todo.date | date}}</p>
</div>
<div class="ml-auto px-3 mr-2">
<a href="javascript: void(0);" (click)='editTodo(todo.id,"edit")' class="link mr-3"
placement="top" ngbTooltip="Edit">
<i-feather name="edit-2" class="feather-sm"></i-feather>
</a>
<a href="javascript: void(0);" class="link" (click)='deleteTodo(i)' placement="top"
ngbTooltip="Delete">
<i-feather name="trash-2" class="feather-sm"></i-feather>
</a>
</div>
</span>
<span class="d-flex align-items-start" *ngIf="todo.edit">
<input type="text" [(ngModel)]="todo.message" class="form-control" />
<div class="ml-auto d-flex px-3 mr-2">
<a href="javascript: void(0);" (click)='editTodo(todo.id,"save")' class="link mr-3"
placement="top" ngbTooltip="Save">
<i-feather name="save" class="feather-sm"></i-feather>
</a>
<a href="javascript: void(0);" class="link" (click)='deleteTodo(i)' placement="top"
ngbTooltip="Delete">
<i-feather name="trash-2" class="feather-sm"></i-feather>
</a>
</div>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
.tasklist {
.task-item {
padding: 16.5px;
cursor: pointer;
&.active {
background-color: #e9ecef;
}
/* &.all {
border-left: 5px solid #7460ee;
}
&.incomplete {
border-left: 5px solid #e60a31;
}
&.complete {
border-left: 5px solid #2b9683;
} */
}
}
button:focus {
outline: none;
}
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
import { ToDo } from './todo';
import { TodoService } from './todo.service';
import { tsvFormat } from 'd3';
@Component({
selector: 'app-todos',
templateUrl: './todos.component.html',
styleUrls: ['./todos.component.scss']
})
export class TodosComponent implements OnInit {
public showSidebar = false;
inputFg: FormGroup = Object.create(null);
todoId = 6;
copyTodos: ToDo[];
/* search: 'all'; */
selectedCategory = 'all';
searchText: string | null = null;
editSave = 'Edit';
todos: ToDo[] = this.todoService.getTodos();
constructor(public fb: FormBuilder, public todoService: TodoService) {
this.copyTodos = this.todos;
}
mobileSidebar() {
this.showSidebar = !this.showSidebar;
}
ngOnInit() {
this.inputFg = this.fb.group({
mess: []
});
}
addTodo(value: string) {
if (this.inputFg?.get('mess')?.value.trim().length === 0) {
return;
}
this.todos.push(
{
id: this.todoId,
message: this.inputFg?.get('mess')?.value,
completionStatus: false,
edit: false,
date: new Date()
}
);
this.copyTodos = this.todos;
this.todoId++;
this.inputFg.patchValue({
mess: '',
});
}
allTodos(): void {
this.todos.forEach(todo => todo.completionStatus = (
<HTMLInputElement>event!.target).checked);
}
selectionlblClick(val: string) {
if (val === 'all') {
this.copyTodos = this.todos;
this.selectedCategory = 'all';
} else if (val === 'uncomplete') {
this.copyTodos = this.todos.filter(todo => !todo.completionStatus);
this.selectedCategory = 'uncomplete';
} else if (val === 'complete') {
this.copyTodos = this.todos.filter(x => x.completionStatus);
this.selectedCategory = 'complete';
}
}
editTodo(i: number, str: string) {
if (this.copyTodos) {
if (str === 'edit') {
// tslint:disable-next-line: no-non-null-assertion
this.copyTodos.find(x => x.id === i)!.edit = true;
} else {
// tslint:disable-next-line: no-non-null-assertion
this.copyTodos.find(x => x.id === i)!.edit = false;
}
}
}
deleteTodo(id: number) {
console.log(id);
this.todos.splice(id, 1);
}
remainingList(): number {
return this.todos.filter(todo => !todo.completionStatus).length;
}
}
import { User } from './user';
export const users: User[] = [
{
id: 1,
Name: 'Johnathan Deo',
Position: 'Seo Expert',
Email: 'r@gmail.com',
Mobile: 9786838,
DateOfJoining: new Date('01-2-2020'),
Salary: 12000,
Projects: 10,
imagePath: 'assets/images/users/2.jpg'
},
{
id: 2,
Name: 'Mark Zukerburg',
Position: 'Web Developer',
Email: 'mark@gmail.com',
Mobile: 8786838,
DateOfJoining: new Date('04-2-2020'),
Salary: 12000,
Projects: 10,
imagePath: 'assets/images/users/3.jpg'
},
{
id: 3,
Name: 'Sam smith',
Position: 'Web Designer',
Email: 'sam@gmail.com',
Mobile: 7788838,
DateOfJoining: new Date('02-2-2020'),
Salary: 12000,
Projects: 10,
imagePath: 'assets/images/users/4.jpg'
},
{
id: 4,
Name: 'John Deo',
Position: 'Tester',
Email: 'john@gmail.com',
Mobile: 8786838,
DateOfJoining: new Date('03-2-2020'),
Salary: 12000,
Projects: 11,
imagePath: 'assets/images/users/5.jpg'
},
{
id: 5,
Name: 'Genilia',
Position: 'Actor',
Email: 'genilia@gmail.com',
Mobile: 8786838,
DateOfJoining: new Date('05-2-2020'),
Salary: 12000,
Projects: 19,
imagePath: 'assets/images/users/6.jpg'
},
{
id: 6,
Name: 'Jack Sparrow',
Position: 'Content Writer',
Email: 'jac@gmail.com',
Mobile: 8786838,
DateOfJoining: new Date('05-21-2020'),
Salary: 12000,
Projects: 5,
imagePath: 'assets/images/users/7.jpg'
},
{
id: 7,
Name: 'Tom Cruise',
Position: 'Actor',
Email: 'tom@gmail.com',
Mobile: 8786838,
DateOfJoining: new Date('02-15-2019'),
Salary: 12000,
Projects: 9,
imagePath: 'assets/images/users/3.jpg'
},
{
id: 8,
Name: 'Hary Porter',
Position: 'Actor',
Email: 'hary@gmail.com',
Mobile: 8786838,
DateOfJoining: new Date('07-3-2019'),
Salary: 12000,
Projects: 7,
imagePath: 'assets/images/users/6.jpg'
},
{
id: 9,
Name: 'Kristen Ronaldo',
Position: 'Player',
Email: 'kristen@gmail.com',
Mobile: 8786838,
DateOfJoining: new Date('01-15-2019'),
Salary: 12000,
Projects: 1,
imagePath: 'assets/images/users/5.jpg'
}
];
import { TestBed } from '@angular/core/testing';
import { UserRxjsServiceService } from './user-rxjs-service.service';
describe('UserRxjsServiceService', () => {
let service: UserRxjsServiceService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(UserRxjsServiceService);
});
// it('should be created', () => {
// expect(service).toBeTruthy();
// });
});
import { Injectable } from '@angular/core';
import { from, Observable } from 'rxjs';
import { User } from './user';
import { users } from './user-data';
@Injectable({
providedIn: 'root'
})
export class UserRxjsServiceService {
constructor() { }
private users: User[] = users;
// getUsers(): Observable<User> {
// You can also fetch data from Api using HttpClient.
// return this.http.get(url..)
// }
getUsers(): Observable<User> {
return from(this.users);
}
deleteUser(id: number): void {
this.users = this.users.filter(user => user.id !== id);
}
addUser(user: User): void {
this.users?.push(user);
}
updateUser(index: number, user: User): void {
this.users[index] = user;
}
}
<div class="row">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">Employee Table</h4>
<h5 class="card-subtitle">Here is the employee list you can add, edit or delet the emplyee</h5>
<div class="d-flex mb-3 mt-3">
<input type="text" class="form-control w-25" placeholder="Search by Name or Email" [(ngModel)]='searchTerm'>
<button class="btn btn-primary ml-auto" (click)="openModal(editUserModal, null)">Add User</button>
</div>
<div class="table-responsive table-bordered">
<table class="table table-striped mb-0 no-wrap v-middle">
<thead>
<tr>
<th class="text-center" scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Mobile</th>
<th scope="col">Date of Joining</th>
<th scope="col">Salary</th>
<th scope="col">Projects</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of filterArray | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize">
<td class="text-center">
{{user.id}}
</td>
<td>
<div class="d-flex align-items-center">
<img class="rounded-circle" [src]='user.imagePath' height=" 50px" width="50px">
<div class="ml-3">
<p class="font-medium mb-0">{{ user.Name }}</p>
<small>{{user.Position}}</small>
</div>
</div>
</td>
<td>{{ user.Email }}</td>
<td>{{ user.Mobile }}</td>
<td>{{ user.DateOfJoining |date :'fullDate' }}</td>
<td>{{ user.Salary }}</td>
<td>{{ user.Projects }}</td>
<td>
<a href="javascript: void(0);" (click)="openModal(editUserModal, user)" class="link mr-2"
placement="top" ngbTooltip="Edit">
<!-- <i class="far fa-edit"></i> -->
<i-feather name="edit-2" class="feather-sm"></i-feather>
</a>
<a href="javascript: void(0);" class="link" (click)="deleteUser(user.id)" placement="top"
ngbTooltip="Delete">
<i-feather name="trash-2" class="feather-sm"></i-feather>
</a>
</td>
</tr>
</tbody>
</table>
</div>
<div class="d-flex justify-content-center mt-5">
<ngb-pagination [(page)]="page" [pageSize]="pageSize" [collectionSize]="filterArray.length"></ngb-pagination>
</div>
</div>
</div>
</div>
<ng-template #editUserModal let-modal>
<div class="modal-header">
<h5 class="modal-title" id="editUserLabel">Edit User</h5>
<button type="button" class="close" (click)="closeBtnClick()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form [formGroup]="editUser" (ngSubmit)="onSubmit()">
<div class="form-group row">
<label for="name" class="col-sm-4 col-form-label">Name</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Name" id="name" (blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Name">
{{formsErrors.Name}}
</span>
</div>
</div>
<div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">Position</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Position" id="position"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Position">
{{formsErrors.Position}}
</span>
</div>
</div>
<div class="form-group row">
<label for="email" class="col-sm-4 col-form-label">Email</label>
<div class="col-sm-8">
<input type="email" class="form-control" formControlName="Email" id="email"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Email">
{{formsErrors.Email}}
</span>
</div>
</div>
<div class="form-group row">
<label for="mobile" class="col-sm-4 col-form-label">Mobile</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Mobile" id="mobile"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Mobile">
{{formsErrors.Mobile}}
</span>
</div>
</div>
<div class="form-group row">
<label for="doj" class="col-sm-4 col-form-label">Date Of Joining</label>
<div class="col-sm-8">
<input type="date" class="form-control" formControlName="DateOfJoining" [(ngModel)]="joiningDate" id="doj"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.DateOfJoining">
{{formsErrors.DateOfJoining}}
</span>
</div>
</div>
<div class="form-group row">
<label for="salary" class="col-sm-4 col-form-label">Salary</label>
<div class="col-sm-8">
<input type="number" class="form-control" formControlName="Salary" id="salary"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Salary">
{{formsErrors.Salary}}
</span>
</div>
</div>
<div class="form-group row">
<label for="projects" class="col-sm-4 col-form-label">Projects</label>
<div class="col-sm-8">
<input type="number" class="form-control" formControlName="Projects" id="projects"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Projects">
{{formsErrors.Projects}}
</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="closeBtnClick()">Close</button>
<button type="submit" class="btn btn-primary" [disabled]="editUser.invalid">Save</button>
</div>
</form>
</div>
</ng-template>
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { UserRxjsComponent } from './user-rxjs.component';
describe('UserRxjsComponent', () => {
let component: UserRxjsComponent;
let fixture: ComponentFixture<UserRxjsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ UserRxjsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(UserRxjsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
});
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DatePipe } from '@angular/common';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { User } from './user';
import { UserRxjsServiceService } from './user-rxjs-service.service'
@Component({
selector: 'app-user-rxjs',
templateUrl: './user-rxjs.component.html',
styleUrls: ['./user-rxjs.component.css']
})
export class UserRxjsComponent implements OnInit {
userList: User[] = [];
filterArray: User[] = [];
userDetail: User | null = null;
config: any;
editUser: FormGroup | null = null;
joiningDate: string | null = null;
page = 1;
pageSize = 7;
_searchTerm = '';
constructor(private userService: UserRxjsServiceService, private fb: FormBuilder, private modalService: NgbModal, private datePipe: DatePipe) {
this.userService.getUsers().subscribe((data) => {
this.userList.push(data);
});
this.filterArray = this.userList;
}
ngOnInit() {
this.editUser = this.fb.group({
id: [''],
Name: ['', Validators.required],
Position: ['', Validators.required],
Email: ['', Validators.required],
Mobile: ['', Validators.required],
DateOfJoining: ['', Validators.required],
Salary: ['', Validators.required],
Projects: ['', Validators.required],
});
}
//search...
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this._searchTerm = val;
this.filterArray = this.filter(val);
}
filter(v: string) {
return this.userList.filter(x => x.Name.toLowerCase().
indexOf(v.toLowerCase()) !== -1 || x.Email.toLowerCase().indexOf(v.toLowerCase()) !== -1);
}
// validation...
ValidationMessage =
[
{
Name: { required: 'Name is required.' }
}, {
Position: { required: 'Position is required.' }
}, {
Email: { required: 'Email is required.' }
},
{
Mobile: { required: 'Mobile is required.' }
},
{
DateOfJoining: { required: 'DOJ is required.' }
},
{
Salary: { required: 'Salary is required.' }
},
{
Projects: { required: 'Project is required.' }
},
];
formsErrors = [];
logValidationErrors(group: FormGroup) {
}
// delete user...
deleteUser(id: number): void {
if (this.filterArray) {
this.filterArray = this.filterArray.filter(user => user.id !== id);
this.userService.deleteUser(id);
}
}
// open model...
openModal(targetModal: NgbModal, user: User | null) {
this.modalService.open(targetModal, {
centered: true,
backdrop: 'static'
});
if (user != null) {
if (user.DateOfJoining) {
this.joiningDate = this.datePipe.
transform(new Date(user.DateOfJoining), 'yyyy-MM-dd');
}
this.userDetail = user;
this.editUser?.patchValue({
Name: user.Name,
Position: user.Position,
Email: user.Email,
Mobile: user.Mobile,
DateOfJoining: user.DateOfJoining,
Salary: user.Salary,
Projects: user.Projects,
});
}
}
// on submit data rom model...
onSubmit() {
if (this.filterArray != null && this.userDetail) {
const index = this.filterArray.indexOf(this.userDetail);
if (this.editUser != null) {
this.userDetail.Name = this.editUser.get('Name')?.value;
this.userDetail.Position = this.editUser.get('Position')?.value;
this.userDetail.Email = this.editUser.get('Email')?.value;
this.userDetail.Mobile = this.editUser.get('Mobile')?.value;
this.userDetail.DateOfJoining = this.editUser.get('DateOfJoining')?.value;
this.userDetail.Salary = this.editUser.get('Salary')?.value;
this.userDetail.Projects = this.editUser.get('Projects')?.value;
}
this.filterArray[index] = this.userDetail;
this.userService.updateUser(index, this.userDetail);
} else {
this.userDetail = new User();
if (this.filterArray)
this.userDetail.id = Math.max.apply(Math, this.filterArray.map(function (o) { return o.id; })) + 1;
this.userDetail.Name = this.editUser?.get('Name')?.value;
this.userDetail.Position = this.editUser?.get('Position')?.value;
this.userDetail.Email = this.editUser?.get('Email')?.value;
this.userDetail.Mobile = this.editUser?.get('Mobile')?.value;
this.userDetail.DateOfJoining = new Date();
this.userDetail.Salary = this.editUser?.get('Salary')?.value;
this.userDetail.Projects = this.editUser?.get('Projects')?.value;
this.userDetail.imagePath = 'assets/images/users/7.jpg';
this.userService.addUser(this.userDetail);
this.filterArray.splice(0, 0, this.userDetail);
}
this.modalService.dismissAll();
this.userDetail = null;
this.joiningDate = '';
this.ngOnInit();
}
// close model...
closeBtnClick() {
this.modalService.dismissAll();
this.ngOnInit();
}
}
export class User {
public id = 0;
public Name = '';
public Position = '';
public Email = '';
public Mobile = 0;
public DateOfJoining: Date | null = null;
public Salary = 0;
public Projects = 0;
public imagePath = '';
}
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { EditAddUserComponent } from './edit-add-user.component';
describe('EditAddUserComponent', () => {
let component: EditAddUserComponent;
let fixture: ComponentFixture<EditAddUserComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ EditAddUserComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EditAddUserComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
});
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-edit-add-user',
templateUrl: './edit-add-user.component.html',
styleUrls: ['./edit-add-user.component.css']
})
export class EditAddUserComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
<div class="row">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">Employee Table</h4>
<h5 class="card-subtitle">Here is the employee list you can add, edit or delet the emplyee</h5>
<div class="d-flex mb-3 mt-3">
<input type="text" class="form-control w-25" placeholder="Search by Name or Email" [(ngModel)]='searchTerm'>
<button class="btn btn-primary ml-auto" (click)="openModal(editUserModal, null)">Add User</button>
</div>
<div class="table-responsive table-bordered">
<table class="table table-striped mb-0 no-wrap v-middle">
<thead>
<tr>
<th class="text-center" scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Mobile</th>
<th scope="col">Date of Joining</th>
<th scope="col">Salary</th>
<th scope="col">Projects</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of filterArray | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize">
<td class="text-center">
{{user.id}}
</td>
<td>
<div class="d-flex align-items-center">
<img class="rounded-circle" [src]='user.imagePath' height=" 50px" width="50px">
<div class="ml-3">
<p class="font-medium mb-0">{{ user.Name }}</p>
<small>{{user.Position}}</small>
</div>
</div>
</td>
<td>{{ user.Email }}</td>
<td>{{ user.Mobile }}</td>
<td>{{ user.DateOfJoining |date :'fullDate' }}</td>
<td>{{ user.Salary }}</td>
<td>{{ user.Projects }}</td>
<td>
<a href="javascript: void(0);" (click)="openModal(editUserModal, user)" class="link mr-2"
placement="top" ngbTooltip="Edit">
<i-feather name="edit-2" class="feather-sm"></i-feather>
</a>
<a href="javascript: void(0);" class="link" (click)="deleteUser(user.id)" placement="top"
ngbTooltip="Delete">
<i-feather name="trash-2" class="feather-sm"></i-feather>
</a>
</td>
</tr>
</tbody>
</table>
</div>
<div class="d-flex justify-content-center mt-5">
<ngb-pagination [(page)]="page" [pageSize]="pageSize" [collectionSize]="userList.length"></ngb-pagination>
</div>
</div>
</div>
</div>
<ng-template #editUserModal let-modal>
<div class="modal-header">
<h5 class="modal-title" id="editUserLabel">Edit User</h5>
<button type="button" class="close" (click)="closeBtnClick()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form [formGroup]="editUser" (ngSubmit)="onSubmit()">
<div class="form-group row">
<label for="name" class="col-sm-4 col-form-label">Name</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Name" id="name" (blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Name">
{{formsErrors.Name}}
</span>
</div>
</div>
<div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">Position</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Position" id="position"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Position">
{{formsErrors.Position}}
</span>
</div>
</div>
<div class="form-group row">
<label for="email" class="col-sm-4 col-form-label">Email</label>
<div class="col-sm-8">
<input type="email" class="form-control" formControlName="Email" id="email"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Email">
{{formsErrors.Email}}
</span>
</div>
</div>
<div class="form-group row">
<label for="mobile" class="col-sm-4 col-form-label">Mobile</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Mobile" id="mobile"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Mobile">
{{formsErrors.Mobile}}
</span>
</div>
</div>
<div class="form-group row">
<label for="doj" class="col-sm-4 col-form-label">Date Of Joining</label>
<div class="col-sm-8">
<input type="date" class="form-control" formControlName="DateOfJoining" [(ngModel)]="joiningDate" id="doj"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.DateOfJoining">
{{formsErrors.DateOfJoining}}
</span>
</div>
</div>
<div class="form-group row">
<label for="salary" class="col-sm-4 col-form-label">Salary</label>
<div class="col-sm-8">
<input type="number" class="form-control" formControlName="Salary" id="salary"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Salary">
{{formsErrors.Salary}}
</span>
</div>
</div>
<div class="form-group row">
<label for="projects" class="col-sm-4 col-form-label">Projects</label>
<div class="col-sm-8">
<input type="number" class="form-control" formControlName="Projects" id="projects"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Projects">
{{formsErrors.Projects}}
</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="closeBtnClick()">Close</button>
<button type="submit" class="btn btn-primary" [disabled]="editUser.invalid">Save</button>
</div>
</form>
</div>
</ng-template>
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { ListTemplateExportComponent } from './list-template-export.component';
describe('ListTemplateExportComponent', () => {
let component: ListTemplateExportComponent;
let fixture: ComponentFixture<ListTemplateExportComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ListTemplateExportComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ListTemplateExportComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { DatePipe } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { UserService } from '../userService.service';
import { User } from '../user';
@Component({
selector: 'app-list-template-export',
templateUrl: './list-template-export.component.html',
styleUrls: ['./list-template-export.component.scss']
})
export class ListTemplateExportComponent implements OnInit {
constructor(private userService: UserService, private fb: FormBuilder, private modalService: NgbModal, private datePipe: DatePipe) {
this.filterArray = this.userList;
}
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this._searchTerm = val;
this.filterArray = this.filter(val);
}
page = 1;
pageSize = 7;
userList: User[] = this.userService.getUser();
config: any;
editUser: FormGroup | null = null;
userDetail: User | null = null;
filterArray: User[] | null = null;
joiningDate: string | null = null;
_searchTerm = '';
ValidationMessage =
[
{
Name: { required: 'Name is required.' }
}, {
Position: { required: 'Position is required.' }
}, {
Email: { required: 'Email is required.' }
},
{
Mobile: { required: 'Mobile is required.' }
},
{
DateOfJoining: { required: 'DOJ is required.' }
},
{
Salary: { required: 'Salary is required.' }
},
{
Projects: { required: 'Project is required.' }
},
];
formsErrors = [];
ngOnInit() {
this.editUser = this.fb.group({
id: [''],
Name: ['', Validators.required],
Position: ['', Validators.required],
Email: ['', Validators.required],
Mobile: ['', Validators.required],
DateOfJoining: ['', Validators.required],
Salary: ['', Validators.required],
Projects: ['', Validators.required],
});
}
filter(v: string) {
return this.userList.filter(x => x.Name.toLowerCase().
indexOf(v.toLowerCase()) !== -1 || x.Email.toLowerCase().indexOf(v.toLowerCase()) !== -1);
}
deleteUser(id: number): void {
if (this.filterArray) {
this.filterArray = this.filterArray.filter(user => user.id !== id);
}
}
logValidationErrors(group: FormGroup) {
// Object.keys(group.controls).forEach((key: string) => {
// const ac = group.get(key);
// this.formsErrors[key] = '';
// if (ac && !ac.valid && (ac.touched || ac.dirty)) {
// const message = this.ValidationMessage[key];
// for (const errorKey in ac.errors) {
// if (errorKey) {
// this.formsErrors[key] += message[errorKey] + ' ';
// }
// }
// }
// if (ac instanceof FormGroup) {
// this.logValidationErrors(ac)
// }
// })
}
openModal(targetModal: NgbModal, user: User | null) {
this.modalService.open(targetModal, {
centered: true,
backdrop: 'static'
});
if (user != null) {
if (user.DateOfJoining) {
this.joiningDate = this.datePipe.
transform(new Date(user.DateOfJoining), 'yyyy-MM-dd');
}
this.userDetail = user;
this.editUser?.patchValue({
Name: user.Name,
Position: user.Position,
Email: user.Email,
Mobile: user.Mobile,
DateOfJoining: user.DateOfJoining,
Salary: user.Salary,
Projects: user.Projects,
});
}
}
onSubmit() {
if (this.userDetail != null) {
const index = this.userService.getUser().indexOf(this.userDetail);
if (this.editUser != null) {
this.userDetail.Name = this.editUser.get('Name')?.value;
this.userDetail.Position = this.editUser.get('Position')?.value;
this.userDetail.Email = this.editUser.get('Email')?.value;
this.userDetail.Mobile = this.editUser.get('Mobile')?.value;
this.userDetail.DateOfJoining = this.editUser.get('DateOfJoining')?.value;
this.userDetail.Salary = this.editUser.get('Salary')?.value;
this.userDetail.Projects = this.editUser.get('Projects')?.value;
}
this.userService.getUser()[index] = this.userDetail;
} else {
this.userDetail = new User();
this.userDetail.id = Math.max.apply(Math, this.userService.getUser().map(function (o) { return o.id; })) + 1;
this.userDetail.Name = this.editUser?.get('Name')?.value;
this.userDetail.Position = this.editUser?.get('Position')?.value;
this.userDetail.Email = this.editUser?.get('Email')?.value;
this.userDetail.Mobile = this.editUser?.get('Mobile')?.value;
this.userDetail.DateOfJoining = new Date();
this.userDetail.Salary = this.editUser?.get('Salary')?.value;
this.userDetail.Projects = this.editUser?.get('Projects')?.value;
this.userDetail.imagePath = 'assets/images/users/7.jpg';
this.filterArray?.push(this.userDetail);
}
this.modalService.dismissAll();
this.userDetail = null;
this.joiningDate = '';
this.ngOnInit();
}
closeBtnClick() {
this.modalService.dismissAll();
this.ngOnInit();
}
}
<div class="row">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">Template</h4>
<h5 class="card-subtitle">Here is the template list you can add, edit or delet the template</h5>
<div class="d-flex mb-3 mt-3">
<input type="text" class="form-control w-25" placeholder="Search by Name or Email" [(ngModel)]='searchTerm'>
<button class="btn btn-primary ml-auto" (click)="openModal(editTemplateModal, null)">Add template</button>
</div>
<div class="table-responsive table-bordered">
<table class="table table-striped mb-0 no-wrap v-middle">
<thead>
<tr>
<th class="text-center" scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Description</th>
<th scope="col">Upload Date</th>
<th scope="col">Status</th>
<th scope="col">Type</th>
<th scope="col">File</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let template of filterArray | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize">
<td class="text-center">
{{template.id}}
</td>
<td>
<div class="d-flex align-items-center">
<img class="rounded-circle" [src]='template.imagePath' height=" 50px" width="50px">
<div class="ml-3">
<p class="font-medium mb-0">{{ template.Name }}</p>
<small>{{template.Position}}</small>
</div>
</div>
</td>
<td>{{ template.Email }}</td>
<td>{{ template.Mobile }}</td>
<td>{{ template.DateOfJoining |date :'fullDate' }}</td>
<td>{{ template.Salary }}</td>
<td>{{ template.Projects }}</td>
<td>
<a href="javascript: void(0);" (click)="openModal(editTemplateModal, template)" class="link mr-2"
placement="top" ngbTooltip="Edit">
<i-feather name="edit-2" class="feather-sm"></i-feather>
</a>
<a href="javascript: void(0);" class="link" (click)="deletetemplate(template.id)" placement="top"
ngbTooltip="Delete">
<i-feather name="trash-2" class="feather-sm"></i-feather>
</a>
</td>
</tr>
</tbody>
</table>
</div>
<div class="d-flex justify-content-center mt-5">
<ngb-pagination [(page)]="page" [pageSize]="pageSize" [collectionSize]="templateList.length"></ngb-pagination>
</div>
</div>
</div>
</div>
<ng-template #editTemplateModal let-modal>
<div class="modal-header">
<h5 class="modal-title" id="edittemplateLabel">Edit template</h5>
<button type="button" class="close" (click)="closeBtnClick()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form [formGroup]="edittemplate" (ngSubmit)="onSubmit()">
<div class="form-group row">
<label for="name" class="col-sm-4 col-form-label">ชื่อ</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Name" id="name" (blur)=logValidationErrors(edittemplate)>
<span class="help-block" *ngIf="formsErrors.Name">
{{formsErrors.Name}}
</span>
</div>
</div>
<div class="form-group row">
<label for="name" class="col-sm-4 col-form-label">ไฟล์เทมเพลต</label>
<div class="col-sm-8">
<input type="file" class="form-control">
</div>
</div>
<div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">รายละเอียด</label>
<div class="col-sm-8">
<textarea class="form-control"></textarea>
</div>
</div>
<div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">ประเภท</label>
<div class="col-sm-8">
<select class="form-control">
<option>Excel</option>
<option>Mail Merge</option>
<option>Resume</option>
</select>
</div>
</div>
<div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">สถานะ</label>
<div class="col-sm-8">
<select class="form-control">
<option>เปิดใช้งาน</option>
<option>ปิดการใช้งาน</option>
</select>
</div>
</div>
<!-- <div class="form-group row">
<label for="email" class="col-sm-4 col-form-label">Email</label>
<div class="col-sm-8">
<input type="email" class="form-control" formControlName="Email" id="email"
(blur)=logValidationErrors(edittemplate)>
<span class="help-block" *ngIf="formsErrors.Email">
{{formsErrors.Email}}
</span>
</div>
</div>
<div class="form-group row">
<label for="mobile" class="col-sm-4 col-form-label">Mobile</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Mobile" id="mobile"
(blur)=logValidationErrors(edittemplate)>
<span class="help-block" *ngIf="formsErrors.Mobile">
{{formsErrors.Mobile}}
</span>
</div>
</div>
<div class="form-group row">
<label for="doj" class="col-sm-4 col-form-label">Date Of Joining</label>
<div class="col-sm-8">
<input type="date" class="form-control" formControlName="DateOfJoining" [(ngModel)]="joiningDate" id="doj"
(blur)=logValidationErrors(edittemplate)>
<span class="help-block" *ngIf="formsErrors.DateOfJoining">
{{formsErrors.DateOfJoining}}
</span>
</div>
</div>
<div class="form-group row">
<label for="salary" class="col-sm-4 col-form-label">Salary</label>
<div class="col-sm-8">
<input type="number" class="form-control" formControlName="Salary" id="salary"
(blur)=logValidationErrors(edittemplate)>
<span class="help-block" *ngIf="formsErrors.Salary">
{{formsErrors.Salary}}
</span>
</div>
</div>
<div class="form-group row">
<label for="projects" class="col-sm-4 col-form-label">Projects</label>
<div class="col-sm-8">
<input type="number" class="form-control" formControlName="Projects" id="projects"
(blur)=logValidationErrors(edittemplate)>
<span class="help-block" *ngIf="formsErrors.Projects">
{{formsErrors.Projects}}
</span>
</div>
</div> -->
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="closeBtnClick()">Close</button>
<button type="submit" class="btn btn-primary" [disabled]="edittemplate.invalid">Save</button>
</div>
</form>
</div>
</ng-template>
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { ListTemplateImportComponent } from './list-template-import.component';
describe('ListTemplateImportComponent', () => {
let component: ListTemplateImportComponent;
let fixture: ComponentFixture<ListTemplateImportComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ListTemplateImportComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ListTemplateImportComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { User } from '../user';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UserService } from '../userService.service';
import { DatePipe } from '@angular/common';
@Component({
selector: 'app-list-template-import',
templateUrl: './list-template-import.component.html',
styleUrls: ['./list-template-import.component.scss']
})
export class ListTemplateImportComponent implements OnInit {
constructor(private userService: UserService, private fb: FormBuilder, private modalService: NgbModal, private datePipe: DatePipe) {
this.filterArray = this.templateList;
}
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this._searchTerm = val;
this.filterArray = this.filter(val);
}
page = 1;
pageSize = 7;
templateList: User[] = this.userService.getUser();
config: any;
editUser: FormGroup | null = null;
userDetail: User | null = null;
filterArray: User[] | null = null;
joiningDate: string | null = null;
_searchTerm = '';
ValidationMessage =
[
{
Name: { required: 'Name is required.' }
}, {
Position: { required: 'Position is required.' }
}, {
Email: { required: 'Email is required.' }
},
{
Mobile: { required: 'Mobile is required.' }
},
{
DateOfJoining: { required: 'DOJ is required.' }
},
{
Salary: { required: 'Salary is required.' }
},
{
Projects: { required: 'Project is required.' }
},
];
formsErrors = [];
ngOnInit() {
this.editUser = this.fb.group({
id: [''],
Name: ['', Validators.required],
Position: ['', Validators.required],
Email: ['', Validators.required],
Mobile: ['', Validators.required],
DateOfJoining: ['', Validators.required],
Salary: ['', Validators.required],
Projects: ['', Validators.required],
});
}
filter(v: string) {
return this.templateList.filter(x => x.Name.toLowerCase().
indexOf(v.toLowerCase()) !== -1 || x.Email.toLowerCase().indexOf(v.toLowerCase()) !== -1);
}
deleteUser(id: number): void {
if (this.filterArray) {
this.filterArray = this.filterArray.filter(user => user.id !== id);
}
}
logValidationErrors(group: FormGroup) {
// Object.keys(group.controls).forEach((key: string) => {
// const ac = group.get(key);
// this.formsErrors[key] = '';
// if (ac && !ac.valid && (ac.touched || ac.dirty)) {
// const message = this.ValidationMessage[key];
// for (const errorKey in ac.errors) {
// if (errorKey) {
// this.formsErrors[key] += message[errorKey] + ' ';
// }
// }
// }
// if (ac instanceof FormGroup) {
// this.logValidationErrors(ac)
// }
// })
}
openModal(targetModal: NgbModal, user: User | null) {
this.modalService.open(targetModal, {
centered: true,
backdrop: 'static'
});
if (user != null) {
if (user.DateOfJoining) {
this.joiningDate = this.datePipe.
transform(new Date(user.DateOfJoining), 'yyyy-MM-dd');
}
this.userDetail = user;
this.editUser?.patchValue({
Name: user.Name,
Position: user.Position,
Email: user.Email,
Mobile: user.Mobile,
DateOfJoining: user.DateOfJoining,
Salary: user.Salary,
Projects: user.Projects,
});
}
}
onSubmit() {
if (this.userDetail != null) {
const index = this.userService.getUser().indexOf(this.userDetail);
if (this.editUser != null) {
this.userDetail.Name = this.editUser.get('Name')?.value;
this.userDetail.Position = this.editUser.get('Position')?.value;
this.userDetail.Email = this.editUser.get('Email')?.value;
this.userDetail.Mobile = this.editUser.get('Mobile')?.value;
this.userDetail.DateOfJoining = this.editUser.get('DateOfJoining')?.value;
this.userDetail.Salary = this.editUser.get('Salary')?.value;
this.userDetail.Projects = this.editUser.get('Projects')?.value;
}
this.userService.getUser()[index] = this.userDetail;
} else {
this.userDetail = new User();
this.userDetail.id = Math.max.apply(Math, this.userService.getUser().map(function (o) { return o.id; })) + 1;
this.userDetail.Name = this.editUser?.get('Name')?.value;
this.userDetail.Position = this.editUser?.get('Position')?.value;
this.userDetail.Email = this.editUser?.get('Email')?.value;
this.userDetail.Mobile = this.editUser?.get('Mobile')?.value;
this.userDetail.DateOfJoining = new Date();
this.userDetail.Salary = this.editUser?.get('Salary')?.value;
this.userDetail.Projects = this.editUser?.get('Projects')?.value;
this.userDetail.imagePath = 'assets/images/users/7.jpg';
this.filterArray?.push(this.userDetail);
}
this.modalService.dismissAll();
this.userDetail = null;
this.joiningDate = '';
this.ngOnInit();
}
closeBtnClick() {
this.modalService.dismissAll();
this.ngOnInit();
}
}
<div class="row">
<div class="col-12">
<div class="card card-body">
<h4 class="card-title">Employee Table</h4>
<h5 class="card-subtitle">Here is the employee list you can add, edit or delet the emplyee</h5>
<div class="d-flex mb-3 mt-3">
<input type="text" class="form-control w-25" placeholder="Search by Name or Email" [(ngModel)]='searchTerm'>
<button class="btn btn-primary ml-auto" (click)="openModal(editUserModal, null)">Add User</button>
</div>
<div class="table-responsive table-bordered">
<table class="table table-striped mb-0 no-wrap v-middle">
<thead>
<tr>
<th class="text-center" scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Mobile</th>
<th scope="col">Date of Joining</th>
<th scope="col">Salary</th>
<th scope="col">Projects</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of filterArray | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize">
<td class="text-center">
{{user.id}}
</td>
<td>
<div class="d-flex align-items-center">
<img class="rounded-circle" [src]='user.imagePath' height=" 50px" width="50px">
<div class="ml-3">
<p class="font-medium mb-0">{{ user.Name }}</p>
<small>{{user.Position}}</small>
</div>
</div>
</td>
<td>{{ user.Email }}</td>
<td>{{ user.Mobile }}</td>
<td>{{ user.DateOfJoining |date :'fullDate' }}</td>
<td>{{ user.Salary }}</td>
<td>{{ user.Projects }}</td>
<td>
<a href="javascript: void(0);" (click)="openModal(editUserModal, user)" class="link mr-2"
placement="top" ngbTooltip="Edit">
<i-feather name="edit-2" class="feather-sm"></i-feather>
</a>
<a href="javascript: void(0);" class="link" (click)="deleteUser(user.id)" placement="top"
ngbTooltip="Delete">
<i-feather name="trash-2" class="feather-sm"></i-feather>
</a>
</td>
</tr>
</tbody>
</table>
</div>
<div class="d-flex justify-content-center mt-5">
<ngb-pagination [(page)]="page" [pageSize]="pageSize" [collectionSize]="userList.length"></ngb-pagination>
</div>
</div>
</div>
</div>
<ng-template #editUserModal let-modal>
<div class="modal-header">
<h5 class="modal-title" id="editUserLabel">Edit User</h5>
<button type="button" class="close" (click)="closeBtnClick()" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form [formGroup]="editUser" (ngSubmit)="onSubmit()">
<div class="form-group row">
<label for="name" class="col-sm-4 col-form-label">Name</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Name" id="name" (blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Name">
{{formsErrors.Name}}
</span>
</div>
</div>
<div class="form-group row">
<label for="position" class="col-sm-4 col-form-label">Position</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Position" id="position"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Position">
{{formsErrors.Position}}
</span>
</div>
</div>
<div class="form-group row">
<label for="email" class="col-sm-4 col-form-label">Email</label>
<div class="col-sm-8">
<input type="email" class="form-control" formControlName="Email" id="email"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Email">
{{formsErrors.Email}}
</span>
</div>
</div>
<div class="form-group row">
<label for="mobile" class="col-sm-4 col-form-label">Mobile</label>
<div class="col-sm-8">
<input type="text" class="form-control" formControlName="Mobile" id="mobile"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Mobile">
{{formsErrors.Mobile}}
</span>
</div>
</div>
<div class="form-group row">
<label for="doj" class="col-sm-4 col-form-label">Date Of Joining</label>
<div class="col-sm-8">
<input type="date" class="form-control" formControlName="DateOfJoining" [(ngModel)]="joiningDate" id="doj"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.DateOfJoining">
{{formsErrors.DateOfJoining}}
</span>
</div>
</div>
<div class="form-group row">
<label for="salary" class="col-sm-4 col-form-label">Salary</label>
<div class="col-sm-8">
<input type="number" class="form-control" formControlName="Salary" id="salary"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Salary">
{{formsErrors.Salary}}
</span>
</div>
</div>
<div class="form-group row">
<label for="projects" class="col-sm-4 col-form-label">Projects</label>
<div class="col-sm-8">
<input type="number" class="form-control" formControlName="Projects" id="projects"
(blur)=logValidationErrors(editUser)>
<span class="help-block" *ngIf="formsErrors.Projects">
{{formsErrors.Projects}}
</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="closeBtnClick()">Close</button>
<button type="submit" class="btn btn-primary" [disabled]="editUser.invalid">Save</button>
</div>
</form>
</div>
</ng-template>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ListUsersComponent } from './list-users.component';
describe('ListUsersComponent', () => {
let component: ListUsersComponent;
let fixture: ComponentFixture<ListUsersComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ListUsersComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ListUsersComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
// it('should create', () => {
// expect(component).toBeTruthy();
// });
});
import { Component, OnInit } from '@angular/core';
import { UserService } from '../userService.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DatePipe } from '@angular/common';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { User } from '../user';
@Component({
selector: 'app-list-users',
templateUrl: './list-users.component.html',
styleUrls: ['./list-users.component.css']
})
export class ListUsersComponent implements OnInit {
constructor(private userService: UserService, private fb: FormBuilder, private modalService: NgbModal, private datePipe: DatePipe) {
this.filterArray = this.userList;
}
get searchTerm(): string {
return this._searchTerm;
}
set searchTerm(val: string) {
this._searchTerm = val;
this.filterArray = this.filter(val);
}
page = 1;
pageSize = 7;
userList: User[] = this.userService.getUser();
config: any;
editUser: FormGroup | null = null;
userDetail: User | null = null;
filterArray: User[] | null = null;
joiningDate: string | null = null;
_searchTerm = '';
ValidationMessage =
[
{
Name: { required: 'Name is required.' }
}, {
Position: { required: 'Position is required.' }
}, {
Email: { required: 'Email is required.' }
},
{
Mobile: { required: 'Mobile is required.' }
},
{
DateOfJoining: { required: 'DOJ is required.' }
},
{
Salary: { required: 'Salary is required.' }
},
{
Projects: { required: 'Project is required.' }
},
];
formsErrors = [];
ngOnInit() {
this.editUser = this.fb.group({
id: [''],
Name: ['', Validators.required],
Position: ['', Validators.required],
Email: ['', Validators.required],
Mobile: ['', Validators.required],
DateOfJoining: ['', Validators.required],
Salary: ['', Validators.required],
Projects: ['', Validators.required],
});
}
filter(v: string) {
return this.userList.filter(x => x.Name.toLowerCase().
indexOf(v.toLowerCase()) !== -1 || x.Email.toLowerCase().indexOf(v.toLowerCase()) !== -1);
}
deleteUser(id: number): void {
if (this.filterArray) {
this.filterArray = this.filterArray.filter(user => user.id !== id);
}
}
logValidationErrors(group: FormGroup) {
// Object.keys(group.controls).forEach((key: string) => {
// const ac = group.get(key);
// this.formsErrors[key] = '';
// if (ac && !ac.valid && (ac.touched || ac.dirty)) {
// const message = this.ValidationMessage[key];
// for (const errorKey in ac.errors) {
// if (errorKey) {
// this.formsErrors[key] += message[errorKey] + ' ';
// }
// }
// }
// if (ac instanceof FormGroup) {
// this.logValidationErrors(ac)
// }
// })
}
openModal(targetModal: NgbModal, user: User | null) {
this.modalService.open(targetModal, {
centered: true,
backdrop: 'static'
});
if (user != null) {
if (user.DateOfJoining) {
this.joiningDate = this.datePipe.
transform(new Date(user.DateOfJoining), 'yyyy-MM-dd');
}
this.userDetail = user;
this.editUser?.patchValue({
Name: user.Name,
Position: user.Position,
Email: user.Email,
Mobile: user.Mobile,
DateOfJoining: user.DateOfJoining,
Salary: user.Salary,
Projects: user.Projects,
});
}
}
onSubmit() {
if (this.userDetail != null) {
const index = this.userService.getUser().indexOf(this.userDetail);
if (this.editUser != null) {
this.userDetail.Name = this.editUser.get('Name')?.value;
this.userDetail.Position = this.editUser.get('Position')?.value;
this.userDetail.Email = this.editUser.get('Email')?.value;
this.userDetail.Mobile = this.editUser.get('Mobile')?.value;
this.userDetail.DateOfJoining = this.editUser.get('DateOfJoining')?.value;
this.userDetail.Salary = this.editUser.get('Salary')?.value;
this.userDetail.Projects = this.editUser.get('Projects')?.value;
}
this.userService.getUser()[index] = this.userDetail;
} else {
this.userDetail = new User();
this.userDetail.id = Math.max.apply(Math, this.userService.getUser().map(function (o) { return o.id; })) + 1;
this.userDetail.Name = this.editUser?.get('Name')?.value;
this.userDetail.Position = this.editUser?.get('Position')?.value;
this.userDetail.Email = this.editUser?.get('Email')?.value;
this.userDetail.Mobile = this.editUser?.get('Mobile')?.value;
this.userDetail.DateOfJoining = new Date();
this.userDetail.Salary = this.editUser?.get('Salary')?.value;
this.userDetail.Projects = this.editUser?.get('Projects')?.value;
this.userDetail.imagePath = 'assets/images/users/7.jpg';
this.filterArray?.push(this.userDetail);
}
this.modalService.dismissAll();
this.userDetail = null;
this.joiningDate = '';
this.ngOnInit();
}
closeBtnClick() {
this.modalService.dismissAll();
this.ngOnInit();
}
}
import { User } from './user';
export const users: User[] = [
{
id: 1,
Name: 'Johnathan Deo',
Position: 'Seo Expert',
Email: 'r@gmail.com',
Mobile: 9786838,
DateOfJoining: new Date('01-2-2020'),
Salary: 12000,
Projects: 10,
imagePath: 'assets/images/users/2.jpg'
},
{
id: 2,
Name: 'Mark Zukerburg',
Position: 'Web Developer',
Email: 'mark@gmail.com',
Mobile: 8786838,
DateOfJoining: new Date('04-2-2020'),
Salary: 12000,
Projects: 10,
imagePath: 'assets/images/users/3.jpg'
},
{
id: 3,
Name: 'Sam smith',
Position: 'Web Designer',
Email: 'sam@gmail.com',
Mobile: 7788838,
DateOfJoining: new Date('02-2-2020'),
Salary: 12000,
Projects: 10,
imagePath: 'assets/images/users/4.jpg'
},
{
id: 4,
Name: 'John Deo',
Position: 'Tester',
Email: 'john@gmail.com',
Mobile: 8786838,
DateOfJoining: new Date('03-2-2020'),
Salary: 12000,
Projects: 11,
imagePath: 'assets/images/users/5.jpg'
},
{
id: 5,
Name: 'Genilia',
Position: 'Actor',
Email: 'genilia@gmail.com',
Mobile: 8786838,
DateOfJoining: new Date('05-2-2020'),
Salary: 12000,
Projects: 19,
imagePath: 'assets/images/users/6.jpg'
},
{
id: 6,
Name: 'Jack Sparrow',
Position: 'Content Writer',
Email: 'jac@gmail.com',
Mobile: 8786838,
DateOfJoining: new Date('05-21-2020'),
Salary: 12000,
Projects: 5,
imagePath: 'assets/images/users/7.jpg'
},
{
id: 7,
Name: 'Tom Cruise',
Position: 'Actor',
Email: 'tom@gmail.com',
Mobile: 8786838,
DateOfJoining: new Date('02-15-2019'),
Salary: 12000,
Projects: 9,
imagePath: 'assets/images/users/3.jpg'
},
{
id: 8,
Name: 'Hary Porter',
Position: 'Actor',
Email: 'hary@gmail.com',
Mobile: 8786838,
DateOfJoining: new Date('07-3-2019'),
Salary: 12000,
Projects: 7,
imagePath: 'assets/images/users/6.jpg'
},
{
id: 9,
Name: 'Kristen Ronaldo',
Position: 'Player',
Email: 'kristen@gmail.com',
Mobile: 8786838,
DateOfJoining: new Date('01-15-2019'),
Salary: 12000,
Projects: 1,
imagePath: 'assets/images/users/5.jpg'
}
];
export class User {
public id = 0;
public Name = '';
public Position = '';
public Email = '';
public Mobile = 0;
public DateOfJoining: Date | null = null;
public Salary = 0;
public Projects = 0;
public imagePath = '';
}
\ No newline at end of file
import { TestBed } from '@angular/core/testing';
import { UserService } from './userService.service';
describe('UserService', () => {
let service: UserService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(UserService);
});
// it('should be created', () => {
// expect(service).toBeTruthy();
// });
});
\ No newline at end of file
import { Injectable } from '@angular/core';
import { User } from './user';
import { users } from './user-data';
@Injectable()
export class UserService {
public users: User[] = users;
public getUser() {
return this.users;
}
}
import { Injectable } from '@angular/core';
import {
CanActivate,
ActivatedRouteSnapshot,
RouterStateSnapshot,
Router
} from '@angular/router';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private routes: Router) { }
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
if (localStorage.getItem('username') != null) {
return true;
} else {
this.routes.navigate(['authentication/login']);
return false;
}
}
}
<div class="error-box">
<div class="error-body text-center">
<h1 class="error-title text-danger">404</h1>
<h3 class="text-uppercase error-subtitle">PAGE NOT FOUND !</h3>
<p class="text-muted m-t-30 m-b-30">YOU SEEM TO BE TRYING TO FIND HIS WAY HOME</p>
<a href="#/dashboard/classic" class="btn btn-danger btn-rounded waves-effect waves-light m-b-40">Back to home</a>
</div>
</div>
\ No newline at end of file
import { Component, AfterViewInit } from '@angular/core';
@Component({
selector: 'app-not-found',
templateUrl: './not-found.component.html'
})
export class NotfoundComponent implements AfterViewInit {
ngAfterViewInit() {}
}
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { NotfoundComponent } from './404/not-found.component';
import { LockComponent } from './lock/lock.component';
import { LoginComponent } from './login/login.component';
import { Login2Component } from './login2/login2.component';
import { SignupComponent } from './signup/signup.component';
import { Signup2Component } from './signup2/signup2.component';
import { AuthenticationRoutes } from './authentication.routing';
@NgModule({
imports: [
CommonModule,
RouterModule.forChild(AuthenticationRoutes),
NgbModule
],
declarations: [
NotfoundComponent,
LoginComponent,
SignupComponent,
LockComponent,
Login2Component,
Signup2Component
]
})
export class AuthenticationModule {}
import { Routes } from '@angular/router';
import { NotfoundComponent } from './404/not-found.component';
import { LockComponent } from './lock/lock.component';
import { LoginComponent } from './login/login.component';
import { Login2Component } from './login2/login2.component';
import { SignupComponent } from './signup/signup.component';
import { Signup2Component } from './signup2/signup2.component';
export const AuthenticationRoutes: Routes = [
{
path: '',
children: [
{
path: '404',
component: NotfoundComponent
},
{
path: 'lock',
component: LockComponent
},
{
path: 'login',
component: LoginComponent
},
{
path: 'login2',
component: Login2Component
},
{
path: 'signup',
component: SignupComponent
},
{
path: 'signup2',
component: Signup2Component
}
]
}
];
<div class="auth-wrapper d-flex no-block justify-content-center align-items-center" style="background:url(assets/images/background/login-register.jpg) no-repeat center center;">
<div class="auth-box">
<div>
<div class="logo">
<span class="db"><img alt="thumbnail" class="rounded-circle" width="100" src="assets/images/users/1.jpg"></span>
<h5 class="font-medium m-b-20">Genelia</h5>
</div>
<!-- Form -->
<div class="row">
<div class="col-12">
<form class="form-horizontal m-t-20" action="index.html">
<div class="form-group row">
<div class="col-12">
<input class="form-control form-control-lg" type="password" required="" placeholder="Password">
</div>
</div>
<div class="form-group text-center">
<div class="col-xs-12 p-b-20">
<button class="btn btn-block btn-lg btn-info" type="submit">LOGIN</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
import { Component } from '@angular/core';
@Component({
selector: 'app-lock',
templateUrl: './lock.component.html'
})
export class LockComponent {
constructor() {}
}
<div class="auth-wrapper d-flex no-block justify-content-center align-items-center" style="background:url(assets/images/background/login-register.jpg) no-repeat center center;">
<div class="auth-box m-3 m-md-0">
<div id="loginform" [ngClass]="{'d-none': recoverform}">
<div class="logo">
<span class="db"><img src="assets/images/logo-icon.png" alt="logo" /></span>
<h5 class="font-medium m-b-20">Sign In to Admin</h5>
</div>
<!-- Form -->
<div class="row">
<div class="col-12">
<form class="form-horizontal m-t-20" id="loginform">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1"><i class="ti-user"></i></span>
</div>
<input type="text" class="form-control" placeholder="Username" aria-label="Username" aria-describedby="basic-addon1">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon2"><i class="ti-pencil"></i></span>
</div>
<input type="text" class="form-control" placeholder="Password" aria-label="Password" aria-describedby="basic-addon1">
</div>
<div class="form-group row">
<div class="col-md-12">
<div class="custom-control custom-checkbox d-flex">
<input type="checkbox" class="custom-control-input" id="customCheck1">
<label class="custom-control-label font-14" for="customCheck1">Remember me</label>
<a (click)="showRecoverForm()" href="javascript:void(0)" id="to-recover" class="text-dark font-14 ml-auto"><i class="fa fa-lock m-r-5"></i> Forgot pwd?</a>
</div>
</div>
</div>
<div class="form-group text-center">
<div class="col-xs-12 p-b-20">
<a class="btn btn-block btn-lg btn-info" href="/apps/users">Log In</a>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 m-t-10 text-center">
<div class="social">
<a href="javascript:void(0)" class="btn btn-facebook mr-2" data-toggle="tooltip" title="" data-original-title="Login with Facebook"> <i aria-hidden="true" class="fab fa-facebook"></i> </a>
<a href="javascript:void(0)" class="btn btn-googleplus" data-toggle="tooltip" title="" data-original-title="Login with Google"> <i aria-hidden="true" class="fab fa-google-plus"></i> </a>
</div>
</div>
</div>
<div class="form-group m-b-0 m-t-10">
<div class="col-sm-12 text-center">
Don't have an account? <a href="authentication/signup" class="text-info m-l-5"><b>Sign Up</b></a>
</div>
</div>
</form>
</div>
</div>
</div>
<div id="recoverform" [ngClass]="{'d-block': recoverform}">
<div class="logo">
<span class="db"><img src="assets/images/logo-icon.png" alt="logo" /></span>
<h5 class="font-medium m-b-20">Recover Password</h5>
<span>Enter your Email and instructions will be sent to you!</span>
</div>
<div class="row m-t-20">
<!-- Form -->
<form class="col-12">
<!-- email -->
<div class="form-group row">
<div class="col-12">
<input class="form-control form-control-lg" type="email" required="" placeholder="Username">
</div>
</div>
<!-- pwd -->
<div class="row m-t-20">
<div class="col-12">
<button class="btn btn-block btn-lg btn-danger" type="submit" name="action">Reset</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
import { Component } from '@angular/core';
@Component({
selector: 'app-login',
templateUrl: './login.component.html'
})
export class LoginComponent {
constructor() {}
loginform = true;
recoverform = false;
showRecoverForm() {
this.loginform = !this.loginform;
this.recoverform = !this.recoverform;
}
}
<div class="auth-wrapper d-flex no-block justify-content-center align-items-center" style="background:url(assets/images/background/login-register.jpg) no-repeat center center;">
<div class="auth-box on-sidebar m-3 m-md-0">
<div id="loginform" [ngClass]="{'d-none': recoverform}">
<div class="logo">
<span class="db"><img src="assets/images/logo-icon.png" alt="logo" /></span>
<h5 class="font-medium m-b-20">Sign In to Admin</h5>
</div>
<!-- Form -->
<div class="row">
<div class="col-12">
<form class="form-horizontal m-t-20" id="loginform">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1"><i class="ti-user"></i></span>
</div>
<input type="text" class="form-control" placeholder="Username" aria-label="Username" aria-describedby="basic-addon1">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon2"><i class="ti-pencil"></i></span>
</div>
<input type="text" class="form-control" placeholder="Password" aria-label="Password" aria-describedby="basic-addon1">
</div>
<div class="form-group row">
<div class="col-md-12">
<div class="custom-control custom-checkbox d-flex">
<input type="checkbox" class="custom-control-input" id="customCheck1">
<label class="custom-control-label font-14" for="customCheck1">Remember me</label>
<a (click)="showRecoverForm()" href="javascript:void(0)" id="to-recover" class="text-dark ml-auto font-14"><i class="fa fa-lock m-r-5"></i> Forgot pwd?</a>
</div>
</div>
</div>
<div class="form-group text-center">
<div class="col-xs-12 p-b-20">
<a class="btn btn-block btn-lg btn-info" href="/dashboard/classic">Log In</a>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 m-t-10 text-center">
<div class="social">
<a href="javascript:void(0)" class="btn btn-facebook mr-2" data-toggle="tooltip" title="" data-original-title="Login with Facebook"> <i aria-hidden="true" class="fab fa-facebook"></i> </a>
<a href="javascript:void(0)" class="btn btn-googleplus" data-toggle="tooltip" title="" data-original-title="Login with Google"> <i aria-hidden="true" class="fab fa-google-plus"></i> </a>
</div>
</div>
</div>
<div class="form-group m-b-0 m-t-10">
<div class="col-sm-12 text-center">
Don't have an account? <a href="/authentication/signup2" class="text-info m-l-5"><b>Sign Up</b></a>
</div>
</div>
</form>
</div>
</div>
</div>
<div id="recoverform" [ngClass]="{'d-block': recoverform}">
<div class="logo">
<span class="db"><img src="assets/images/logo-icon.png" alt="logo" /></span>
<h5 class="font-medium m-b-20">Recover Password</h5>
<span>Enter your Email and instructions will be sent to you!</span>
</div>
<div class="row m-t-20">
<!-- Form -->
<form class="col-12" action="index.html">
<!-- email -->
<div class="form-group row">
<div class="col-12">
<input class="form-control form-control-lg" type="email" required="" placeholder="Username">
</div>
</div>
<!-- pwd -->
<div class="row m-t-20">
<div class="col-12">
<button class="btn btn-block btn-lg btn-danger" type="submit" name="action">Reset</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
\ No newline at end of file
import { Component } from '@angular/core';
@Component({
selector: 'app-login',
templateUrl: './login2.component.html'
})
export class Login2Component {
constructor() {}
loginform = true;
recoverform = false;
showRecoverForm() {
this.loginform = !this.loginform;
this.recoverform = !this.recoverform;
}
}
<div class="auth-wrapper d-flex no-block justify-content-center align-items-center" style="background:url(assets/images/background/login-register.jpg) no-repeat center center;">
<div class="auth-box m-3 m-md-0">
<div>
<div class="logo">
<span class="db"><img src="assets/images/logo-icon.png" alt="logo" /></span>
<h5 class="font-medium m-b-20">Sign Up to Admin</h5>
</div>
<!-- Form -->
<div class="row">
<div class="col-12">
<form class="form-horizontal m-t-20" action="index.html">
<div class="form-group row ">
<div class="col-12 ">
<input class="form-control" type="text" required=" " placeholder="Name">
</div>
</div>
<div class="form-group row">
<div class="col-12 ">
<input class="form-control" type="text" required=" " placeholder="Email">
</div>
</div>
<div class="form-group row">
<div class="col-12 ">
<input class="form-control" type="password" required=" " placeholder="Password">
</div>
</div>
<div class="form-group row">
<div class="col-12 ">
<input class="form-control" type="password" required=" " placeholder="Confirm Password">
</div>
</div>
<div class="form-group row">
<div class="col-md-12 ">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck1">
<label class="custom-control-label" for="customCheck1">I agree to all <a href="javascript:void(0)">Terms</a></label>
</div>
</div>
</div>
<div class="form-group text-center ">
<div class="col-xs-12 p-b-20 ">
<a class="btn btn-block btn-lg btn-info" href="/dashboard/classic">SIGN UP</a>
</div>
</div>
<div class="form-group m-b-0 m-t-10 ">
<div class="col-sm-12 text-center ">
Already have an account? <a href="/authentication/login" class="text-info m-l-5 "><b>Sign In</b></a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
import { Component } from '@angular/core';
@Component({
selector: 'app-signup',
templateUrl: './signup.component.html'
})
export class SignupComponent {
constructor() {}
}
<div class="auth-wrapper d-flex no-block justify-content-center align-items-center" style="background:url(assets/images/background/login-register.jpg) no-repeat center center;">
<div class="auth-box on-sidebar m-3 m-md-0">
<div>
<div class="logo">
<span class="db"><img src="assets/images/logo-icon.png" alt="logo" /></span>
<h5 class="font-medium m-b-20">Sign Up to Admin</h5>
</div>
<!-- Form -->
<div class="row">
<div class="col-12">
<form class="form-horizontal m-t-20" action="index.html">
<div class="form-group row ">
<div class="col-12 ">
<input class="form-control" type="text" required=" " placeholder="Name">
</div>
</div>
<div class="form-group row">
<div class="col-12 ">
<input class="form-control" type="text" required=" " placeholder="Email">
</div>
</div>
<div class="form-group row">
<div class="col-12 ">
<input class="form-control" type="password" required=" " placeholder="Password">
</div>
</div>
<div class="form-group row">
<div class="col-12 ">
<input class="form-control" type="password" required=" " placeholder="Confirm Password">
</div>
</div>
<div class="form-group row">
<div class="col-md-12 ">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck1">
<label class="custom-control-label" for="customCheck1">I agree to all <a href="javascript:void(0)">Terms</a></label>
</div>
</div>
</div>
<div class="form-group text-center ">
<div class="col-xs-12 p-b-20 ">
<a class="btn btn-block btn-lg btn-info" href="/dashboard/classic">SIGN UP</a>
</div>
</div>
<div class="form-group m-b-0 m-t-10 ">
<div class="col-sm-12 text-center ">
Already have an account? <a href="/authentication/login2" class="text-info m-l-5 "><b>Sign In</b></a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
import { Component } from '@angular/core';
@Component({
selector: 'app-signup',
templateUrl: './signup2.component.html'
})
export class Signup2Component {
constructor() {}
}
import { TestBed } from '@angular/core/testing';
import { MyserviceService } from './myservice.service';
describe('MyserviceService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: MyserviceService = TestBed.get(MyserviceService);
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
@Injectable()
export class MyserviceService {
constructor() { }
checkusernameandpassword(uname: string, pwd: string) {
if (uname === 'admin' && pwd === 'admin123') {
localStorage.setItem('username', 'admin');
return true;
} else {
return false;
}
}
logout() {
// remove user from local storage to log user out
localStorage.removeItem('username');
}
}
import { RouteInfo } from './vertical-sidebar.metadata'; import { RouteInfo } from "./vertical-sidebar.metadata";
export const ROUTES: RouteInfo[] = [ export const ROUTES: RouteInfo[] = [
{ {
path: '', path: '/apps/import-template',
title: 'Personal', title: 'Import Template',
icon: 'mdi mdi-dots-horizontal', icon: 'mdi mdi-adjust',
class: 'nav-small-cap', class: '',
extralink: true, label: "",
labelClass: "",
extralink: false,
submenu: [] submenu: []
}, },
{ {
path: '/starter', path: '/apps/export-template',
title: 'Starter Page', title: 'Export Template',
icon: 'Home', icon: 'mdi mdi-adjust',
class: '', class: '',
label: "",
labelClass: "",
extralink: false, extralink: false,
submenu: [] submenu: []
}, },
{ {
path: '', path: "",
title: 'UI Components', title: "Personal",
icon: 'mdi mdi-dots-horizontal', icon: "mdi mdi-dots-horizontal",
class: 'nav-small-cap', class: "nav-small-cap",
extralink: true, extralink: true,
submenu: [] label: "",
labelClass: "",
submenu: [],
},
{
path: "dashboard",
title: "Dashboards",
icon: "Home",
class: "has-arrow",
extralink: false,
label: "10",
labelClass: "badge badge-info sidebar-badge",
submenu: [
{
path: "/dashboard/classic",
title: "Classic",
icon: "mdi mdi-adjust",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/dashboard/analytical",
title: "Analytical",
icon: "mdi mdi-adjust",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/dashboard/cryptocurrency",
title: "Cryptocurrency",
icon: "mdi mdi-adjust",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/dashboard/overview",
title: "Overview",
icon: "mdi mdi-adjust",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/dashboard/ecommerce",
title: "Ecommerce",
icon: "mdi mdi-adjust",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/dashboard/sale",
title: "Sale",
icon: "mdi mdi-adjust",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/dashboard/general",
title: "General",
icon: "mdi mdi-adjust",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/dashboard/trendy",
title: "Trendy",
icon: "mdi mdi-adjust",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/dashboard/campaign",
title: "Campaign",
icon: "mdi mdi-adjust",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/dashboard/modern",
title: "Modern",
icon: "mdi mdi-adjust",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
],
},
{
path: "",
title: "Apps",
icon: "mdi mdi-dots-horizontal",
class: "nav-small-cap",
extralink: true,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/mail/inbox",
title: "Mail",
icon: "Inbox",
class: "",
extralink: false,
label: "new",
labelClass: "badge badge-success sidebar-badge",
submenu: [],
},
{
path: "/apps/jobs",
title: "Job",
icon: "Briefcase",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/chat",
title: "Chat",
icon: "message-square",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/todo",
title: "Todo",
icon: "Sliders",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/tasks",
title: "Tasks",
icon: "Layout",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/notes",
title: "Notes",
icon: "Book",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/users",
title: "Users",
icon: "Users",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/usersrxjs",
title: "Users-Rxjs",
icon: "Users",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/fullcalendar",
title: "Calendar",
icon: "Calendar",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/taskboard",
title: "Taskboard",
icon: "Layout",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/contact",
title: "Contact",
icon: "Phone",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/contactrxjs",
title: "Contact-Rxjs",
icon: "Phone",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/contact-list",
title: "Contact Lists",
icon: "Pocket",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/contact-list-rxjs",
title: "Contact Lists-Rxjs",
icon: "Pocket",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/contact-grid",
title: "Contact Grid",
icon: "Server",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/apps/invoice",
title: "Invoice",
icon: "Server",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "ticket",
title: "Ticket",
icon: "bookmark",
class: "has-arrow",
extralink: false,
label: "",
labelClass: "",
submenu: [
{
path: "apps/ticket/ticketlist",
title: "Ticket List",
icon: "mdi mdi-book-multiple",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "apps/ticket/ticketdetails",
title: "Ticket Details",
icon: "mdi mdi-book-plus",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
],
},
{
path: "",
title: "UI",
icon: "mdi mdi-dots-horizontal",
class: "nav-small-cap",
extralink: true,
label: "",
labelClass: "",
submenu: [],
},
{
path: "component",
title: "UI Elements",
icon: "Cpu",
class: "has-arrow",
extralink: false,
label: "13",
labelClass: "badge badge-warning sidebar-badge",
submenu: [
{
path: "/component/accordion",
title: "Accordion",
icon: "mdi mdi-equal",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/component/alert",
title: "Alert",
icon: "mdi mdi-message-bulleted",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/component/carousel",
title: "Carousel",
icon: "mdi mdi-view-carousel",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/component/dropdown",
title: "Dropdown",
icon: "mdi mdi-arrange-bring-to-front",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/component/modal",
title: "Modal",
icon: "mdi mdi-tablet",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/component/pagination",
title: "Pagination",
icon: "mdi mdi-backburger",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/component/poptool",
title: "Popover & Tooltip",
icon: "mdi mdi-image-filter-vintage",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/component/progressbar",
title: "Progressbar",
icon: "mdi mdi-poll",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/component/rating",
title: "Ratings",
icon: "mdi mdi-bandcamp",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/component/tabs",
title: "Tabs",
icon: "mdi mdi-sort-variant",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/component/timepicker",
title: "Timepicker",
icon: "mdi mdi-calendar-clock",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/component/buttons",
title: "Button",
icon: "mdi mdi-toggle-switch",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/component/notifier",
title: "Notifier",
icon: "mdi mdi-bandcamp",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
],
},
{
path: "cards",
title: "Cards",
icon: "Copy",
class: "has-arrow",
extralink: false,
label: "",
labelClass: "",
submenu: [
{
path: "/cards/basiccards",
title: "Basic Cards",
icon: "mdi mdi-layers",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/cards/customcards",
title: "Custom Cards",
icon: "mdi mdi-credit-card-scan",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/cards/weathercards",
title: "Weather Cards",
icon: "mdi mdi-weather-fog",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
],
},
{
path: "extra-component",
title: "Extra Components",
icon: "Layers",
class: "has-arrow",
extralink: false,
label: "",
labelClass: "",
submenu: [
{
path: "/extra-component/toastr",
title: "Toastr",
icon: "mdi mdi-poll",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/extra-component/editor",
title: "Editor",
icon: "mdi mdi-dns",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/extra-component/dragndrop",
title: "Drag n Drop",
icon: "mdi mdi-arrow-expand-all",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
],
},
{
path: "widgets",
title: "Widgets",
icon: "Grid",
class: "has-arrow",
extralink: false,
label: "",
labelClass: "",
submenu: [
{
path: "/widgets/apps",
title: "Widget Apps",
icon: "mdi mdi-comment-processing-outline",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/widgets/data",
title: "Widget Data",
icon: "mdi mdi-calendar",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
],
},
{
path: "",
title: "Forms",
icon: "mdi mdi-dots-horizontal",
class: "nav-small-cap",
extralink: true,
label: "",
labelClass: "",
submenu: [],
},
{
path: "forms",
title: "Form Elements",
icon: "Edit",
class: "has-arrow",
extralink: false,
label: "",
labelClass: "",
submenu: [
{
path: "/forms/forminputs",
title: "Form Inputs",
icon: "mdi mdi-priority-low",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/forms/inputgroups",
title: "Input Groups",
icon: "mdi mdi-rounded-corner",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/forms/inputgrid",
title: "Input Grid",
icon: "mdi mdi-select-all",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/forms/checkboxandradio",
title: "Checkbox & Radio",
icon: "mdi mdi-shape-plus",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/forms/multiselect",
title: "Multiselect",
icon: "mdi mdi-select-inverse",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
],
},
{
path: "formsl",
title: "Form Layouts",
icon: "Sidebar",
class: "has-arrow",
extralink: false,
label: "",
labelClass: "",
submenu: [
{
path: "/forms/formsl/formbasic",
title: "Basic Forms",
icon: "mdi mdi-vector-difference-ba",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/forms/formsl/formhorizontal",
title: "Horizontal Forms",
icon: "mdi mdi-file-document-box",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/forms/formsl/formactions",
title: "Form Actions",
icon: "mdi mdi-code-greater-than",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/forms/formsl/formrowseparator",
title: "Row Separator",
icon: "mdi mdi-code-equal",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/forms/formsl/formstripedrows",
title: "Striped Rows",
icon: "mdi mdi-content-duplicate",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/forms/formsl/formdetail",
title: "Detail Forms",
icon: "mdi mdi-cards-outline",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
],
},
{
path: "formsa",
title: "Form Addons",
icon: "Package",
class: "has-arrow",
extralink: false,
label: "",
labelClass: "",
submenu: [
{
path: "forms/formsa/formvalidation",
title: "Form Validation",
icon: "mdi mdi-alert-box",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "forms/formsa/typehead",
title: "Form Typehead",
icon: "mdi mdi-backburger",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "forms/formsa/datepicker",
title: "Datepicker",
icon: "mdi mdi-calendar-check",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "forms/formsa/language-datepicker",
title: "Language Datepicker",
icon: "mdi mdi-calendar-check",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "forms/ngx",
title: "Form Wizard / Steps",
icon: "mdi mdi-attachment",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
],
},
{
path: "",
title: "Tables",
icon: "mdi mdi-dots-horizontal",
class: "nav-small-cap",
extralink: true,
label: "",
labelClass: "",
submenu: [],
},
{
path: "tables",
title: "Bootstrap Tables",
icon: "Crop",
class: "has-arrow",
extralink: false,
label: "4",
labelClass: "badge badge-danger sidebar-badge",
submenu: [
{
path: "/tables/basictables",
title: "Basic Tables",
icon: "mdi mdi-border-all",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/tables/darktables",
title: "Dark Basic Tables",
icon: "mdi mdi-border-all",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/tables/colortables",
title: "Colored Tables",
icon: "mdi mdi-border-all",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/tables/tablesizing",
title: "Table Sizing",
icon: "mdi mdi-border-all",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
],
}, },
{ {
path: '', path: "/tables/ngtable",
title: 'Component', title: "Ng Tables",
icon: 'Cpu', icon: "Maximize",
class: 'has-arrow', class: "",
extralink: false, extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/tables/datatable",
title: "Data Tables",
icon: "Disc",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "",
title: "Charts",
icon: "mdi mdi-dots-horizontal",
class: "nav-small-cap",
extralink: true,
label: "",
labelClass: "",
submenu: [],
},
{
path: "charts",
title: "Charts",
icon: "Loader",
class: "has-arrow",
extralink: false,
label: "",
labelClass: "",
submenu: [
{
path: "/charts/chartjs",
title: "Chart Js",
icon: "mdi mdi-svg",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/charts/chartistjs",
title: "Chartist Js",
icon: "mdi mdi-blur",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/charts/ngxchart",
title: "Ngx Charts",
icon: "mdi mdi-blur",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/charts/apexchart",
title: "Apex Charts",
icon: "mdi mdi-blur",
class: "",
label: "",
labelClass: "",
extralink: false,
submenu: [],
},
],
},
{
path: "",
title: "Maps",
icon: "mdi mdi-dots-horizontal",
class: "nav-small-cap",
extralink: true,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/maps/google",
title: "Google Maps",
icon: "Map",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "",
title: "Pages",
icon: "mdi mdi-dots-horizontal",
class: "nav-small-cap",
extralink: true,
label: "",
labelClass: "",
submenu: [],
},
{
path: "ecom",
title: "Ecommerce Pages",
icon: "shopping-cart",
class: "has-arrow",
extralink: false,
label: "",
labelClass: "",
submenu: [
{
path: "/ecom/products",
title: "Products",
icon: "mdi mdi-cards-variant",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/ecom/cart",
title: "Cart",
icon: "mdi mdi-cart",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/ecom/edit",
title: "Edit Products",
icon: "mdi mdi-cart-plus",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/ecom/details",
title: "Product Details",
icon: "mdi mdi-camera-burst",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/ecom/orders",
title: "Orders",
icon: "mdi mdi-chart-pie",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/ecom/checkout",
title: "Checkout",
icon: "mdi mdi-clipboard-check",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
],
},
{
path: "authentication",
title: "Authentication",
icon: "Lock",
class: "has-arrow",
extralink: false,
label: "",
labelClass: "",
submenu: [ submenu: [
{ {
path: '/component/accordion', path: "/authentication/login",
title: 'Accordion', title: "Login",
icon: 'mdi mdi-adjust', icon: "mdi mdi-account-key",
class: '', class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/authentication/login2",
title: "Login 2",
icon: "mdi mdi-account-key",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/authentication/signup",
title: "Register",
icon: "mdi mdi-account-plus",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/authentication/signup2",
title: "Register 2",
icon: "mdi mdi-account-plus",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/authentication/404",
title: "404",
icon: "mdi mdi-alert-outline",
class: "",
extralink: false, extralink: false,
submenu: [] label: "",
labelClass: "",
submenu: [],
}, },
{ {
path: '/component/alert', path: "/authentication/lock",
title: 'Alert', title: "Lockscreen",
icon: 'mdi mdi-adjust', icon: "mdi mdi-account-off",
class: '', class: "",
extralink: false, extralink: false,
submenu: [] label: "",
labelClass: "",
submenu: [],
}, },
],
},
{
path: "sample-pages",
title: "Sample Pages",
icon: "book-open",
class: "has-arrow",
extralink: false,
label: "",
labelClass: "",
submenu: [
{ {
path: '/component/carousel', path: "/sample-pages/profile",
title: 'Carousel', title: "Profile",
icon: 'mdi mdi-adjust', icon: "mdi mdi-account-network",
class: '', class: "",
extralink: false, extralink: false,
submenu: [] label: "",
labelClass: "",
submenu: [],
}, },
{ {
path: '/component/dropdown', path: "/sample-pages/pricing",
title: 'Dropdown', title: "Pricing",
icon: 'mdi mdi-adjust', icon: "mdi mdi-file-export",
class: '', class: "",
extralink: false, extralink: false,
submenu: [] label: "",
labelClass: "",
submenu: [],
}, },
{ {
path: '/component/modal', path: "/sample-pages/invoice",
title: 'Modal', title: "Invoice",
icon: 'mdi mdi-adjust', icon: "mdi mdi-ungroup",
class: '', class: "",
extralink: false, extralink: false,
submenu: [] label: "",
labelClass: "",
submenu: [],
}, },
{ {
path: '/component/pagination', path: "/sample-pages/helperclasses",
title: 'Pagination', title: "Helper Classes",
icon: 'mdi mdi-adjust', icon: "mdi mdi-tune",
class: '', class: "",
extralink: false, extralink: false,
submenu: [] label: "",
labelClass: "",
submenu: [],
}, },
{ {
path: '/component/poptool', path: "/starter",
title: 'Popover & Tooltip', title: "Starter Page",
icon: 'mdi mdi-adjust', icon: "mdi mdi-crop-free",
class: '', class: "",
extralink: false, extralink: false,
submenu: [] label: "",
labelClass: "",
submenu: [],
}, },
],
},
{
path: "timeline",
title: "Timeline",
icon: "Activity",
class: "has-arrow",
extralink: false,
label: "",
labelClass: "",
submenu: [
{ {
path: '/component/progressbar', path: "/timeline/left",
title: 'Progressbar', title: "Left Timeline",
icon: 'mdi mdi-adjust', icon: "mdi mdi-clock-fast",
class: '', class: "",
extralink: false, extralink: false,
submenu: [] label: "",
labelClass: "",
submenu: [],
}, },
{ {
path: '/component/rating', path: "/timeline/right",
title: 'Ratings', title: "Right Timeline",
icon: 'mdi mdi-adjust', icon: "mdi mdi-clock-end",
class: '', class: "",
extralink: false, extralink: false,
submenu: [] label: "",
labelClass: "",
submenu: [],
}, },
{ {
path: '/component/tabs', path: "/timeline/center",
title: 'Tabs', title: "Center Timeline",
icon: 'mdi mdi-adjust', icon: "mdi mdi-clock-in",
class: '', class: "",
extralink: false, extralink: false,
submenu: [] label: "",
labelClass: "",
submenu: [],
}, },
],
},
{
path: "icons",
title: "Icons",
icon: "Feather",
class: "has-arrow",
extralink: false,
label: "",
labelClass: "",
submenu: [
{ {
path: '/component/timepicker', path: "/icons/fontawesome",
title: 'Timepicker', title: "Fontawesome",
icon: 'mdi mdi-adjust', icon: "mdi mdi-emoticon-cool",
class: '', class: "",
extralink: false, extralink: false,
submenu: [] label: "",
labelClass: "",
submenu: [],
}, },
{ {
path: '/component/buttons', path: "/icons/simpleline",
title: 'Button', title: "Simple Line Icons",
icon: 'mdi mdi-adjust', icon: "mdi mdi mdi-image-broken-variant",
class: '', class: "",
extralink: false, extralink: false,
submenu: [] label: "",
labelClass: "",
submenu: [],
}, },
{ {
path: '/component/card', path: "/icons/material",
title: 'Card', title: "Material Icons",
icon: 'mdi mdi-adjust', icon: "mdi mdi-emoticon",
class: '', class: "",
extralink: false, extralink: false,
submenu: [] label: "",
labelClass: "",
submenu: [],
},
],
},
{
path: "mlevel",
title: "Menu Levels",
icon: "align-left",
class: "has-arrow",
extralink: false,
label: "",
labelClass: "",
submenu: [
{
path: "",
title: "Second Level",
icon: "mdi mdi-octagram",
class: "",
extralink: true,
label: "",
labelClass: "",
submenu: [],
}, },
{ {
path: '/component/notifier', path: "/second",
title: 'Notifier', title: "Second Child",
icon: 'mdi mdi-adjust', icon: "mdi mdi-octagram",
class: '', class: "has-arrow",
extralink: false, extralink: false,
submenu: [] label: "",
} labelClass: "",
] submenu: [
} {
path: "/thirdone",
title: "Third 1.1",
icon: "mdi mdi-playlist-plus",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
{
path: "/thirdtwo",
title: "Third 1.2",
icon: "mdi mdi-playlist-plus",
class: "",
extralink: false,
label: "",
labelClass: "",
submenu: [],
},
],
},
],
},
]; ];
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
<div class="user-pic"> <div class="user-pic">
<img src="assets/images/users/1.jpg" alt="users" class="rounded-circle" width="40" /> <img src="assets/images/users/1.jpg" alt="users" class="rounded-circle" width="40" />
</div> </div>
<div class="dropdown user-content hide-menu m-l-10" ngbDropdown placement="bottom-right"> <div class="dropdown user-content hide-menu m-l-10 overflow-inherit" ngbDropdown
placement="bottom-right">
<a ngbDropdownToggle href="javascript:void(0)" class="dropdown-toggle" id="Userdd" role="button" <a ngbDropdownToggle href="javascript:void(0)" class="dropdown-toggle" id="Userdd" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<h5 class="m-b-0 user-name font-medium">Steave Jobs <h5 class="m-b-0 user-name font-medium">Steave Jobs
...@@ -42,17 +43,19 @@ ...@@ -42,17 +43,19 @@
*ngFor="let sidebarnavItem of sidebarnavItems" *ngFor="let sidebarnavItem of sidebarnavItems"
(click)="sidebarnavItem.submenu.length != 0 ? '' : handleNotify()" (click)="sidebarnavItem.submenu.length != 0 ? '' : handleNotify()"
[routerLinkActive]="sidebarnavItem.submenu.length != 0 ? '' : 'active'"> [routerLinkActive]="sidebarnavItem.submenu.length != 0 ? '' : 'active'">
<div class="nav-small-cap" *ngIf="sidebarnavItem.extralink === true"> <div class="nav-small-cap" *ngIf="sidebarnavItem.extralink === true"><i
<i [ngClass]="[sidebarnavItem.icon]"></i> [ngClass]="[sidebarnavItem.icon]"></i><span class="hide-menu">{{sidebarnavItem.title |
<span class="hide-menu">{{sidebarnavItem.title | translate}}</span> translate}}</span></div>
</div>
<a class="sidebar-link waves-effect waves-dark" <a class="sidebar-link waves-effect waves-dark"
[routerLink]="sidebarnavItem.class === '' ? [sidebarnavItem.path] : null" [routerLink]="sidebarnavItem.class === '' ? [sidebarnavItem.path] : null"
[ngClass]="[sidebarnavItem.class]" *ngIf="!sidebarnavItem.extralink;" [ngClass]="[sidebarnavItem.class]" *ngIf="!sidebarnavItem.extralink;"
(click)="addExpandClass(sidebarnavItem.title)" (click)="addExpandClass(sidebarnavItem.title)"
[routerLinkActive]="sidebarnavItem.submenu.length != 0 ? '' : 'active'"> [routerLinkActive]="sidebarnavItem.submenu.length != 0 ? '' : 'active'">
<i-feather [name]="sidebarnavItem.icon" [ngClass]="[sidebarnavItem.icon]"></i-feather> <i-feather [name]="sidebarnavItem.icon" [ngClass]="[sidebarnavItem.icon]"></i-feather>
<span class="hide-menu">{{sidebarnavItem.title | translate}}</span> <span class="hide-menu">{{sidebarnavItem.title |translate}}
<span *ngIf="sidebarnavItem.label != '' "
[ngClass]="[sidebarnavItem.labelClass]">{{sidebarnavItem.label | translate}}</span>
</span>
</a> </a>
<!-- Second level menu --> <!-- Second level menu -->
<ul aria-expanded="false" class="collapse first-level" *ngIf="sidebarnavItem.submenu.length > 0" <ul aria-expanded="false" class="collapse first-level" *ngIf="sidebarnavItem.submenu.length > 0"
...@@ -67,7 +70,7 @@ ...@@ -67,7 +70,7 @@
[ngClass]="[sidebarnavSubItem.class]" *ngIf="!sidebarnavSubItem.extralink;" [ngClass]="[sidebarnavSubItem.class]" *ngIf="!sidebarnavSubItem.extralink;"
(click)="addActiveClass(sidebarnavSubItem.title)"> (click)="addActiveClass(sidebarnavSubItem.title)">
<i [ngClass]="[sidebarnavSubItem.icon]"></i> <i [ngClass]="[sidebarnavSubItem.icon]"></i>
<span class="hide-menu">{{sidebarnavSubItem.title | translate}}</span> <span class="hide-menu">{{sidebarnavSubItem.title| translate}}</span>
</a> </a>
<!-- Third level menu --> <!-- Third level menu -->
<ul aria-expanded="false" class="collapse Second-level" *ngIf="sidebarnavSubItem.submenu.length > 0" <ul aria-expanded="false" class="collapse Second-level" *ngIf="sidebarnavSubItem.submenu.length > 0"
...@@ -78,7 +81,7 @@ ...@@ -78,7 +81,7 @@
*ngIf="!sidebarnavSubsubItem.extralink;" *ngIf="!sidebarnavSubsubItem.extralink;"
[routerLinkActive]="sidebarnavSubsubItem.submenu.length > 0 ? '' : 'router-link-active'"> [routerLinkActive]="sidebarnavSubsubItem.submenu.length > 0 ? '' : 'router-link-active'">
<i [ngClass]="[sidebarnavSubsubItem.icon]"></i> <i [ngClass]="[sidebarnavSubsubItem.icon]"></i>
<span class="hide-menu">{{sidebarnavSubsubItem.title | translate}}</span> <span class="hide-menu">{{sidebarnavSubsubItem.title| translate}}</span>
</a> </a>
</li> </li>
</ul> </ul>
......
...@@ -5,5 +5,7 @@ export interface RouteInfo { ...@@ -5,5 +5,7 @@ export interface RouteInfo {
icon: string; icon: string;
class: string; class: string;
extralink: boolean; extralink: boolean;
label: string;
labelClass: string;
submenu: RouteInfo[]; submenu: RouteInfo[];
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment