first commit
This commit is contained in:
41
src/app/content/advance-cards/advance-cards.module.ts
Normal file
41
src/app/content/advance-cards/advance-cards.module.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { StatisticsComponent } from './statistics/statistics.component';
|
||||
import { ChartistModule } from 'ng-chartist';
|
||||
import { SocialComponent } from './social/social.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { NgChartsModule } from 'ng2-charts';
|
||||
import { BreadcrumbModule } from 'src/app/_layout/breadcrumb/breadcrumb.module';
|
||||
import { ChartsComponent } from './charts/charts.component';
|
||||
import { CardModule } from '../partials/general/card/card.module';
|
||||
import { MatchHeightModule } from '../partials/general/match-height/match-height.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
NgbModule,
|
||||
ChartistModule,
|
||||
CardModule,
|
||||
NgChartsModule,
|
||||
BreadcrumbModule,
|
||||
MatchHeightModule,
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'statistics',
|
||||
component: StatisticsComponent
|
||||
},
|
||||
{
|
||||
path: 'social',
|
||||
component: SocialComponent
|
||||
},
|
||||
{
|
||||
path: 'charts',
|
||||
component: ChartsComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
declarations: [StatisticsComponent, SocialComponent, ChartsComponent],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AdvanceCardsModule {}
|
||||
159
src/app/content/advance-cards/charts/charts.component.css
Normal file
159
src/app/content/advance-cards/charts/charts.component.css
Normal file
@@ -0,0 +1,159 @@
|
||||
:host ::ng-deep .areaChartLegend .ct-series-a .ct-line {
|
||||
stroke:#1e9ff2;
|
||||
}
|
||||
:host ::ng-deep .areaChartLegend .ct-series-a .ct-line {
|
||||
stroke: url(#gradient1);
|
||||
stroke-width: 5px;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
:host ::ng-deep .areaChartLegend {
|
||||
-webkit-filter: drop-shadow(0px 20px 11px rgba(0, 0, 0, 0.5)) !important;
|
||||
filter: drop-shadow(0px 20px 11px rgba(0, 0, 0, 0.5));
|
||||
}
|
||||
:host ::ng-deep .areaChartLegend .ct-series-a .ct-area {
|
||||
fill: #ffffff;
|
||||
}
|
||||
:host ::ng-deep .areaChartLegend .ct-series-a .ct-line {
|
||||
stroke: #3da2ea;
|
||||
}
|
||||
|
||||
:host ::ng-deep .earningchart .ct-series-a .ct-line {
|
||||
stroke: #FF4961;
|
||||
}
|
||||
:host ::ng-deep .earningchart .ct-series-a .ct-point-circle {
|
||||
stroke-width: 3px;
|
||||
stroke: #FF4961;
|
||||
fill: #ffffff;
|
||||
}
|
||||
:host ::ng-deep .barchart .ct-series-a .ct-bar {
|
||||
stroke: #ff394f !important;
|
||||
stroke-width: 7px !important;
|
||||
}
|
||||
:host ::ng-deep .Revenuechartist .ct-series-a .ct-line {
|
||||
|
||||
stroke: url(#gradient2);
|
||||
stroke-linecap: round;
|
||||
}
|
||||
:host ::ng-deep .Revenuechartist {
|
||||
filter: drop-shadow(0px 20px 11px rgba(252, 198, 198, 0.8)) !important;
|
||||
|
||||
}
|
||||
:host ::ng-deep .Revenuechartist .ct-grid{
|
||||
stroke-dasharray: 0px;
|
||||
stroke: rgba(0, 0, 0, 0.4);
|
||||
stroke-width: 0.6px;
|
||||
}
|
||||
:host ::ng-deep .Revenuechartist .ct-series-a .ct-line {
|
||||
stroke: #ff4961;
|
||||
}
|
||||
:host ::ng-deep .Revenuechartist .ct-series-b .ct-line {
|
||||
stroke: #c8c2c3;
|
||||
stroke-dasharray: 8px 3px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .Revenuechartist .ct-label.ct-vertical.ct-start {
|
||||
font-weight: 600;
|
||||
color: #636161;
|
||||
font-size: 12px;
|
||||
}
|
||||
:host ::ng-deep .ecommercesaleslineArea .ct-series-a .ct-point-circle {
|
||||
stroke-width: 5px;
|
||||
stroke: #ffffff;
|
||||
fill: #1e9ff2;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ecommercesaleslineArea .ct-series-b .ct-point-circle {
|
||||
stroke-width: 5px;
|
||||
stroke: #ffffff;
|
||||
fill: #58e0cd;
|
||||
;
|
||||
}
|
||||
:host ::ng-deep .ecommercesaleslineArea .ct-series-a .ct-area {
|
||||
fill: #4105f9f5;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ecommercesaleslineArea .ct-series-b .ct-area {
|
||||
fill: #03f7b2fa;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ecommercesaleslineArea .ct-series-b .ct-line {
|
||||
stroke: #58e0cd;
|
||||
}
|
||||
:host ::ng-deep .ecommercesaleslineArea .ct-series-a .ct-line {
|
||||
stroke: #1e9ff2;
|
||||
}
|
||||
:host ::ng-deep .donut-chart2{
|
||||
margin-bottom: -25px;
|
||||
margin-top: -17px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart2 .ct-series-a .ct-slice-donut {
|
||||
stroke: #28d094;
|
||||
stroke-width: 5.5px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart2 .ct-series-b .ct-slice-donut {
|
||||
stroke: #ff4961;
|
||||
stroke-width: 5.5px !important;
|
||||
}
|
||||
:host ::ng-deep .donut-chart2 {
|
||||
-webkit-filter: drop-shadow(0px 10px 11px rgba(187,187,187)) !important;
|
||||
filter: drop-shadow(0px 10px 11px rgba(187,187,187));
|
||||
height: 288px;
|
||||
}
|
||||
:host ::ng-deep .donut-chart2 .ct-label {
|
||||
fill: #ff4b62;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
font-size: 1.75rem;
|
||||
line-height: 1;
|
||||
}
|
||||
:host ::ng-deep .donut-chart1 {
|
||||
margin-bottom: -25px;
|
||||
margin-top: -17px;
|
||||
height: 288px;
|
||||
}
|
||||
:host ::ng-deep .donut-chart1 .ct-series-a .ct-slice-donut {
|
||||
stroke: #ff7889;
|
||||
stroke-width: 5.5px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart1 .ct-series-b .ct-slice-donut {
|
||||
stroke: #ffffff;
|
||||
stroke-width: 5.5px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart1 .ct-label {
|
||||
fill: #ffffff;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
font-size: 1.75rem;
|
||||
line-height: 1;
|
||||
}
|
||||
:host ::ng-deep .donut .ct-done .ct-slice-donut {
|
||||
stroke: #28d094;
|
||||
stroke-width: 24px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut .ct-progress .ct-slice-donut {
|
||||
stroke: #ff4558;
|
||||
stroke-width: 16px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut .ct-outstanding .ct-slice-donut {
|
||||
stroke: #ff7d4d;
|
||||
stroke-width: 8px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut .ct-started .ct-slice-donut {
|
||||
stroke: #666ECC;
|
||||
stroke-width: 32px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut .ct-label {
|
||||
text-anchor: middle;
|
||||
font-size: 20px;
|
||||
fill: #868e96;
|
||||
}
|
||||
|
||||
:host ::ng-deep .dountchartheader{
|
||||
margin-top: 10px;
|
||||
}
|
||||
194
src/app/content/advance-cards/charts/charts.component.html
Normal file
194
src/app/content/advance-cards/charts/charts.component.html
Normal file
@@ -0,0 +1,194 @@
|
||||
<div class="app-content content">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<!-- Charts section start -->
|
||||
<section id="charts-section">
|
||||
<div class="row">
|
||||
<div class="col-12 mt-3 mb-1">
|
||||
<h4 class="text-uppercase">Charts</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" matchHeight="card">
|
||||
<div class="col-xl-4 col-lg-12">
|
||||
<div class="card text-white">
|
||||
<div class="card-content">
|
||||
<div class="position-relative">
|
||||
<div class="chart-title position-absolute mt-2 ml-2 white">
|
||||
</div>
|
||||
<div class="earningchart">
|
||||
<x-chartist *ngIf="earningchart" [data]="earningchart.data" [type]="earningchart.type" [options]="earningchart.options"
|
||||
[responsiveOptions]="earningchart.responsiveOptions" [events]="earningchart.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
<div class="chart-stats position-absolute position-bottom-0 position-right-0 mb-2 mr-3">
|
||||
<a href="#" class="btn bg-danger mr-1 white">Statistics <i class="feather ft-bar-chart"></i></a> <span
|
||||
class="text-muted">for the <a href="#" class="danger darken-2">last year.</a></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-8 col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="row">
|
||||
<div class="card-body">
|
||||
<ul class="list-inline text-center">
|
||||
<li class="mr-1">
|
||||
<h6><i class="la la-circle danger"></i> <span>iOS</span></h6>
|
||||
</li>
|
||||
<li class="mr-1">
|
||||
<h6><i class="la la-circle warning"></i> <span>Windows</span></h6>
|
||||
</li>
|
||||
<li class="mr-1">
|
||||
<h6><i class="la la-circle success"></i> <span>Android</span></h6>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="areaChartLegend">
|
||||
<x-chartist *ngIf="lineArea" [data]="lineArea.data" [type]="lineArea.type" [options]="lineArea.options"
|
||||
[responsiveOptions]="lineArea.responsiveOptions" [events]="lineArea.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" matchHeight="card">
|
||||
<div class="col-xl-4 col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="earning-chart position-relative">
|
||||
<div class="chart-title position-absolute mt-2 ml-2">
|
||||
</div>
|
||||
<p class="font-medium-2 text-muted text-center dountchartheader">Project Tasks</p>
|
||||
<div class="donut">
|
||||
<x-chartist class="pr_stats" *ngIf="DonutChart" [data]="DonutChart.data" [type]="DonutChart.type"
|
||||
[options]="DonutChart.options" [responsiveOptions]="DonutChart.responsiveOptions"
|
||||
[events]="DonutChart.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-lg-12">
|
||||
<m-card [options]="hitRateOptions" id="card">
|
||||
<ng-container mCardHeaderTitle>
|
||||
Hit Rate <span class="danger">-12%</span>
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<div id="donut-chart2" class="height-230 donut-chart2">
|
||||
<x-chartist *ngIf="donutChart2" [data]="donutChart2.data" [type]="donutChart2.type" [options]="donutChart2.options"
|
||||
[responsiveOptions]="donutChart2.responsiveOptions" [events]="donutChart2.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
<div class="col-xl-4 col-lg-12">
|
||||
<m-card [options]="dealsOptions">
|
||||
<ng-container mCardBody>
|
||||
<h4 class="card-title white">Deals <span class="white">-55%</span>
|
||||
<span class="float-right">
|
||||
<span class="white">152</span><span class="red lighten-4">/200</span>
|
||||
</span>
|
||||
</h4>
|
||||
<div id="donut-chart1" class="height-230 donut-chart1">
|
||||
<x-chartist *ngIf="donutChart1" [data]="donutChart1.data" [type]="donutChart1.type" [options]="donutChart1.options"
|
||||
[responsiveOptions]="donutChart1.responsiveOptions" [events]="donutChart1.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" matchHeight="card">
|
||||
<div class="col-xl-4 col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card-body sales-growth-chart">
|
||||
<div class="barchart">
|
||||
<x-chartist *ngIf="barChart" [data]="barChart.data" [type]="barChart.type" [options]="barChart.options"
|
||||
[responsiveOptions]="barChart.responsiveOptions" [events]="barChart.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-8 col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="Revenuechartist">
|
||||
<x-chartist *ngIf="lineArea1" [data]="lineArea1.data" [type]="lineArea1.type" [options]="lineArea1.options"
|
||||
[responsiveOptions]="lineArea1.responsiveOptions" [events]="lineArea1.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" matchHeight="card">
|
||||
<div class="col-xl-12 col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-content ">
|
||||
<div id="cost-revenue" class="ecommercesaleslineArea position-relative">
|
||||
<x-chartist *ngIf="ecommercesaleslineArea" [data]="ecommercesaleslineArea.data" [type]="ecommercesaleslineArea.type"
|
||||
[options]="ecommercesaleslineArea.options"
|
||||
[responsiveOptions]="ecommercesaleslineArea.responsiveOptions"
|
||||
[events]="ecommercesaleslineArea.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<div class="row mt-1">
|
||||
<div class="col-3 text-center">
|
||||
<h6 class="text-muted">Total Products</h6>
|
||||
<h2 class="block font-weight-normal">18.6 k</h2>
|
||||
<div class="progress progress-sm mt-1 mb-0 box-shadow">
|
||||
<div class="progress-bar bg-gradient-x-info" role="progressbar" style="width: 70%"
|
||||
aria-valuenow="70" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3 text-center">
|
||||
<h6 class="text-muted">Total Sales</h6>
|
||||
<h2 class="block font-weight-normal">64.54 M</h2>
|
||||
<div class="progress progress-sm mt-1 mb-0 box-shadow">
|
||||
<div class="progress-bar bg-gradient-x-warning" role="progressbar" style="width: 60%"
|
||||
aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3 text-center">
|
||||
<h6 class="text-muted">Total Cost</h6>
|
||||
<h2 class="block font-weight-normal">24.38 B</h2>
|
||||
<div class="progress progress-sm mt-1 mb-0 box-shadow">
|
||||
<div class="progress-bar bg-gradient-x-danger" role="progressbar" style="width: 40%"
|
||||
aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3 text-center">
|
||||
<h6 class="text-muted">Total Revenue</h6>
|
||||
<h2 class="block font-weight-normal">36.72 M</h2>
|
||||
<div class="progress progress-sm mt-1 mb-0 box-shadow">
|
||||
<div class="progress-bar bg-gradient-x-success" role="progressbar" style="width: 90%"
|
||||
aria-valuenow="90" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- // Charts section end -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END: Content-->
|
||||
@@ -0,0 +1,24 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { ChartsComponent } from './charts.component';
|
||||
|
||||
describe('ChartsComponent', () => {
|
||||
let component: ChartsComponent;
|
||||
let fixture: ComponentFixture<ChartsComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ChartsComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ChartsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
472
src/app/content/advance-cards/charts/charts.component.ts
Normal file
472
src/app/content/advance-cards/charts/charts.component.ts
Normal file
@@ -0,0 +1,472 @@
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import * as Chartist from 'chartist';
|
||||
import { ChartEvent, ChartType } from 'ng-chartist';
|
||||
import { ChartApiService } from '../../../_services/chart.api';
|
||||
|
||||
|
||||
export interface Chart {
|
||||
type: ChartType;
|
||||
data: Chartist.IChartistData;
|
||||
options?: any;
|
||||
responsiveOptions?: any;
|
||||
events?: ChartEvent;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-charts',
|
||||
templateUrl: './charts.component.html',
|
||||
styleUrls: ['./charts.component.css']
|
||||
})
|
||||
export class ChartsComponent implements OnInit {
|
||||
public breadcrumb: any;
|
||||
salesData: any;
|
||||
ChartistData: any;
|
||||
lineArea: any;
|
||||
earningchart: any;
|
||||
DonutChart: any;
|
||||
barChart: any;
|
||||
lineArea1: any;
|
||||
ecommercesaleslineArea: any;
|
||||
donutChart2: any;
|
||||
donutChart1: any;
|
||||
constructor(private chartApiservice: ChartApiService) { }
|
||||
hitRateOptions = {
|
||||
bodyClass: ['bg-hexagons', 'pt-0'],
|
||||
headerClass: ['bg-hexagons'],
|
||||
cardClass: ['pull-up'],
|
||||
close: false,
|
||||
expand: false,
|
||||
minimize: false,
|
||||
reload: true
|
||||
};
|
||||
dealsOptions = {
|
||||
bodyClass: ['bg-hexagons-danger'],
|
||||
cardClass: ['pull-up'],
|
||||
contentClass: ['bg-gradient-directional-danger']
|
||||
};
|
||||
getlineArea() {
|
||||
const Chartdata = this.ChartistData;
|
||||
this.lineArea = {
|
||||
type: 'Line',
|
||||
data: Chartdata['lineArea'],
|
||||
options: {
|
||||
lineSmooth: Chartist.Interpolation.simple({
|
||||
divisor: 1.8
|
||||
}),
|
||||
fullwidth: true,
|
||||
height: '320px',
|
||||
low: 0,
|
||||
showArea: true,
|
||||
fullWidth: true,
|
||||
showPoint: false,
|
||||
axisX: {
|
||||
showGrid: false
|
||||
},
|
||||
axisY: {
|
||||
low: 0,
|
||||
offset: 16,
|
||||
scaleMinSpace: 40,
|
||||
labelInterpolationFnc: function (value) {
|
||||
return value + 'K';
|
||||
}
|
||||
}
|
||||
},
|
||||
responsiveOptions: [
|
||||
[
|
||||
'screen and (max-width: 640px) and (min-width: 200px)',
|
||||
{
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
'screen and (max-width: 380px)',
|
||||
{
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 3 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
events: {
|
||||
created(data: any): void {
|
||||
const defs = data.svg.elem('defs');
|
||||
defs
|
||||
.elem('linearGradient', {
|
||||
id: 'gradient1',
|
||||
x1: 1,
|
||||
y1: 1,
|
||||
x2: 1,
|
||||
y2: 1
|
||||
})
|
||||
.elem('stop', {
|
||||
offset: 0,
|
||||
'stop-color': 'rgba(22, 141, 238, 1)'
|
||||
})
|
||||
.parent()
|
||||
.elem('stop', {
|
||||
offset: 1,
|
||||
'stop-color': 'rgba(98, 188, 270, 11)'
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.DonutChart = {
|
||||
type: 'Pie',
|
||||
data: Chartdata['donutDashboard'],
|
||||
options: {
|
||||
width: '100%',
|
||||
height: '280px',
|
||||
donut: true,
|
||||
startAngle: 0,
|
||||
labelInterpolationFnc: function (value) {
|
||||
const total = Chartdata['donutDashboard'].series.reduce(function (
|
||||
prev,
|
||||
series
|
||||
) {
|
||||
return prev + series.value;
|
||||
},
|
||||
0);
|
||||
return total + '%';
|
||||
}
|
||||
},
|
||||
events: {
|
||||
draw(data: any): void {
|
||||
if (data.type === 'label') {
|
||||
if (data.index === 0) {
|
||||
data.element.attr({
|
||||
dx: data.element.root().width() / 2,
|
||||
dy: data.element.root().height() / 2
|
||||
});
|
||||
} else {
|
||||
data.element.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
this.barChart = {
|
||||
type: 'Bar',
|
||||
data: Chartdata['Bar'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
height: '320px',
|
||||
seriesBarDistance: 21,
|
||||
chartPadding: {
|
||||
top: 0
|
||||
},
|
||||
axisX: {
|
||||
showLable: true,
|
||||
showGrid: false,
|
||||
offset: 60,
|
||||
labelInterpolationFnc: function (value) {
|
||||
return value.slice(0, 3);
|
||||
}
|
||||
},
|
||||
|
||||
axisY: {
|
||||
scaleMinSpace: 40
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.ecommercesaleslineArea = {
|
||||
type: 'Line',
|
||||
data: Chartdata['lineArea2'],
|
||||
options: {
|
||||
height: '300px',
|
||||
low: 0,
|
||||
showArea: true,
|
||||
fullWidth: true,
|
||||
onlyInteger: true,
|
||||
axisX: {
|
||||
showGrid: false
|
||||
},
|
||||
axisY: {
|
||||
low: 0,
|
||||
scaleMinSpace: 40,
|
||||
showGrid: false
|
||||
}
|
||||
},
|
||||
responsiveOptions: [
|
||||
[
|
||||
'screen and (max-width: 640px) and (min-width: 381px)',
|
||||
{
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
'screen and (max-width: 380px)',
|
||||
{
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 3 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
events: {
|
||||
draw(data: any): void {
|
||||
const circleRadius = 6;
|
||||
if (data.type === 'point') {
|
||||
const circle = new Chartist.Svg('circle', {
|
||||
cx: data.x,
|
||||
cy: data.y,
|
||||
r: circleRadius,
|
||||
class: 'ct-point-circle'
|
||||
});
|
||||
data.element.replace(circle);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
getChartData() {
|
||||
const SaleschartData = this.salesData;
|
||||
this.earningchart = {
|
||||
type: 'Line',
|
||||
data: SaleschartData['earningchart'],
|
||||
options: {
|
||||
chartPadding: 0,
|
||||
height: '440px',
|
||||
low: 0,
|
||||
showArea: true,
|
||||
fullWidth: true,
|
||||
onlyInteger: true,
|
||||
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
showLabel: false,
|
||||
offset: -1
|
||||
},
|
||||
axisY: {
|
||||
scaleMinSpace: 40,
|
||||
showGrid: false,
|
||||
showLabel: false,
|
||||
offset: -2
|
||||
}
|
||||
},
|
||||
responsiveOptions: [
|
||||
[
|
||||
'screen and (max-width: 640px) and (min-width: 381px)',
|
||||
{
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
'screen and (max-width: 380px)',
|
||||
{
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 3 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
events: {
|
||||
created(data: any): void {
|
||||
const defs = data.svg.elem('defs');
|
||||
defs
|
||||
.elem('linearGradient', {
|
||||
id: 'gradient1',
|
||||
x1: 0,
|
||||
y1: 0,
|
||||
x2: 1,
|
||||
y2: 0
|
||||
})
|
||||
.elem('stop', {
|
||||
offset: 0,
|
||||
'stop-color': 'rgb(255,73,97)'
|
||||
})
|
||||
.parent()
|
||||
.elem('stop', {
|
||||
offset: 1,
|
||||
'stop-color': 'rgb(255,73,97)'
|
||||
});
|
||||
},
|
||||
draw(data: any): void {
|
||||
const circleRadius = 6;
|
||||
if (data.type === 'point') {
|
||||
const circle = new Chartist.Svg('circle', {
|
||||
cx: data.x,
|
||||
cy: data.y,
|
||||
r: circleRadius,
|
||||
class: 'ct-point-circle'
|
||||
});
|
||||
data.element.replace(circle);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
this.lineArea1 = {
|
||||
type: 'Line',
|
||||
data: SaleschartData['lineArea'],
|
||||
|
||||
options: {
|
||||
lineSmooth: Chartist.Interpolation.simple({
|
||||
divisor: 2.8
|
||||
}),
|
||||
fullWidth: true,
|
||||
height: '320px',
|
||||
showArea: false,
|
||||
showPoint: false,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
showLabel: true,
|
||||
offset: 32
|
||||
},
|
||||
axisY: {
|
||||
showGrid: true,
|
||||
showLabel: true,
|
||||
scaleMinSpace: 28,
|
||||
offset: 44
|
||||
}
|
||||
},
|
||||
events: {
|
||||
created(data: any): void {
|
||||
const defs = data.svg.elem('defs');
|
||||
defs
|
||||
.elem('linearGradient', {
|
||||
id: 'gradient2',
|
||||
x1: 0,
|
||||
y1: 0,
|
||||
x2: 1,
|
||||
y2: 0
|
||||
})
|
||||
.elem('stop', {
|
||||
offset: 0,
|
||||
'stop-color': 'rgb(255,73,97)'
|
||||
})
|
||||
.parent()
|
||||
.elem('stop', {
|
||||
offset: 1,
|
||||
'stop-color': 'rgb(255,73,97)'
|
||||
});
|
||||
},
|
||||
draw(data: any): void {
|
||||
const circleRadius = 4;
|
||||
if (data.type === 'point') {
|
||||
const circle = new Chartist.Svg('circle', {
|
||||
cx: data.x,
|
||||
cy: data.y,
|
||||
r: circleRadius,
|
||||
class: 'ct-point-circle'
|
||||
});
|
||||
data.element.replace(circle);
|
||||
} else if (data.type === 'label') {
|
||||
// adjust label position for rotation
|
||||
const dX = data.width / 2 + (26 - data.width);
|
||||
data.element.attr({ x: data.element.attr('x') - dX });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
this.donutChart2 = {
|
||||
type: 'Pie',
|
||||
data: SaleschartData['donut1'],
|
||||
options: {
|
||||
chartPadding: 0,
|
||||
fullwidth: true,
|
||||
height: '273px',
|
||||
donut: true,
|
||||
showLabel: true,
|
||||
startAngle: 0,
|
||||
labelInterpolationFnc: function (value) {
|
||||
const total = 82;
|
||||
return total + '%';
|
||||
}
|
||||
},
|
||||
events: {
|
||||
draw(data: any): void {
|
||||
if (data.type === 'label') {
|
||||
if (data.index === 0) {
|
||||
data.element.attr({
|
||||
dx: data.element.root().width() / 2,
|
||||
dy: data.element.root().height() / 2
|
||||
});
|
||||
} else {
|
||||
data.element.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
this.donutChart1 = {
|
||||
type: 'Pie',
|
||||
data: SaleschartData['donut2'],
|
||||
options: {
|
||||
chartPadding: 0,
|
||||
fullwidth: true,
|
||||
height: '273px',
|
||||
donut: true,
|
||||
showLabel: true,
|
||||
labelInterpolationFnc: function (value) {
|
||||
const total = 76;
|
||||
return total + '%';
|
||||
}
|
||||
},
|
||||
events: {
|
||||
draw(data: any): void {
|
||||
if (data.type === 'label') {
|
||||
if (data.index === 0) {
|
||||
data.element.attr({
|
||||
dx: data.element.root().width() / 2,
|
||||
dy: data.element.root().height() / 2
|
||||
});
|
||||
} else {
|
||||
data.element.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
ngOnInit() {
|
||||
this.breadcrumb = {
|
||||
mainlabel: 'Advance Charts Cards',
|
||||
links: [
|
||||
{
|
||||
name: 'Home',
|
||||
isLink: true,
|
||||
link: '/dashboard/sales'
|
||||
},
|
||||
{
|
||||
name: 'Advance Cards',
|
||||
isLink: true,
|
||||
link: '#'
|
||||
},
|
||||
{
|
||||
name: 'Charts',
|
||||
isLink: false,
|
||||
link: '#'
|
||||
}
|
||||
]
|
||||
};
|
||||
this.chartApiservice.getSalesData().subscribe(Response => {
|
||||
this.salesData = Response;
|
||||
this.getChartData();
|
||||
});
|
||||
this.chartApiservice.getEcommerceData().subscribe(Response => {
|
||||
this.ChartistData = Response;
|
||||
this.getlineArea();
|
||||
});
|
||||
}
|
||||
}
|
||||
206
src/app/content/advance-cards/social/social.component.html
Normal file
206
src/app/content/advance-cards/social/social.component.html
Normal file
@@ -0,0 +1,206 @@
|
||||
<div class="app-content content">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<!-- Social cards section start -->
|
||||
<section id="social-cards">
|
||||
<div class="row">
|
||||
<div class="col-12 mt-3 mb-1">
|
||||
<h4 class="text-uppercase">Social Cards</h4>
|
||||
<p>User's social profile cards with followers - following numbers and follow button.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<div class="col-xl-4 col-md-6 col-12">
|
||||
<div class="card profile-card-with-cover">
|
||||
<div class="card-content">
|
||||
<div class="card-img-top img-fluid bg-cover height-200"
|
||||
style="background: url('../../../../../assets/images/backgrounds/fb.jpg') 0 30%;"></div>
|
||||
<div class="card-profile-image">
|
||||
<img src="../../../../../assets/images/portrait/small/avatar-s-4.png"
|
||||
class="rounded-circle img-border box-shadow-1" alt="Card image">
|
||||
</div>
|
||||
<div class="profile-card-with-cover-content text-center">
|
||||
<div class="profile-details mt-2">
|
||||
<h4 class="card-title">Linda Holland</h4>
|
||||
<ul class="list-inline clearfix mt-2">
|
||||
<li class="mr-3">
|
||||
<h2 class="block">3.5K</h2> Likes
|
||||
</li>
|
||||
<li class="mr-3">
|
||||
<h2 class="block">2845</h2> Followers
|
||||
</li>
|
||||
<li>
|
||||
<h2 class="block">645</h2> Following
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<a [routerLink]="" class="btn btn-social btn-min-width mr-1 mb-1 btn-facebook"><i
|
||||
class="la la-facebook"></i> Follow</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-md-6 col-12">
|
||||
<div class="card profile-card-with-cover">
|
||||
<div class="card-content">
|
||||
<div class="card-img-top img-fluid bg-cover height-200"
|
||||
style="background: url('../../../../../assets/images/backgrounds/in.jpg') 0 40%;"></div>
|
||||
<div class="card-profile-image">
|
||||
<img src="../../../../../assets/images/portrait/small/avatar-s-9.png"
|
||||
class="rounded-circle img-border box-shadow-1" alt="Card image">
|
||||
</div>
|
||||
<div class="profile-card-with-cover-content text-center">
|
||||
<div class="profile-details mt-2">
|
||||
<h4 class="card-title">Philip Garrett</h4>
|
||||
<ul class="list-inline clearfix mt-2">
|
||||
<li class="mr-3">
|
||||
<h2 class="block">500+</h2> Connections
|
||||
</li>
|
||||
<li class="mr-3">
|
||||
<h2 class="block">485</h2> Posts
|
||||
</li>
|
||||
<li>
|
||||
<h2 class="block">35</h2> Following
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<a [routerLink]="" class="btn btn-social btn-min-width mr-1 mb-1 btn-linkedin"><span
|
||||
class="la la-linkedin"></span> Follow</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-md-6 col-12">
|
||||
<div class="card profile-card-with-cover">
|
||||
<div class="card-content">
|
||||
<div class="card-img-top img-fluid bg-cover height-200"
|
||||
style="background: url('../../../../../assets/images/backgrounds/tw.jpg') 0 30%;"></div>
|
||||
<div class="card-profile-image">
|
||||
<img src="../../../../../assets/images/portrait/small/avatar-s-8.png"
|
||||
class="rounded-circle img-border box-shadow-1" alt="Card image">
|
||||
</div>
|
||||
<div class="profile-card-with-cover-content text-center">
|
||||
<div class="profile-details mt-2">
|
||||
<h4 class="card-title">Christine Wood</h4>
|
||||
<ul class="list-inline clearfix mt-2">
|
||||
<li class="mr-3">
|
||||
<h2 class="block">1.6K</h2> Likes
|
||||
</li>
|
||||
<li class="mr-3">
|
||||
<h2 class="block">264</h2> Followers
|
||||
</li>
|
||||
<li>
|
||||
<h2 class="block">85</h2> Following
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<a [routerLink]="" class="btn btn-social btn-min-width mr-1 mb-1 btn-twitter white"><span
|
||||
class="la la-twitter"></span> Follow</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-4 col-md-12">
|
||||
<div class="card bg-twitter white">
|
||||
<div class="card-content p-2">
|
||||
<div class="card-body">
|
||||
<div class="text-center mb-1">
|
||||
<i class="la la-twitter font-large-3"></i>
|
||||
</div>
|
||||
<div class="tweet-slider carousel slide text-center" data-ride="carousel">
|
||||
<div class="carousel-inner">
|
||||
<div class="carousel-item active">
|
||||
<p>Congratulations to Rob Jones in accounting for winning our <span class="yellow">#NFL</span>
|
||||
football pool!</p>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<p>Contests are a great thing to partner on. Partnerships immediately <span
|
||||
class="yellow">#DOUBLE</span> the reach.</p>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<p>Puns, humor, and quotes are great content on <span class="yellow">#Twitter</span>. Find some
|
||||
related to your business.</p>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<p>Are there <span class="yellow">#common-sense</span> facts related to your business? Combine
|
||||
them with a great photo.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4 col-md-12">
|
||||
<div class="card bg-facebook white">
|
||||
<div class="card-content p-2">
|
||||
<div class="card-body">
|
||||
<div class="text-center mb-1">
|
||||
<i class="la la-facebook font-large-3"></i>
|
||||
</div>
|
||||
<div class="fb-post-slider carousel slide text-center" data-ride="carousel">
|
||||
<div class="carousel-inner">
|
||||
<div class="carousel-item active">
|
||||
<p>Congratulations to Rob Jones in accounting for winning our #NFL football pool!</p>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<p>Contests are a great thing to partner on. Partnerships immediately #DOUBLE the reach.</p>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<p>Puns, humor, and quotes are great content on #Twitter. Find some related to your business.
|
||||
</p>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<p>Are there #common-sense facts related to your business? Combine them with a great photo.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4 col-md-12">
|
||||
<div class="card bg-linkedin white">
|
||||
<div class="card-content p-2">
|
||||
<div class="card-body">
|
||||
<div class="text-center mb-1">
|
||||
<i class="la la-linkedin font-large-3"></i>
|
||||
</div>
|
||||
<div class="linkedin-post-slider carousel slide text-center" data-ride="carousel">
|
||||
<div class="carousel-inner">
|
||||
<div class="carousel-item active">
|
||||
<p>Congratulations to Rob Jones in accounting for winning our #NFL football pool!</p>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<p>Contests are a great thing to partner on. Partnerships immediately #DOUBLE the reach.</p>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<p>Puns, humor, and quotes are great content on #Twitter. Find some related to your business.
|
||||
</p>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<p>Are there #common-sense facts related to your business? Combine them with a great photo.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- // Social cards section end -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,24 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { SocialComponent } from './social.component';
|
||||
|
||||
describe('SocialComponent', () => {
|
||||
let component: SocialComponent;
|
||||
let fixture: ComponentFixture<SocialComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [SocialComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SocialComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
35
src/app/content/advance-cards/social/social.component.ts
Normal file
35
src/app/content/advance-cards/social/social.component.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-social',
|
||||
templateUrl: './social.component.html',
|
||||
styleUrls: ['./social.component.css']
|
||||
})
|
||||
export class SocialComponent implements OnInit {
|
||||
public breadcrumb: any;
|
||||
|
||||
constructor() {}
|
||||
|
||||
ngOnInit() {
|
||||
this.breadcrumb = {
|
||||
mainlabel: 'Advance Social Cards',
|
||||
links: [
|
||||
{
|
||||
name: 'Home',
|
||||
isLink: true,
|
||||
link: '/dashboard/sales'
|
||||
},
|
||||
{
|
||||
name: 'Advance Cards',
|
||||
isLink: true,
|
||||
link: '#'
|
||||
},
|
||||
{
|
||||
name: 'Social',
|
||||
isLink: false,
|
||||
link: '#'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
:host ::ng-deep .Likes .ct-series-a .ct-point {
|
||||
stroke: #28d094;
|
||||
}
|
||||
:host ::ng-deep .Likes .ct-line {
|
||||
fill: none;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
:host ::ng-deep .Likes .ct-point{
|
||||
stroke-width: 0px;
|
||||
}
|
||||
:host ::ng-deep .Likes .ct-series-a .ct-line {
|
||||
stroke: #28d094;
|
||||
}
|
||||
:host ::ng-deep .Likes .ct-series-a .ct-area {
|
||||
fill: #28d094;
|
||||
}
|
||||
:host ::ng-deep .Comments .ct-series-a .ct-point {
|
||||
stroke: #FF9149;
|
||||
}
|
||||
:host ::ng-deep .Comments .ct-line {
|
||||
fill: none;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
:host ::ng-deep .Comments .ct-point{
|
||||
stroke-width: 0px;
|
||||
}
|
||||
:host ::ng-deep .Comments .ct-series-a .ct-line {
|
||||
stroke: #FF9149;
|
||||
}
|
||||
:host ::ng-deep .Comments .ct-series-a .ct-area {
|
||||
fill: #FF9149;
|
||||
}
|
||||
:host ::ng-deep .Views .ct-series-a .ct-point {
|
||||
stroke: #FF4961;
|
||||
}
|
||||
:host ::ng-deep .Views .ct-line {
|
||||
fill: none;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
:host ::ng-deep .Views .ct-point{
|
||||
stroke-width: 0px;
|
||||
}
|
||||
:host ::ng-deep .Views .ct-series-a .ct-line {
|
||||
stroke: #FF4961;
|
||||
}
|
||||
:host ::ng-deep .Views .ct-series-a .ct-area {
|
||||
fill: #FF4961;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-point{
|
||||
stroke: #ff9149;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-line{
|
||||
stroke: #ff9149;
|
||||
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-cost .ct-series-a .ct-area{
|
||||
fill: #ff9149;
|
||||
fill-opacity: 1;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-cost .ct-point{
|
||||
stroke-width: 0px;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-cost svg {
|
||||
margin-left: 13px;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-sales .ct-series-a .ct-point{
|
||||
stroke: #28d094;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-sales .ct-series-a .ct-line{
|
||||
stroke: #28d094;
|
||||
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-sales .ct-series-a .ct-area{
|
||||
fill: #28d094;
|
||||
fill-opacity: 1;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-sales .ct-point{
|
||||
stroke-width: 0px;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-sales svg {
|
||||
margin-left: 13px;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-revenue .ct-series-a .ct-point{
|
||||
stroke: #ff4961;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-revenue .ct-series-a .ct-line{
|
||||
stroke: #ff4961;
|
||||
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-revenue .ct-series-a .ct-area{
|
||||
fill: #ff4961;
|
||||
fill-opacity: 1;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-revenue .ct-point{
|
||||
stroke-width: 0px;
|
||||
}
|
||||
:host ::ng-deep .sp-line-total-revenue svg {
|
||||
margin-left: 13px;
|
||||
}
|
||||
:host ::ng-deep .ct-bar {
|
||||
fill: none;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
:host ::ng-deep .sp-bar-total-cost .ct-series-a .ct-bar{
|
||||
stroke: #ff9148;
|
||||
}
|
||||
:host ::ng-deep .sp-bar-total-sales .ct-series-a .ct-bar{
|
||||
stroke: #28d094;
|
||||
}
|
||||
:host ::ng-deep .sp-bar-total-revenue .ct-series-a .ct-bar{
|
||||
stroke: #ff4961;
|
||||
}
|
||||
:host ::ng-deep .sp-bar-total-cost {
|
||||
margin-bottom: -90px;
|
||||
}
|
||||
:host ::ng-deep .sp-bar-total-sales{
|
||||
margin-bottom: -90px;
|
||||
}
|
||||
:host ::ng-deep .sp-bar-total-revenue{
|
||||
margin-bottom: -90px;
|
||||
}
|
||||
:host ::ng-deep .feedbacks .ct-series-a .ct-slice-donut {
|
||||
stroke: #28d094;
|
||||
stroke-width: 10px !important;
|
||||
}
|
||||
:host ::ng-deep .Subscribers .ct-series-a .ct-slice-donut {
|
||||
stroke: #ff9149;
|
||||
stroke-width: 10px !important;
|
||||
}
|
||||
:host ::ng-deep .Users .ct-series-a .ct-slice-donut {
|
||||
stroke: #ff4961;
|
||||
stroke-width: 10px !important;
|
||||
}
|
||||
:host ::ng-deep .ct-series-b .ct-slice-donut {
|
||||
stroke: #eeeeee;
|
||||
stroke-width: 12px !important;
|
||||
}
|
||||
:host ::ng-deep .text-muted {
|
||||
position: absolute;
|
||||
}
|
||||
2274
src/app/content/advance-cards/statistics/statistics.component.html
Normal file
2274
src/app/content/advance-cards/statistics/statistics.component.html
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { StatisticsComponent } from './statistics.component';
|
||||
|
||||
describe('StatisticsComponent', () => {
|
||||
let component: StatisticsComponent;
|
||||
let fixture: ComponentFixture<StatisticsComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ StatisticsComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(StatisticsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
224
src/app/content/advance-cards/statistics/statistics.component.ts
Normal file
224
src/app/content/advance-cards/statistics/statistics.component.ts
Normal file
@@ -0,0 +1,224 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import * as Chartist from 'chartist';
|
||||
import { ChartEvent, ChartType } from 'ng-chartist';
|
||||
import { ChartApiService } from '../../../_services/chart.api';
|
||||
|
||||
export interface Chart {
|
||||
type: ChartType;
|
||||
data: Chartist.IChartistData;
|
||||
options?: any;
|
||||
responsiveOptions?: any;
|
||||
events?: ChartEvent;
|
||||
}
|
||||
@Component({
|
||||
selector: 'app-statistics',
|
||||
templateUrl: './statistics.component.html',
|
||||
styleUrls: ['./statistics.component.css']
|
||||
})
|
||||
export class StatisticsComponent implements OnInit {
|
||||
Data: any;
|
||||
public breadcrumb: any;
|
||||
feedbacksdonutChart: any;
|
||||
subscribersdonutChart: any;
|
||||
usersdonutChart: any;
|
||||
lineArea: any;
|
||||
commentslineArea: any;
|
||||
viewslineArea: any;
|
||||
sparklineArea: any;
|
||||
barChart1: any;
|
||||
barChart: any;
|
||||
|
||||
constructor(private chartApiservice: ChartApiService) {}
|
||||
|
||||
getlineArea() {
|
||||
const ChartData = this.Data;
|
||||
this.feedbacksdonutChart = {
|
||||
type: 'Pie',
|
||||
data: ChartData['feedbacksdonutChart'],
|
||||
options: {
|
||||
showLabel: false,
|
||||
chartPadding: 0,
|
||||
fullwidth: true,
|
||||
height: '200px',
|
||||
donut: true,
|
||||
startAngle: 0
|
||||
}
|
||||
};
|
||||
this.subscribersdonutChart = {
|
||||
type: 'Pie',
|
||||
data: ChartData['subscribersdonutChart'],
|
||||
options: {
|
||||
chartPadding: 0,
|
||||
fullwidth: true,
|
||||
height: '200px',
|
||||
donut: true,
|
||||
showLabel: false,
|
||||
startAngle: 0
|
||||
}
|
||||
};
|
||||
this.usersdonutChart = {
|
||||
type: 'Pie',
|
||||
data: ChartData['usersdonutChart'],
|
||||
options: {
|
||||
showLabel: false,
|
||||
chartPadding: 0,
|
||||
fullwidth: true,
|
||||
height: '200px',
|
||||
donut: true,
|
||||
startAngle: 0
|
||||
}
|
||||
};
|
||||
|
||||
this.lineArea = {
|
||||
type: 'Line',
|
||||
data: ChartData['lineArea'],
|
||||
options: {
|
||||
// low: 650,
|
||||
fullwidth: true,
|
||||
height: '80px',
|
||||
showArea: true,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
showLabel: false
|
||||
},
|
||||
axisY: {
|
||||
showGrid: false,
|
||||
showLabel: false
|
||||
}
|
||||
}
|
||||
};
|
||||
this.commentslineArea = {
|
||||
type: 'Line',
|
||||
data: ChartData['commentslineArea'],
|
||||
options: {
|
||||
// low: 650,
|
||||
fullwidth: true,
|
||||
height: '80px',
|
||||
showArea: true,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
showLabel: false
|
||||
},
|
||||
axisY: {
|
||||
showGrid: false,
|
||||
showLabel: false
|
||||
}
|
||||
}
|
||||
};
|
||||
this.viewslineArea = {
|
||||
type: 'Line',
|
||||
data: ChartData['viewslineArea'],
|
||||
options: {
|
||||
// low: 650,
|
||||
fullwidth: true,
|
||||
height: '80px',
|
||||
showArea: true,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
showLabel: false
|
||||
},
|
||||
axisY: {
|
||||
showGrid: false,
|
||||
showLabel: false
|
||||
}
|
||||
}
|
||||
};
|
||||
this.sparklineArea = {
|
||||
type: 'Line',
|
||||
data: ChartData['sparklineArea'],
|
||||
options: {
|
||||
chartPadding: 0,
|
||||
showArea: true,
|
||||
showLine: false,
|
||||
showPoint: false,
|
||||
lineSmooth: Chartist.Interpolation.none(),
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
offset: -1
|
||||
},
|
||||
axisY: {
|
||||
showGrid: false,
|
||||
offset: -1
|
||||
}
|
||||
}
|
||||
};
|
||||
this.barChart = {
|
||||
type: 'Bar',
|
||||
data: ChartData['Bar'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
showLabel: false,
|
||||
offset: 100
|
||||
},
|
||||
|
||||
axisY: {
|
||||
showGrid: false,
|
||||
showLabel: false
|
||||
}
|
||||
}
|
||||
};
|
||||
this.barChart1 = {
|
||||
type: 'Bar',
|
||||
data: ChartData['Bar1'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
showLabel: false,
|
||||
offset: 100
|
||||
},
|
||||
|
||||
axisY: {
|
||||
showGrid: false,
|
||||
showLabel: false
|
||||
}
|
||||
}
|
||||
};
|
||||
this.lineArea = {
|
||||
type: 'Line',
|
||||
data: ChartData['lineArea'],
|
||||
options: {
|
||||
// low: 650,
|
||||
fullwidth: true,
|
||||
height: '75px',
|
||||
showArea: true,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
showLabel: false
|
||||
},
|
||||
axisY: {
|
||||
showGrid: false,
|
||||
showLabel: false
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
ngOnInit() {
|
||||
this.breadcrumb = {
|
||||
mainlabel: 'Advance Statistics Cards',
|
||||
links: [
|
||||
{
|
||||
name: 'Home',
|
||||
isLink: true,
|
||||
link: '/dashboard/sales'
|
||||
},
|
||||
{
|
||||
name: 'Advance Cards',
|
||||
isLink: true,
|
||||
link: '#'
|
||||
},
|
||||
{
|
||||
name: 'Statistics Cards',
|
||||
isLink: false,
|
||||
link: '#'
|
||||
}
|
||||
]
|
||||
};
|
||||
this.chartApiservice.getStatisticsData().subscribe(Response => {
|
||||
this.Data = Response;
|
||||
this.getlineArea();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import { ChangeDetectorRef, Component, forwardRef, Input } from '@angular/core';
|
||||
import {
|
||||
getSeconds,
|
||||
getMinutes,
|
||||
getHours,
|
||||
getDate,
|
||||
getMonth,
|
||||
getYear,
|
||||
setSeconds,
|
||||
setMinutes,
|
||||
setHours,
|
||||
setDate,
|
||||
setMonth,
|
||||
setYear
|
||||
} from 'date-fns';
|
||||
import { NgbDateStruct, NgbTimeStruct } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
export const DATE_TIME_PICKER_CONTROL_VALUE_ACCESSOR: any = {
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: forwardRef(() => DateTimePickerComponent),
|
||||
multi: true
|
||||
};
|
||||
|
||||
@Component({
|
||||
selector: 'app-mwl-demo-utils-date-time-picker',
|
||||
templateUrl: 'dateTimeComponent.component.html',
|
||||
styleUrls: ['dateTimePickerComponent.component.css'],
|
||||
providers: [DATE_TIME_PICKER_CONTROL_VALUE_ACCESSOR]
|
||||
})
|
||||
export class DateTimePickerComponent implements ControlValueAccessor {
|
||||
@Input() placeholder: string;
|
||||
|
||||
date: Date;
|
||||
|
||||
dateStruct: NgbDateStruct;
|
||||
|
||||
timeStruct: NgbTimeStruct;
|
||||
|
||||
datePicker: any;
|
||||
|
||||
private onChangeCallback: (date: Date) => void = () => { };
|
||||
|
||||
constructor(private cdr: ChangeDetectorRef) { }
|
||||
|
||||
writeValue(date: Date): void {
|
||||
this.date = date;
|
||||
this.dateStruct = {
|
||||
day: getDate(date),
|
||||
month: getMonth(date) + 1,
|
||||
year: getYear(date)
|
||||
};
|
||||
this.timeStruct = {
|
||||
second: getSeconds(date),
|
||||
minute: getMinutes(date),
|
||||
hour: getHours(date)
|
||||
};
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
registerOnChange(fn: any): void {
|
||||
this.onChangeCallback = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(fn: any): void { }
|
||||
|
||||
updateDate(): void {
|
||||
const newDate: Date = setYear(
|
||||
setMonth(
|
||||
setDate(this.date, this.dateStruct.day),
|
||||
this.dateStruct.month - 1
|
||||
),
|
||||
this.dateStruct.year
|
||||
);
|
||||
this.onChangeCallback(newDate);
|
||||
}
|
||||
|
||||
updateTime(): void {
|
||||
const newDate: Date = setHours(
|
||||
setMinutes(
|
||||
setSeconds(this.date, this.timeStruct.second),
|
||||
this.timeStruct.minute
|
||||
),
|
||||
this.timeStruct.hour
|
||||
);
|
||||
this.onChangeCallback(newDate);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
:host ::ng-deep .card-block .h4 {
|
||||
font-size: 1.32rem;
|
||||
font-family: bold;
|
||||
}
|
||||
|
||||
:host ::ng-deep .content-sub-header {
|
||||
margin-top: 0;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
:host ::ng-deep .mb-3,
|
||||
.my-3 {
|
||||
margin-bottom: 2rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .block-ui-wrapper {
|
||||
background: rgba(255, 249, 249, 0.5) !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngb-datepicker-month-view {
|
||||
display: block;
|
||||
background-color: red !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.bottom_space {
|
||||
padding-bottom: 1rem !important;
|
||||
text-align: unset !important;
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.pull-right {
|
||||
float: left !important;
|
||||
}
|
||||
}
|
||||
|
||||
.close {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
::ng-deep ngb-modal-backdrop {
|
||||
z-index: 1050 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngb-dp-header {
|
||||
background-color: var(--light) !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngb-dp-weekdays {
|
||||
background-color: var(--light);
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngb-dp-month-name {
|
||||
background-color: var(--light);
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
<div class="app-content content">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<section id="calendar">
|
||||
<div class="row">
|
||||
<div class="col-12" *blockUI="'default'; message: 'Loading'">
|
||||
<m-card [options]="options" (reloadFunction)="reloadDefault($event)">
|
||||
<ng-container mCardHeaderTitle>
|
||||
Add Event
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<p class="content-sub-header">This is the most advanced example having various features. This
|
||||
example lists all the events on the calendar with Add new event functionality.</p>
|
||||
<ng-template #modalContent let-close="close">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">{{ modalData?.action }}</h5>
|
||||
<button type="button" class="close" (click)="close()">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-body">
|
||||
<div class="form-group">
|
||||
<label>Event Title:</label>
|
||||
<input type="text" name="event-title" class="form-control" [(ngModel)]="modalData?.event.title"
|
||||
(keyup)="refresh.next()">
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-12">
|
||||
<div class="form-group">
|
||||
<label>Primary Color:</label>
|
||||
<input type="color" name="primary-color" [(ngModel)]="modalData?.event.color.primary"
|
||||
(change)="refresh.next()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-12">
|
||||
<div class="form-group">
|
||||
<label>Secondary Color:</label>
|
||||
<input type="color" name="secondary-color" [(ngModel)]="modalData?.event.color.secondary"
|
||||
(change)="refresh.next()">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-12">
|
||||
<div class="form-group">
|
||||
<label>Starts At:</label>
|
||||
<!-- <input type="date" name="starts-at" [(ngModel)]="modalData?.event.start" (ngModelChange)="refresh.next()" placeholder="Not set"> -->
|
||||
<!-- <input type="date" class="form-control" id="date" > -->
|
||||
<app-mwl-demo-utils-date-time-picker name="starts-at" [(ngModel)]="modalData?.event.start" (ngModelChange)="refresh.next()" placeholder="Not set">
|
||||
</app-mwl-demo-utils-date-time-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-12">
|
||||
<div class="form-group">
|
||||
<label>Ends At:</label>
|
||||
<app-mwl-demo-utils-date-time-picker name="ends-at" [(ngModel)]="modalData?.event.end" (ngModelChange)="refresh.next()" placeholder="Not set">
|
||||
</app-mwl-demo-utils-date-time-picker>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="close()">OK</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
<div class="card">
|
||||
<div class="card-block">
|
||||
<div class=" row d-flex flex-wrap justify-content-md-between mb-3 no-gutters">
|
||||
|
||||
<div class="col-md-4 bottom_space">
|
||||
<div class="btn-group">
|
||||
<div class="btn btn-primary" 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-primary" mwlCalendarNextView [view]="view" [(viewDate)]="viewDate"
|
||||
(viewDateChange)="activeDayIsOpen = false">
|
||||
Next
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 text-center align-self-center bottom_space">
|
||||
<h3 class="text-uppercase mb-0">{{ viewDate | calendarDate:(view + 'ViewTitle'):'en' }}</h3>
|
||||
</div>
|
||||
<div class="col-md-4 text-right bottom_space">
|
||||
<div class="btn-group">
|
||||
<div class="btn btn-primary" (click)="view = CalendarView.Month"
|
||||
[class.active]="view === CalendarView.Month">
|
||||
Month
|
||||
</div>
|
||||
<div class="btn btn-primary" (click)="view = CalendarView.Week"
|
||||
[class.active]="view === CalendarView.Week">
|
||||
Week
|
||||
</div>
|
||||
<div class="btn btn-primary" (click)="view = CalendarView.Day"
|
||||
[class.active]="view === CalendarView.Day">
|
||||
Day
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<button class="btn btn-raised btn-primary pull-right" (click)="addEvent()">
|
||||
Add Event
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div [ngSwitch]="view">
|
||||
<mwl-calendar-month-view *ngSwitchCase="'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="'week'" [viewDate]="viewDate" [events]="events"
|
||||
[refresh]="refresh" (eventClicked)="handleEvent('Clicked', $event.event)"
|
||||
(eventTimesChanged)="eventTimesChanged($event)">
|
||||
</mwl-calendar-week-view>
|
||||
<mwl-calendar-day-view *ngSwitchCase="'day'" [viewDate]="viewDate" [events]="events"
|
||||
[refresh]="refresh" (eventClicked)="handleEvent('Clicked', $event.event)"
|
||||
(eventTimesChanged)="eventTimesChanged($event)">
|
||||
</mwl-calendar-day-view>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { AddeventComponent } from './addevent.component';
|
||||
|
||||
describe('AddeventComponent', () => {
|
||||
let component: AddeventComponent;
|
||||
let fixture: ComponentFixture<AddeventComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ AddeventComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AddeventComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,233 @@
|
||||
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
||||
import { ViewChild, TemplateRef } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { startOfDay, endOfDay, subDays, addDays, endOfMonth, startOfMonth, isSameDay, isSameMonth, addHours } from 'date-fns';
|
||||
import { CalendarEventTimesChangedEvent, CalendarView, CalendarEvent, CalendarEventAction } from 'angular-calendar';
|
||||
import { NgbDateStruct, NgbTimeStruct } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { BlockUI, NgBlockUI } from 'ng-block-ui';
|
||||
|
||||
const colors: any = {
|
||||
red: {
|
||||
primary: '#ad2121',
|
||||
secondary: '#FAE3E3'
|
||||
},
|
||||
blue: {
|
||||
primary: '#1e90ff',
|
||||
secondary: '#D1E8FF'
|
||||
},
|
||||
yellow: {
|
||||
primary: '#e3bc08',
|
||||
secondary: '#FDF1BA'
|
||||
}
|
||||
};
|
||||
@Component({
|
||||
selector: 'app-adddeleteevent',
|
||||
templateUrl: './addevent.component.html',
|
||||
styleUrls: ['./addevent.component.css']
|
||||
})
|
||||
export class AddeventComponent implements OnInit {
|
||||
|
||||
@BlockUI('default') blockUIDefault: NgBlockUI;
|
||||
date: Date;
|
||||
options = {
|
||||
close: true,
|
||||
expand: true,
|
||||
minimize: true,
|
||||
reload: true
|
||||
};
|
||||
@ViewChild('modalContent') modalContent: TemplateRef<any>;
|
||||
view: CalendarView = CalendarView.Month;
|
||||
CalendarView = CalendarView;
|
||||
newEvent: CalendarEvent;
|
||||
viewDate: Date = new Date();
|
||||
activeDayIsOpen = true;
|
||||
modalData: {action: string;
|
||||
event: CalendarEvent;
|
||||
};
|
||||
actions: CalendarEventAction[] = [
|
||||
{
|
||||
label: '<i class="fa fa-fw fa-pencil"></i>',
|
||||
onClick: ({ event }: { event: CalendarEvent }): void => {
|
||||
this.handleEvent('Edited', event);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '<i class="fa fa-fw fa-times"></i>',
|
||||
onClick: ({ event }: { event: CalendarEvent }): void => {
|
||||
this.events = this.events.filter(iEvent => iEvent !== event);
|
||||
this.handleEvent('Deleted', event);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
refresh: Subject<any> = new Subject();
|
||||
|
||||
events: CalendarEvent[] = [
|
||||
{
|
||||
start: subDays(startOfDay(new Date()), 0),
|
||||
end: addDays(new Date(), 1),
|
||||
title: 'Business Lunch',
|
||||
color: colors.red,
|
||||
actions: this.actions,
|
||||
allDay: true,
|
||||
resizable: {
|
||||
beforeStart: true,
|
||||
afterEnd: true
|
||||
},
|
||||
draggable: true
|
||||
},
|
||||
|
||||
{
|
||||
start: subDays(endOfMonth(new Date()), 2),
|
||||
end: addDays(endOfMonth(new Date()), 1),
|
||||
title: 'A long event that spans 2 months',
|
||||
color: colors.blue,
|
||||
allDay: true
|
||||
},
|
||||
|
||||
{
|
||||
start: subDays(startOfMonth(new Date()), 1),
|
||||
end: addDays(startOfMonth(new Date()), 0),
|
||||
title: 'Meeting',
|
||||
color: colors.yellow,
|
||||
actions: this.actions,
|
||||
resizable: {
|
||||
beforeStart: true,
|
||||
afterEnd: true
|
||||
},
|
||||
draggable: true
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
dateStruct: NgbDateStruct;
|
||||
|
||||
timeStruct: NgbTimeStruct;
|
||||
public breadcrumb: any;
|
||||
|
||||
datePicker: any;
|
||||
private onChangeCallback: (date: Date) => void = () => { };
|
||||
|
||||
/**
|
||||
*
|
||||
* @param NgbModal modal
|
||||
*/
|
||||
constructor(private modal: NgbModal) { }
|
||||
|
||||
/**
|
||||
* onInit
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.breadcrumb = {
|
||||
'mainlabel': 'Calendar AddEvent',
|
||||
'links': [
|
||||
{
|
||||
'name': 'Home',
|
||||
'isLink': true,
|
||||
'link': '/dashboard/sales'
|
||||
},
|
||||
{
|
||||
'name': 'Apps',
|
||||
'isLink': true,
|
||||
'link': '#'
|
||||
},
|
||||
{
|
||||
'name': 'Calendars',
|
||||
'isLink': true,
|
||||
'link': '#'
|
||||
},
|
||||
{
|
||||
'name': 'AddEvent',
|
||||
'isLink': false,
|
||||
'link': '#'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* selacted date
|
||||
*
|
||||
* @param date Clicked date in datepicker
|
||||
* @param events Events of selected date
|
||||
*/
|
||||
dayClicked({ date, events }: { date: Date; events: CalendarEvent[] }): void {
|
||||
if (isSameMonth(date, this.viewDate)) {
|
||||
this.viewDate = date;
|
||||
if (
|
||||
(isSameDay(this.viewDate, date) && this.activeDayIsOpen === true) ||
|
||||
events.length === 0
|
||||
) {
|
||||
this.activeDayIsOpen = false;
|
||||
} else {
|
||||
this.activeDayIsOpen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param event Event of the time change
|
||||
* @param newStart Event start date
|
||||
* @param newEnd Event end date
|
||||
*/
|
||||
eventTimesChanged({
|
||||
event,
|
||||
newStart,
|
||||
newEnd
|
||||
}: CalendarEventTimesChangedEvent): void {
|
||||
event.start = newStart;
|
||||
event.end = newEnd;
|
||||
this.handleEvent('Dropped or resized', event);
|
||||
this.refresh.next({});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param action Event action
|
||||
* @param event calendar event
|
||||
*/
|
||||
handleEvent(action: string, event: CalendarEvent): void {
|
||||
this.modalData = { event, action };
|
||||
this.modal.open(this.modalContent, { size: 'lg' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new event in modal
|
||||
*/
|
||||
addEvent(): void {
|
||||
this.newEvent = {
|
||||
title: 'New event',
|
||||
start: startOfDay(new Date()),
|
||||
end: endOfDay(new Date()),
|
||||
color: colors.red,
|
||||
draggable: true,
|
||||
resizable: {
|
||||
beforeStart: true,
|
||||
afterEnd: true
|
||||
},
|
||||
actions: this.actions,
|
||||
};
|
||||
this.events.push(this.newEvent);
|
||||
|
||||
// this.refresh.next();
|
||||
this.handleEvent('Add new event', this.newEvent);
|
||||
this.refresh.next({});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload card
|
||||
*/
|
||||
reloadDefault () {
|
||||
this.blockUIDefault.start('Loading..');
|
||||
|
||||
setTimeout(() => {
|
||||
this.blockUIDefault.stop();
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<form class="form-inline">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input
|
||||
readonly
|
||||
class="form-control"
|
||||
[placeholder]="placeholder"
|
||||
name="date"
|
||||
[(ngModel)]="dateStruct"
|
||||
(ngModelChange)="updateDate()"
|
||||
ngbDatepicker
|
||||
#datePicker="ngbDatepicker">
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text" (click)="datePicker.toggle()" >
|
||||
<i class="fa fa-calendar"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<ngb-timepicker
|
||||
[(ngModel)]="timeStruct"
|
||||
(ngModelChange)="updateTime()"
|
||||
[meridian]="true">
|
||||
</ngb-timepicker>
|
||||
@@ -0,0 +1,143 @@
|
||||
.form-group {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:host ::ng-deep .btn-light:not(:disabled):not(.disabled):active {
|
||||
color: unset !important;
|
||||
background-color: unset !important;
|
||||
border-color: #d3d9df !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .btn-light:hover:not(.disabled):active {
|
||||
background-color: #e2e6ea !important;
|
||||
border-color: #dae0e5 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .btn-light {
|
||||
color: unset !important;
|
||||
background-color: unset !important;
|
||||
border-color: unset !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .bg-primary {
|
||||
background-color: #007bff !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .text-white {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .custom-day {
|
||||
text-align: center;
|
||||
padding: .185rem .25rem;
|
||||
display: inline-block;
|
||||
height: 2rem;
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
:host ::ng-deep .custom-day:active {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
div.bg-light {
|
||||
background-color: #f8f9fa !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .hidden {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.ngb-dp-weekday {
|
||||
color: #17a2b8;
|
||||
}
|
||||
|
||||
.ngb-dp-week-number,
|
||||
.ngb-dp-weekday {
|
||||
line-height: 2rem;
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.ngb-datepicker-month-view {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 80%;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.ngb-dp-day {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
.ngb-dp-month {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.btn-light:hover {
|
||||
color: #212529 !important;
|
||||
background-color: #e2e6ea !important;
|
||||
border-color: #dae0e5 !important;
|
||||
}
|
||||
|
||||
.ngb-datepicker-month-view {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.ngb-dp-header {
|
||||
border-bottom: 0;
|
||||
border-radius: .25rem .25rem 0 0;
|
||||
padding-top: .25rem;
|
||||
}
|
||||
|
||||
.ngb-dp-day,
|
||||
.ngb-dp-week-number,
|
||||
.ngb-dp-weekday {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.custom-day {
|
||||
text-align: center;
|
||||
padding: 0.185rem 0.25rem;
|
||||
display: inline-block;
|
||||
height: 2rem;
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.custom-day.focused {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
.custom-day.range,
|
||||
.custom-day:hover {
|
||||
background-color: rgb(2, 117, 216);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.custom-day.faded {
|
||||
background-color: rgba(2, 117, 216, 0.5);
|
||||
}
|
||||
|
||||
:host ::ng-deep.visually-hidden {
|
||||
position: absolute !important;
|
||||
width: 1px !important;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
border: 0;
|
||||
}
|
||||
:host ::ng-deep .ngb-dp-header {
|
||||
background-color: var(--light) !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngb-dp-weekdays {
|
||||
background-color: var(--light);
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngb-dp-month-name {
|
||||
background-color: var(--light);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
:host ::ng-deep .h3 {
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .pre {
|
||||
background-color: #f5f5f5;
|
||||
padding: 15px;
|
||||
}
|
||||
:host ::ng-deep.card-header .heading-elements, .card-header .heading-elements-toggle {
|
||||
background-color: inherit;
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
right: 77px;
|
||||
}
|
||||
:host ::ng-deep .cal-month-view .cal-open-day-events {
|
||||
padding: 0px !important;
|
||||
color: white;
|
||||
background-color: #555;
|
||||
-webkit-box-shadow: inset 0 0 15px 0 rgba(0, 0, 0, 0.5);
|
||||
box-shadow: inset 0 0 15px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
:host ::ng-deep .card-header .heading-elements {
|
||||
background-color: inherit;
|
||||
position: absolute;
|
||||
top: 19px;
|
||||
right: 19px;
|
||||
}
|
||||
|
||||
.fc-toolbar .fc-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.fc-toolbar .fc-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.fc-toolbar.fc-header-toolbar {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
|
||||
:host ::ng-deep .block-ui-wrapper {
|
||||
background: rgba(255, 249, 249, 0.5) !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.bottom_space {
|
||||
padding-bottom: 1rem !important;
|
||||
text-align: unset !important;
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep ngb-modal-backdrop {
|
||||
z-index: 1050 !important;
|
||||
}
|
||||
183
src/app/content/applications/calender/basic/basic.component.html
Normal file
183
src/app/content/applications/calender/basic/basic.component.html
Normal file
@@ -0,0 +1,183 @@
|
||||
<div class="app-content content">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<section id="basic-examples">
|
||||
<div class="row">
|
||||
<div class="col-12" *blockUI="'basicViews'; message: 'Loading'">
|
||||
<m-card [options]="options" (reloadFunction)="reloadBasicViews($event)">
|
||||
<ng-container mCardHeaderTitle>
|
||||
Basic Views
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<p>This is the most basic example having navigation buttons as well as month, week and day views. In
|
||||
this example you have the option to change your view to a basicWeek or basicDay view. In the Basic
|
||||
Week or Basic Day View events are listed all together.</p>
|
||||
<br>
|
||||
<ng-template #modalContent let-close="close">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Event action occurred</h5>
|
||||
<button type="button" class="close" (click)="close()">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
Action:
|
||||
<pre>{{ modalData?.action }}</pre>
|
||||
</div>
|
||||
<div>
|
||||
Event:
|
||||
<pre>{{ modalData?.event | json }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="close()">
|
||||
OK
|
||||
</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 bottom_space">
|
||||
<h3>{{ BviewDate | calendarDate:(Bview + 'ViewTitle'):'en' }}</h3>
|
||||
</div>
|
||||
<div class="col-md-6 text-right bottom_space">
|
||||
<div class="btn-group">
|
||||
<div class="btn btn-primary" mwlCalendarPreviousView [view]="Bview" [(viewDate)]="BviewDate"
|
||||
(viewDateChange)="activeDayIsOpen = false">
|
||||
Previous
|
||||
</div>
|
||||
<div class="btn btn-outline-secondary" mwlCalendarToday [(viewDate)]="BviewDate">
|
||||
Today
|
||||
</div>
|
||||
<div class="btn btn-primary" mwlCalendarNextView [view]="Bview" [(viewDate)]="BviewDate"
|
||||
(viewDateChange)="activeDayIsOpen = false">
|
||||
Next
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<br />
|
||||
<div [ngSwitch]="Bview">
|
||||
<mwl-calendar-month-view *ngSwitchCase="CalendarView.Month" [viewDate]="BviewDate" [refresh]="refresh"
|
||||
[activeDayIsOpen]="activeDayIsOpen" (eventClicked)="handleEvent('Clicked', $event.event)"
|
||||
(eventTimesChanged)="eventTimesChanged($event)">
|
||||
</mwl-calendar-month-view>
|
||||
<mwl-calendar-week-view *ngSwitchCase="CalendarView.Week" [viewDate]="BviewDate" [refresh]="refresh"
|
||||
(eventClicked)="handleEvent('Clicked', $event.event)"
|
||||
(eventTimesChanged)="eventTimesChanged($event)">
|
||||
</mwl-calendar-week-view>
|
||||
<mwl-calendar-day-view *ngSwitchCase="CalendarView.Day" [viewDate]="BviewDate" [refresh]="refresh"
|
||||
(eventClicked)="handleEvent('Clicked', $event.event)"
|
||||
(eventTimesChanged)="eventTimesChanged($event)">
|
||||
</mwl-calendar-day-view>
|
||||
</div>
|
||||
<br /><br /><br />
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<section id="basic-examples">
|
||||
<div class="row">
|
||||
<div class="col-12" *blockUI="'basicViews'; message: 'Loading'">
|
||||
<m-card [options]="options" (reloadFunction)="reloadBasicViews($event)">
|
||||
<ng-container mCardHeaderTitle>
|
||||
Basic Views
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<p>This is the most basic example having navigation buttons as well as month, week and day views. In
|
||||
this example you have the option to change your view to a basicWeek or basicDay view. In the Basic
|
||||
Week or Basic Day View events are listed all together.</p>
|
||||
<br>
|
||||
<ng-template #modalContent let-close="close">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Event action occurred</h5>
|
||||
<button type="button" class="close" (click)="close()">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
Action:
|
||||
<pre>{{ modalData?.action }}</pre>
|
||||
</div>
|
||||
<div>
|
||||
Event:
|
||||
<pre>{{ modalData?.event | json }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="close()">
|
||||
OK
|
||||
</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 bottom_space">
|
||||
<div class="btn-group">
|
||||
<div class="btn btn-primary" mwlCalendarPreviousView [view]="Bview" [(viewDate)]="BviewDate"
|
||||
(viewDateChange)="activeDayIsOpen = false">
|
||||
Previous
|
||||
</div>
|
||||
<div class="btn btn-outline-secondary" mwlCalendarToday [(viewDate)]="BviewDate">
|
||||
Today
|
||||
</div>
|
||||
<div class="btn btn-primary" mwlCalendarNextView [view]="Bview" [(viewDate)]="BviewDate"
|
||||
(viewDateChange)="activeDayIsOpen = false">
|
||||
Next
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 text-center bottom_space">
|
||||
<h3>{{ BviewDate | calendarDate:(Bview + 'ViewTitle'):'en' }}</h3>
|
||||
</div>
|
||||
<div class="col-md-4 text-right bottom_space">
|
||||
<div class="btn-group">
|
||||
<div class="btn btn-primary" (click)="Bview = CalendarView.Month"
|
||||
[class.active]="Bview === CalendarView.Month">
|
||||
Month
|
||||
</div>
|
||||
<div class="btn btn-primary" (click)="Bview = CalendarView.Week"
|
||||
[class.active]="Bview === CalendarView.Week">
|
||||
Week
|
||||
</div>
|
||||
<div class="btn btn-primary" (click)="Bview = CalendarView.Day"
|
||||
[class.active]="Bview === CalendarView.Day">
|
||||
Day
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div [ngSwitch]="Bview">
|
||||
<mwl-calendar-month-view *ngSwitchCase="CalendarView.Month" [viewDate]="BviewDate" [refresh]="refresh"
|
||||
[activeDayIsOpen]="activeDayIsOpen" (eventClicked)="handleEvent('Clicked', $event.event)"
|
||||
(eventTimesChanged)="eventTimesChanged($event)">
|
||||
</mwl-calendar-month-view>
|
||||
<mwl-calendar-week-view *ngSwitchCase="CalendarView.Week" [viewDate]="BviewDate" [refresh]="refresh"
|
||||
(eventClicked)="handleEvent('Clicked', $event.event)"
|
||||
(eventTimesChanged)="eventTimesChanged($event)">
|
||||
</mwl-calendar-week-view>
|
||||
<mwl-calendar-day-view *ngSwitchCase="CalendarView.Day" [viewDate]="BviewDate" [refresh]="refresh"
|
||||
(eventClicked)="handleEvent('Clicked', $event.event)"
|
||||
(eventTimesChanged)="eventTimesChanged($event)">
|
||||
</mwl-calendar-day-view>
|
||||
</div>
|
||||
<br /><br /><br />
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { BasicComponent } from './basic.component';
|
||||
|
||||
describe('BasicComponent', () => {
|
||||
let component: BasicComponent;
|
||||
let fixture: ComponentFixture<BasicComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ BasicComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(BasicComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,89 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ViewChild, TemplateRef } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { CalendarView } from 'angular-calendar';
|
||||
import { BlockUI, NgBlockUI } from 'ng-block-ui';
|
||||
|
||||
@Component({
|
||||
selector: 'app-basic',
|
||||
templateUrl: './basic.component.html',
|
||||
styleUrls: ['./basic.component.css']
|
||||
})
|
||||
export class BasicComponent implements OnInit {
|
||||
|
||||
@BlockUI('default') blockUIDefault: NgBlockUI;
|
||||
@BlockUI('basicViews') blockUIBasicViews: NgBlockUI;
|
||||
|
||||
public breadcrumb: any;
|
||||
options = {
|
||||
close: true,
|
||||
expand: true,
|
||||
minimize: true,
|
||||
reload: true
|
||||
};
|
||||
@ViewChild('modalContent', { static: true }) modalContent: TemplateRef<any>;
|
||||
|
||||
view: CalendarView = CalendarView.Month;
|
||||
Bview: CalendarView = CalendarView.Month;
|
||||
CalendarView = CalendarView;
|
||||
|
||||
viewDate: Date = new Date();
|
||||
BviewDate: Date = new Date();
|
||||
modalData: {action: string};
|
||||
refresh: Subject<any> = new Subject();
|
||||
|
||||
activeDayIsOpen: boolean;
|
||||
|
||||
/**
|
||||
* onInit
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.breadcrumb = {
|
||||
mainlabel: 'Calendar Basic',
|
||||
links: [
|
||||
{
|
||||
name: 'Home',
|
||||
isLink: true,
|
||||
link: '/dashboard/sales'
|
||||
},
|
||||
{
|
||||
name: 'Apps',
|
||||
isLink: true,
|
||||
link: '#'
|
||||
},
|
||||
{
|
||||
name: 'Calendars',
|
||||
isLink: true,
|
||||
link: '#'
|
||||
},
|
||||
{
|
||||
name: 'Basic',
|
||||
isLink: false,
|
||||
link: '#'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* realod card
|
||||
*/
|
||||
reloadDefault() {
|
||||
this.blockUIDefault.start('Loading..');
|
||||
|
||||
setTimeout(() => {
|
||||
this.blockUIDefault.stop();
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Realod card
|
||||
*/
|
||||
reloadBasicViews() {
|
||||
this.blockUIBasicViews.start('Loading..');
|
||||
|
||||
setTimeout(() => {
|
||||
this.blockUIBasicViews.stop();
|
||||
}, 2500);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { CalenderModule } from './calender.module';
|
||||
|
||||
describe('CalenderModule', () => {
|
||||
let calenderModule: CalenderModule;
|
||||
|
||||
beforeEach(() => {
|
||||
calenderModule = new CalenderModule();
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
expect(calenderModule).toBeTruthy();
|
||||
});
|
||||
});
|
||||
61
src/app/content/applications/calender/calender.module.ts
Normal file
61
src/app/content/applications/calender/calender.module.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { CalendarModule, DateAdapter } from 'angular-calendar';
|
||||
import { adapterFactory } from 'angular-calendar/date-adapters/date-fns';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { FlatpickrModule } from 'angularx-flatpickr';
|
||||
import { BasicComponent } from './basic/basic.component';
|
||||
import { EventsComponent } from './events/events.component';
|
||||
import { AddeventComponent } from './addevent/addevent.component';
|
||||
import { CardModule } from '../../partials/general/card/card.module';
|
||||
import { BreadcrumbModule } from 'src/app/_layout/breadcrumb/breadcrumb.module';
|
||||
import { BlockUIModule } from 'ng-block-ui';
|
||||
import { BlockTemplateComponent } from 'src/app/_layout/blockui/block-template.component';
|
||||
import { DateTimePickerComponent } from './addevent/DateTimePickerComponent';
|
||||
import {
|
||||
NgbModalModule,
|
||||
NgbDatepickerModule,
|
||||
NgbTimepickerModule
|
||||
} from '@ng-bootstrap/ng-bootstrap';
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
CardModule,
|
||||
BreadcrumbModule,
|
||||
FormsModule,
|
||||
FlatpickrModule.forRoot(),
|
||||
BlockUIModule.forRoot({
|
||||
template: BlockTemplateComponent
|
||||
}),
|
||||
NgbModalModule,
|
||||
NgbDatepickerModule,
|
||||
NgbTimepickerModule,
|
||||
CalendarModule.forRoot({
|
||||
provide: DateAdapter,
|
||||
useFactory: adapterFactory
|
||||
}),
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'basic',
|
||||
component: BasicComponent
|
||||
},
|
||||
{
|
||||
path: 'events',
|
||||
component: EventsComponent
|
||||
},
|
||||
{
|
||||
path: 'addevent',
|
||||
component: AddeventComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
|
||||
declarations: [
|
||||
BasicComponent,
|
||||
EventsComponent,
|
||||
AddeventComponent,
|
||||
DateTimePickerComponent
|
||||
]
|
||||
})
|
||||
export class CalenderModule {}
|
||||
@@ -0,0 +1,27 @@
|
||||
:host ::ng-deep .cal-month-view .cal-open-day-events {
|
||||
padding: 0px !important;
|
||||
color: white;
|
||||
background-color: #555;
|
||||
-webkit-box-shadow: inset 0 0 15px 0 rgba(0, 0, 0, 0.5);
|
||||
box-shadow: inset 0 0 15px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
:host ::ng-deep .title {
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .block-ui-wrapper {
|
||||
background: rgba(255, 249, 249, 0.5) !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.bottom_space {
|
||||
padding-bottom: 1rem !important;
|
||||
text-align: unset !important;
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep ngb-modal-backdrop {
|
||||
z-index: 1050 !important;
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
<div class="app-content content">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<section id="basic-examples">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<m-card [options]="options" (reloadFunction)="reloadEvents()">
|
||||
<ng-container mCardHeaderTitle>
|
||||
Events
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<p>This is the most basic example having navigation button to navigate next and previous months and
|
||||
today button. This example lists all the events on the calendar with Add new event functionality. </p>
|
||||
<br>
|
||||
<ng-template #modalContent let-close="close">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Event action occurred</h5>
|
||||
<button type="button" class="close" (click)="close()">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
Action:
|
||||
<pre>{{ modalData?.action }}</pre>
|
||||
</div>
|
||||
<div>
|
||||
Event:
|
||||
<pre>{{ modalData?.event | json }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="close()">
|
||||
OK
|
||||
</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 bottom_space">
|
||||
<div class="btn-group">
|
||||
<div class="btn btn-primary" 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-primary" mwlCalendarNextView [view]="view" [(viewDate)]="viewDate"
|
||||
(viewDateChange)="activeDayIsOpen = false">
|
||||
Next
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 text-center bottom_space">
|
||||
<h3>{{ viewDate | calendarDate:(view + 'ViewTitle'):'en' }}</h3>
|
||||
</div>
|
||||
<div class="col-md-4 text-right bottom_space">
|
||||
<div class="btn-group">
|
||||
<div class="btn btn-primary" (click)="view = CalendarView.Month"
|
||||
[class.active]="view === CalendarView.Month">
|
||||
Month
|
||||
</div>
|
||||
<div class="btn btn-primary" (click)="view = CalendarView.Week"
|
||||
[class.active]="view === CalendarView.Week">
|
||||
Week
|
||||
</div>
|
||||
<div class="btn btn-primary" (click)="view = CalendarView.Day"
|
||||
[class.active]="view === CalendarView.Day">
|
||||
Day
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<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 /><br />
|
||||
|
||||
<h3>
|
||||
Edit events
|
||||
<button class="btn btn-primary pull-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; let index = index">
|
||||
<td>
|
||||
<input type="text" name="event-title" class="form-control title" [(ngModel)]="event.title"
|
||||
>
|
||||
|
||||
</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" 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" type="text" mwlFlatpickr [(ngModel)]="event.end"
|
||||
(ngModelChange)="refresh.next()" [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)="events.splice(index, 1); refresh.next()">
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<br /><br /><br />
|
||||
<ng-template #modalContent let-close="close">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Event action occurred</h5>
|
||||
<button type="button" class="close" (click)="close()">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
Action:
|
||||
<pre>{{ modalData?.action }}</pre>
|
||||
</div>
|
||||
<div>
|
||||
Event:
|
||||
<pre>{{ modalData?.event | json }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="close()">
|
||||
OK
|
||||
</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { EventsComponent } from './events.component';
|
||||
|
||||
describe('EventsComponent', () => {
|
||||
let component: EventsComponent;
|
||||
let fixture: ComponentFixture<EventsComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ EventsComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(EventsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
214
src/app/content/applications/calender/events/events.component.ts
Normal file
214
src/app/content/applications/calender/events/events.component.ts
Normal file
@@ -0,0 +1,214 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ViewChild, TemplateRef } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import {
|
||||
startOfDay,
|
||||
endOfDay,
|
||||
subDays,
|
||||
addDays,
|
||||
endOfMonth,
|
||||
isSameDay,
|
||||
isSameMonth,
|
||||
addHours
|
||||
} from 'date-fns';
|
||||
import {
|
||||
CalendarEventTimesChangedEvent,
|
||||
CalendarView,
|
||||
CalendarEvent,
|
||||
CalendarEventAction
|
||||
} from 'angular-calendar';
|
||||
import { BlockUI, NgBlockUI } from 'ng-block-ui';
|
||||
const colors: any = {
|
||||
red: {
|
||||
primary: '#ad2121',
|
||||
secondary: '#FAE3E3'
|
||||
},
|
||||
blue: {
|
||||
primary: '#1e90ff',
|
||||
secondary: '#D1E8FF'
|
||||
},
|
||||
yellow: {
|
||||
primary: '#e3bc08',
|
||||
secondary: '#FDF1BA'
|
||||
}
|
||||
};
|
||||
@Component({
|
||||
selector: 'app-events',
|
||||
templateUrl: './events.component.html',
|
||||
styleUrls: ['./events.component.css']
|
||||
})
|
||||
export class EventsComponent implements OnInit {
|
||||
public breadcrumb: any;
|
||||
options = {
|
||||
close: true,
|
||||
expand: true,
|
||||
minimize: true,
|
||||
reload: true
|
||||
};
|
||||
|
||||
@BlockUI('events') blockUIEvents: NgBlockUI;
|
||||
|
||||
@ViewChild('modalContent', { static: true }) modalContent: TemplateRef<any>;
|
||||
|
||||
view: CalendarView = CalendarView.Month;
|
||||
|
||||
CalendarView = CalendarView;
|
||||
|
||||
viewDate: Date = new Date();
|
||||
activeDayIsOpen = true;
|
||||
modalData: {
|
||||
action: string;
|
||||
event: CalendarEvent;
|
||||
};
|
||||
|
||||
actions: CalendarEventAction[] = [
|
||||
{
|
||||
label: '<i class="fa fa-fw fa-pencil"></i>',
|
||||
onClick: ({ event }: { event: CalendarEvent }): void => {
|
||||
this.handleEvent('Edited', event);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '<i class="fa fa-fw fa-times"></i>',
|
||||
onClick: ({ event }: { event: CalendarEvent }): void => {
|
||||
this.events = this.events.filter(iEvent => iEvent !== event);
|
||||
this.handleEvent('Deleted', event);
|
||||
}
|
||||
}
|
||||
];
|
||||
refresh: Subject<any> = new Subject();
|
||||
|
||||
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: new Date(),
|
||||
title: 'A draggable and resizable event',
|
||||
color: colors.yellow,
|
||||
actions: this.actions,
|
||||
resizable: {
|
||||
beforeStart: true,
|
||||
afterEnd: true
|
||||
},
|
||||
draggable: true
|
||||
}
|
||||
];
|
||||
|
||||
ngOnInit() {
|
||||
this.breadcrumb = {
|
||||
mainlabel: 'Full Calendar Events',
|
||||
links: [
|
||||
{
|
||||
name: 'Home',
|
||||
isLink: true,
|
||||
link: '/dashboard/sales'
|
||||
},
|
||||
{
|
||||
name: 'Apps',
|
||||
isLink: true,
|
||||
link: '#'
|
||||
},
|
||||
{
|
||||
name: 'Calendars',
|
||||
isLink: true,
|
||||
link: '#'
|
||||
},
|
||||
{
|
||||
name: 'Events',
|
||||
isLink: false,
|
||||
link: '#'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
constructor(private modal: NgbModal) {}
|
||||
|
||||
dayClicked({ date, events }: { date: Date; events: CalendarEvent[] }): void {
|
||||
if (isSameMonth(date, this.viewDate)) {
|
||||
this.viewDate = date;
|
||||
if (
|
||||
(isSameDay(this.viewDate, date) && this.activeDayIsOpen === true) ||
|
||||
events.length === 0
|
||||
) {
|
||||
this.activeDayIsOpen = false;
|
||||
} else {
|
||||
this.activeDayIsOpen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eventTimesChanged({
|
||||
event,
|
||||
newStart,
|
||||
newEnd
|
||||
}: CalendarEventTimesChangedEvent): void {
|
||||
event.start = newStart;
|
||||
event.end = newEnd;
|
||||
this.handleEvent('Dropped or resized', event);
|
||||
this.refresh.next({});
|
||||
}
|
||||
|
||||
handleEvent(action: string, event: CalendarEvent): void {
|
||||
this.modalData = { event, action };
|
||||
this.modal.open(this.modalContent, { size: 'lg' });
|
||||
}
|
||||
|
||||
addEvent(): void {
|
||||
this.events.push({
|
||||
title: 'New event',
|
||||
start: startOfDay(new Date()),
|
||||
end: endOfDay(new Date()),
|
||||
color: colors.red,
|
||||
draggable: true,
|
||||
resizable: {
|
||||
beforeStart: true,
|
||||
afterEnd: true
|
||||
}
|
||||
});
|
||||
this.refresh.next({});
|
||||
}
|
||||
deleteEvent(eventToDelete: CalendarEvent) {
|
||||
this.events = this.events.filter(event => event !== eventToDelete);
|
||||
}
|
||||
setView(view: CalendarView) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
closeOpenMonthViewDay() {
|
||||
this.activeDayIsOpen = false;
|
||||
}
|
||||
|
||||
reloadEvents() {
|
||||
this.blockUIEvents.start('Loading..');
|
||||
|
||||
setTimeout(() => {
|
||||
this.blockUIEvents.stop();
|
||||
}, 2500);
|
||||
}
|
||||
}
|
||||
56
src/app/content/applications/chat/chats.component.css
Normal file
56
src/app/content/applications/chat/chats.component.css
Normal file
@@ -0,0 +1,56 @@
|
||||
:host ::ng-deep .content-right {
|
||||
width: calc(100% - 300px) !important;
|
||||
}
|
||||
:host ::ng-deep .mx-75 {
|
||||
margin-left: .75rem!important;
|
||||
margin-right: .75rem!important;
|
||||
}
|
||||
:host ::ng-deep .py-75 {
|
||||
padding-bottom: .75rem!important;
|
||||
padding-top: .75rem!important;
|
||||
}
|
||||
:host ::ng-deep .px-1 {
|
||||
padding-left: 1rem!important;
|
||||
padding-right: 1rem!important;
|
||||
}
|
||||
:host ::ng-deep .mr-50, .mx-50 {
|
||||
margin-right: .5rem!important;
|
||||
margin-left: .5rem!important;
|
||||
}
|
||||
:host ::ng-deep .mb-50, .my-50 {
|
||||
margin-bottom: .5rem!important;
|
||||
}
|
||||
:host ::ng-deep .dropdown-menu
|
||||
{
|
||||
transform: translate3d(-131px, 18px, 0px) !important;
|
||||
}
|
||||
:host ::ng-deep .chat-sidebar .chat-sidebar-list-wrapper {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
:host ::ng-deep .sidebar-fixed {
|
||||
overflow: hidden !important;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .app-content {
|
||||
overflow-y: hidden !important;
|
||||
}
|
||||
:host ::ng-deep .pb-25, .py-25 {
|
||||
padding-bottom: .25rem!important;
|
||||
}
|
||||
:host ::ng-deep .ml-25, .mx-25 {
|
||||
margin-left: .25rem!important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ps--active-y > .ps__rail-y {
|
||||
display: none;
|
||||
}
|
||||
@media(max-width:767px) {
|
||||
:host ::ng-deep .content-right {
|
||||
width: calc(100% - 0px) !important;
|
||||
}
|
||||
}
|
||||
:host ::ng-deep .d-inline-block {
|
||||
display: inline !important;
|
||||
}
|
||||
|
||||
254
src/app/content/applications/chat/chats.component.html
Normal file
254
src/app/content/applications/chat/chats.component.html
Normal file
@@ -0,0 +1,254 @@
|
||||
<div class="app-content content" >
|
||||
<div class="sidebar-left" id="sidebar-left">
|
||||
<div class="sidebar"><!-- app chat user profile left sidebar start -->
|
||||
<div class="chat-user-profile" id="user-profile" >
|
||||
<header class="chat-user-profile-header text-center border-bottom">
|
||||
<span class="chat-profile-close" (click)="showProfile($event)" >
|
||||
<i class="ficon feather ft-x" ></i>
|
||||
</span>
|
||||
<div class="my-2">
|
||||
<img *ngIf="loggedInUser.photoURL" src="{{loggedInUser.photoURL}}" class="round mb-1" alt="user_avatar" height="100" width="100" >
|
||||
<img *ngIf="!loggedInUser.photoURL" src="../../../../assets/images/portrait/small/avatar-s-19.png" class="round mb-1" alt="user_avatar"
|
||||
alt="avatar" height="100" width="100" >
|
||||
<!-- <img src="../../../assets/images/portrait/small/avatar-s-16.png" class="round mb-1" alt="user_avatar"
|
||||
height="100" width="100" > -->
|
||||
|
||||
<h5 class="mb-0">{{loggedInUser.displayName}}</h5>
|
||||
<span>Designer</span>
|
||||
</div>
|
||||
</header>
|
||||
<div class="chat-user-profile-content">
|
||||
<div class="chat-user-profile-scroll" fxFlex="auto" [perfectScrollbar]="config">
|
||||
<h6 class="text-uppercase mb-1">ABOUT</h6>
|
||||
<p class="mb-2">It is a long established fact that a reader will be distracted by the readable content .</p>
|
||||
<h6>PERSONAL INFORAMTION</h6>
|
||||
<ul class="list-unstyled mb-2">
|
||||
<li class="mb-25">email@gmail.com</li>
|
||||
<li>+1(789) 950 -7654</li>
|
||||
</ul>
|
||||
<h6 class="text-uppercase mb-1">CHANNELS</h6>
|
||||
<ul class="list-unstyled mb-2">
|
||||
<li><a href=""># Devlopers</a></li>
|
||||
<li><a href=""># Designers</a></li>
|
||||
</ul>
|
||||
<h6 class="text-uppercase mb-1">SETTINGS</h6>
|
||||
<ul class="list-unstyled">
|
||||
<li class="mb-50 "><a href="" class="d-flex align-items-center"><i class="ficon feather ft-tag mr-50"></i>
|
||||
Add
|
||||
Tag</a></li>
|
||||
<li class="mb-50 "><a href="" class="d-flex align-items-center"><i class="ficon feather ft-star mr-50"></i>
|
||||
Important Contact</a>
|
||||
</li>
|
||||
<li class="mb-50 "><a href="" class="d-flex align-items-center"><i
|
||||
class="ficon feather ft-image mr-50"></i>
|
||||
Shared
|
||||
Documents</a></li>
|
||||
<li class="mb-50 "><a href="" class="d-flex align-items-center"><i
|
||||
class="ficon feather ft-trash-2 mr-50"></i>
|
||||
Deleted
|
||||
Documents</a></li>
|
||||
<li><a href="" class="d-flex align-items-center"><i class="ficon feather ft-x-circle mr-50"></i> Blocked
|
||||
Contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- app chat user profile left sidebar ends -->
|
||||
<!-- app chat sidebar start -->
|
||||
<div class="chat-sidebar card" id="sidebar-card">
|
||||
<span class="chat-sidebar-close" (click) = "Sidebar($event)">
|
||||
<i class="ficon feather ft-x" ></i>
|
||||
</span>
|
||||
<div class="chat-sidebar-search">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="chat-sidebar-profile-toggle" (click)="showProfile($event)">
|
||||
<div class="avatar">
|
||||
<img *ngIf="loggedInUser.photoURL" src="{{loggedInUser.photoURL}}" class="cursor-pointer" alt="user_avatar" height="36" width="36">
|
||||
<img *ngIf="!loggedInUser.photoURL" src="../../../../assets/images/portrait/small/avatar-s-19.png"
|
||||
alt="avatar" height="36" width="36">
|
||||
<!-- <img src="../../../assets/images/portrait/small/avatar-s-16.png" class="cursor-pointer" alt="user_avatar"
|
||||
height="36" width="36"> -->
|
||||
</div>
|
||||
</div>
|
||||
<fieldset class="form-group position-relative has-icon-left mx-75 mb-0">
|
||||
<input type="text" class="form-control round" id="chat-search" (keyup)="searchContact($event)" placeholder="Search">
|
||||
<div class="form-control-position">
|
||||
<i class="ficon feather ft-search text-dark"></i>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-sidebar-list-wrapper pt-2 " fxFlex="auto" [perfectScrollbar]="config" >
|
||||
<h6 class="px-2 pb-25 mb-0">CHANNELS<i class="ficon feather ft-plus float-right cursor-pointer"></i></h6>
|
||||
<ul class="chat-sidebar-list">
|
||||
<li>
|
||||
<h6 class="mb-0"># Devlopers</h6>
|
||||
</li>
|
||||
<li>
|
||||
<h6 class="mb-0"># Designers</h6>
|
||||
</li>
|
||||
</ul>
|
||||
<h6 class="px-2 pt-2 pb-25 mb-0">CHATS</h6>
|
||||
<ul class="chat-sidebar-list" >
|
||||
<li class = "chatSidebar" *ngFor="let chat of chatList" id="users-list" (click)="loadMyChatRoom(chat)" (click)="contentOverlay($event)"
|
||||
id="_media" [ngClass]="(chat.uid === clickedUser) ? 'active': ''">
|
||||
<div class="d-flex align-items-center" >
|
||||
<div class="avatar m-0 mr-50" ><img [src]="chat.image" height="36"
|
||||
width="36" >
|
||||
<span class="avatar-status-busy"></span>
|
||||
</div>
|
||||
<div class="chat-sidebar-name">
|
||||
<span class="mb-0">{{chat.name}}</span>
|
||||
<span class="badge badge-pill float-right badge-danger mr-2">{{chat.unreadMessageCount ? chat.unreadMessageCount : ''}}</span>
|
||||
<span class="text-muted"></span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<h6 class="px-2 pt-2 pb-25 mb-0">CONTACTS<i class="ficon feather ft-plus float-right cursor-pointer"></i></h6>
|
||||
<ul class="chat-sidebar-list" >
|
||||
<li class = "chatSidebar" *ngFor="let contact of contactList" (click)="showChat(contact)" (click)="contentOverlay($event)"
|
||||
id="_media" [ngClass]="(contact.uid === clickedUser) ? 'active': ''">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="avatar m-0 mr-50"><img [src]="contact.image" height="36"
|
||||
width="36" >
|
||||
<span class="avatar-status-away"></span>
|
||||
</div>
|
||||
<div class="chat-sidebar-name">
|
||||
<h6 class="mb-0">{{contact.name}}</h6><span class="text-muted"> {{contact.showMessage}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- app chat sidebar ends -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-right ">
|
||||
|
||||
<div class="content-overlay" ></div>
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row">
|
||||
</div>
|
||||
<div class="content-body"><!-- app chat overlay -->
|
||||
<div class="chat-overlay " id="overlayChat" (click) = "Sidebar($event)"></div>
|
||||
<!-- app chat window start -->
|
||||
<section class="chat-window-wrapper">
|
||||
<div class="chat-start" id='chat-overlay1'>
|
||||
<span class="ficon feather ft-message-square chat-sidebar-toggle chat-start-icon font-large-3 p-3 mb-1" (click)="showSidebar($event)" ></span>
|
||||
<h4 class="d-none d-lg-block py-50 text-bold-500">Select a contact to start a chat!</h4>
|
||||
<button class="btn btn-light-primary chat-start-text chat-sidebar-toggle d-block d-lg-none py-50 px-1" (click)="showSidebar($event)" >Start
|
||||
Conversation!</button>
|
||||
</div>
|
||||
<div class="chat-area d-none" id = "chat-area d-none">
|
||||
<div class="chat-header">
|
||||
<header class="d-flex justify-content-between align-items-center px-1 py-75">
|
||||
<div class="d-flex align-items-center" >
|
||||
<div class="chat-sidebar-toggle d-block d-lg-none mr-1" id="chat-sidebar"><i
|
||||
class="ficon feather ft-align-justify font-large-1 cursor-pointer" (click)="showSidebar($event)"></i>
|
||||
</div>
|
||||
<div class="avatar chat-profile-toggle m-0 mr-1" (click)="ShowChatProfile($event)">
|
||||
<span >
|
||||
<img [src]="headerImage" class="cursor-pointer" alt="avatar"/>
|
||||
</span>
|
||||
<span class="avatar-status-busy"></span>
|
||||
</div>
|
||||
<h6 class="mb-0">{{headerName}}</h6>
|
||||
</div>
|
||||
<div class="chat-header-icons">
|
||||
|
||||
<span class="chat-icon-favorite" id='chat-icon'(click)="chatFavorite($event)" >
|
||||
<i class="ficon feather ft-star font-medium-5 cursor-pointer"></i>
|
||||
</span>
|
||||
<span class="dropdown">
|
||||
|
||||
<span ngbDropdown [open]="false" [autoClose]="true" class="d-inline-block">
|
||||
<i class="ficon feather ft-more-vertical font-medium-4 ml-25 cursor-pointer dropdown-toggle nav-hide-arrow cursor-pointer"
|
||||
id="dropdownMenuButton" dropdown-menu dropdown-menu-left show data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" role="menu" ngbDropdownToggle>
|
||||
</i>
|
||||
<div ngbDropdownMenu ="dropdownMenuButton">
|
||||
<a class="dropdown-item">Pin to top</a>
|
||||
<a class="dropdown-item">Delete chat</a>
|
||||
<a class="dropdown-item ">Block</a>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
<!-- chat card start -->
|
||||
<div class="card chat-wrapper shadow-none mb-0">
|
||||
<div class="card-content">
|
||||
<div class="card-body chat-container" id="componentRef">
|
||||
<perfect-scrollbar [config]="config" #chatPS>
|
||||
<div class="chat-content" #content>
|
||||
<div id="chatWindow" class="chat" [ngClass]="(currentUserUid === messages.uid)?'chat-right':'chat-left'"
|
||||
*ngFor="let messages of displayChat">
|
||||
<div class="chat-avatar">
|
||||
<a [routerLink]="" class="avatar m-0">
|
||||
<img [src]="messages.userImage" *ngIf="messages.userImage"/>
|
||||
</a>
|
||||
</div>
|
||||
<div class="chat-body">
|
||||
<div class="chat-message">
|
||||
<p>{{messages.message}}</p>
|
||||
<span class="chat-time" title="{{messages.date | date}}">{{messages.date| date: 'HH:mm a'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</perfect-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer chat-footer px-2 py-1 pb-0">
|
||||
<form class="d-flex align-items-center">
|
||||
<i class="ficon feather ft-user cursor-pointer"></i>
|
||||
<i class="ficon feather ft-paperclip ml-1 cursor-pointer"></i>
|
||||
<input type="text" class="form-control chat-message-send mx-1" [(ngModel)]="newMessage" name="newmessage" id="iconLeft4"
|
||||
placeholder="Type your message here...." #box (keyup.enter)="onEnter(box.value)">
|
||||
<button type="submit" class="btn btn-primary glow send d-lg-flex" (click)="sendMessage()"><i class="ficon feather ft-play"></i>
|
||||
<span class="d-none d-lg-block mx-50">Send</span></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- chat card ends -->
|
||||
</div>
|
||||
</section>
|
||||
<section class="chat-profile " id="chat-profile">
|
||||
<header class="chat-profile-header text-center border-bottom">
|
||||
<span class="chat-profile-close" (click)="ChatProfile($event)">
|
||||
<i class="ficon feather ft-x"></i>
|
||||
</span>
|
||||
<div class="my-2">
|
||||
|
||||
<img [src]="headerImage" class="round mb-1" alt="chat avatar"
|
||||
height="100" width="100">
|
||||
|
||||
<h5 class="app-chat-user-name mb-0">{{headerName}}</h5>
|
||||
<span>Devloper</span>
|
||||
</div>
|
||||
</header>
|
||||
<div class="chat-profile-content p-2">
|
||||
<h6 class="mt-1">ABOUT</h6>
|
||||
<p>It is a long established fact that a reader will be distracted by the readable content.</p>
|
||||
<h6 class="mt-2">PERSONAL INFORMATION</h6>
|
||||
<ul class="list-unstyled">
|
||||
<li class="mb-25">email@gmail.com</li>
|
||||
<li>+1(789) 950-7654</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
<!-- app chat window ends -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- END: Content-->
|
||||
|
||||
<!-- app chat profile right sidebar ends -->
|
||||
25
src/app/content/applications/chat/chats.component.spec.ts
Normal file
25
src/app/content/applications/chat/chats.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { ChatsComponent } from './chats.component';
|
||||
|
||||
describe('ChatComponent', () => {
|
||||
let component: ChatsComponent;
|
||||
let fixture: ComponentFixture<ChatsComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ChatsComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ChatsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
543
src/app/content/applications/chat/chats.component.ts
Normal file
543
src/app/content/applications/chat/chats.component.ts
Normal file
@@ -0,0 +1,543 @@
|
||||
import { Component, OnInit, AfterViewInit, ViewChild, Renderer2, ViewChildren, QueryList, ElementRef } from '@angular/core';
|
||||
import { PerfectScrollbarConfigInterface, PerfectScrollbarComponent, PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
|
||||
import { UserService } from '../../../../../src/app/_api/user/user.service';
|
||||
import { ChatService } from '../../../../../src/app/_api/chat/chat.service';
|
||||
import { Chats } from './chats';
|
||||
import { AppConstants } from '../../../_helpers/app.constants';
|
||||
import * as _ from 'lodash';
|
||||
@Component({
|
||||
selector: 'app-chat',
|
||||
templateUrl: './chats.component.html',
|
||||
styleUrls: ['./chats.component.css']
|
||||
})
|
||||
|
||||
export class ChatsComponent implements OnInit, AfterViewInit {
|
||||
showicon: boolean;
|
||||
name: any;
|
||||
isicon: boolean;
|
||||
isactive: boolean;
|
||||
isSelected: boolean;
|
||||
chatArray: any;
|
||||
status = true;
|
||||
newMessage = '';
|
||||
contactId: string;
|
||||
messageInfo: any;
|
||||
userInfo: any;
|
||||
public displayName: boolean;
|
||||
public config: PerfectScrollbarConfigInterface = { wheelPropagation: false };
|
||||
|
||||
@ViewChild('chatPS') public chatPS?: PerfectScrollbarComponent;
|
||||
@ViewChild(PerfectScrollbarDirective, { static: true })
|
||||
directiveRef?: PerfectScrollbarDirective;
|
||||
@ViewChildren('messages') messages: QueryList<any>;
|
||||
@ViewChild('content', { static: true }) content: ElementRef;
|
||||
|
||||
contactList = [];
|
||||
contactChats = [];
|
||||
headerName: string;
|
||||
headerImage: any;
|
||||
showChatInProgress = false;
|
||||
createInProgress = false;
|
||||
contactMaster = this.contactList;
|
||||
chatListMaster = [];
|
||||
temp = [];
|
||||
loggedInUser = JSON.parse(localStorage.getItem('currentUser'));
|
||||
currentUserUid = this.loggedInUser.uid;
|
||||
|
||||
currentUser = ''; // UID of user 1
|
||||
clickedUser = ''; // UID of user 2
|
||||
chatList = [];
|
||||
displayChat = [];
|
||||
chatId = '';
|
||||
senderImage = '';
|
||||
currentUserImage = '';
|
||||
loadContacts = false;
|
||||
prevMsg = '';
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param ApplicationApiService chatApiService;
|
||||
* @param Renderer2 renderer
|
||||
*/
|
||||
constructor(
|
||||
private renderer: Renderer2,
|
||||
private userService: UserService,
|
||||
private chatService: ChatService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll chat to bottom
|
||||
*/
|
||||
ngAfterViewInit() {
|
||||
this.messages.forEach(this.scrollToBottom);
|
||||
this.messages.changes.subscribe(this.scrollToBottom);
|
||||
}
|
||||
|
||||
getLoggedInUserChats () {
|
||||
if (this.contactChats) {
|
||||
const chatsWithHistory = this.contactChats.filter((item: Chats) => {
|
||||
return item.chatHistory.length > 0;
|
||||
});
|
||||
const loggedInUserChats = chatsWithHistory.filter(chatHistory => {
|
||||
return chatHistory.name.indexOf(this.loggedInUser.uid) !== -1;
|
||||
});
|
||||
return loggedInUserChats;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* OnInit
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.userService.getUsers().subscribe(users => {
|
||||
let contactList = users.map(item => {
|
||||
return {
|
||||
...item.payload.doc.data() as {},
|
||||
id: item.payload.doc['id']
|
||||
};
|
||||
});
|
||||
contactList = contactList.filter(element => {
|
||||
return this.loggedInUser.uid !== element['uid'];
|
||||
});
|
||||
this.contactMaster = contactList;
|
||||
this.chatService.getChats().subscribe(chats => {
|
||||
this.chatList = [];
|
||||
this.contactList = [];
|
||||
const chatRooms = chats.map(item => {
|
||||
return {
|
||||
...item.payload.doc.data() as Chats,
|
||||
id: item.payload.doc['id']
|
||||
};
|
||||
});
|
||||
this.contactChats = chatRooms;
|
||||
const loggedInUserChats = this.getLoggedInUserChats();
|
||||
|
||||
const contactListMap = [];
|
||||
const chatListMap = [];
|
||||
|
||||
this.contactMaster.forEach(element => {
|
||||
const userChat = this.isChatExistsWithUser(loggedInUserChats, element.uid);
|
||||
if (userChat && !chatListMap[element.uid]) {
|
||||
element['chatRoomId'] = userChat['id'];
|
||||
if (userChat['chatHistory'] && userChat['chatHistory'].length > 0) {
|
||||
const unreadMessages = userChat['chatHistory'].filter( history => {
|
||||
return history.uid !== this.loggedInUser.uid && history.status === 'send';
|
||||
});
|
||||
if (unreadMessages.length > 0 && this.clickedUser !== element.uid) {
|
||||
element['unreadMessageCount'] = unreadMessages.length;
|
||||
} else {
|
||||
element['unreadMessageCount'] = 0;
|
||||
}
|
||||
element['chatHistory'] = userChat['chatHistory'];
|
||||
}
|
||||
chatListMap[element.uid] = true;
|
||||
this.chatList.push(element);
|
||||
this.chatListMaster.push(element);
|
||||
} else if (!contactListMap[element.uid]) {
|
||||
contactListMap[element.uid] = true;
|
||||
this.contactList.push(element);
|
||||
}
|
||||
});
|
||||
this.chatList = _.orderBy(this.chatList, [user => user.name.toLowerCase()], ['asc']);
|
||||
this.contactList = _.orderBy(this.contactList, [user => user.name && user.name.toLowerCase()], ['asc']);
|
||||
this.currentUserImage = this.loggedInUser.photoURL;
|
||||
this.senderImage = this.contactList[0].image;
|
||||
this.createInProgress = false;
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
isChatExistsWithUser (userChats, userId) {
|
||||
for (let index = 0; index < userChats.length; index++) {
|
||||
if (userChats[index].name.indexOf(userId) !== -1) {
|
||||
return userChats[index];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chat scroll to bottom
|
||||
*/
|
||||
scrollToBottom = () => {
|
||||
try {
|
||||
this.content.nativeElement.scrollTop = this.content.nativeElement.scrollHeight;
|
||||
this.chatPS.directiveRef.scrollToBottom(0, 500);
|
||||
} catch (err) { }
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter Chat
|
||||
*
|
||||
* @param event search event
|
||||
*/
|
||||
searchContact (event) {
|
||||
const value = event.target.value.toLowerCase();
|
||||
// filter our data
|
||||
let temp = this.contactMaster.filter(function (d) {
|
||||
return d.name && d.name.toLowerCase().indexOf(value) !== -1 || !value;
|
||||
});
|
||||
const loggedInUserChats = this.getLoggedInUserChats();
|
||||
const _self = this;
|
||||
temp = temp.filter(function (user) {
|
||||
return !_self.isChatExistsWithUser(loggedInUserChats, user.uid);
|
||||
});
|
||||
// update the rows
|
||||
this.contactList = [];
|
||||
const contactListMap = [];
|
||||
temp.forEach(element => {
|
||||
if (!contactListMap[element.uid]) {
|
||||
contactListMap[element.uid] = true;
|
||||
this.contactList.push(element);
|
||||
}
|
||||
});
|
||||
|
||||
// filter our data
|
||||
const tempChat = this.chatListMaster.filter(function (d) {
|
||||
return d.name && d.name.toLowerCase().indexOf(value) !== -1 || !value;
|
||||
});
|
||||
// update the rows
|
||||
this.chatList = [];
|
||||
const chatListMap = [];
|
||||
tempChat.forEach(element => {
|
||||
if (!chatListMap[element.uid]) {
|
||||
chatListMap[element.uid] = true;
|
||||
this.chatList.push(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message
|
||||
*/
|
||||
sendMessage() {
|
||||
if (this.newMessage !== null && this.newMessage !== '') {
|
||||
this.messageInfo = {
|
||||
message: this.newMessage,
|
||||
date: Date.now(),
|
||||
uid: this.loggedInUser.uid,
|
||||
status: 'send'
|
||||
};
|
||||
if (this.chatId !== '') {
|
||||
this.chatService.sendMessage(this.chatId, this.messageInfo);
|
||||
} else {
|
||||
this.currentUser = this.loggedInUser.uid;
|
||||
const roomName = (this.currentUser < this.clickedUser ? this.currentUser + '_' +
|
||||
this.clickedUser : this.clickedUser + '_' + this.currentUser);
|
||||
this.userInfo = {
|
||||
uid: this.loggedInUser.uid,
|
||||
name: roomName,
|
||||
image: this.loggedInUser.photoURL,
|
||||
time: Date.now(),
|
||||
showMessage: '',
|
||||
badge: '',
|
||||
showicon: true,
|
||||
isicon: false,
|
||||
isactive: 'online',
|
||||
isSelected: false,
|
||||
chatHistory: []
|
||||
};
|
||||
// Add message to box before sending
|
||||
this.displayChat.push(this.messageInfo);
|
||||
this.createInProgress = true;
|
||||
this.chatService.createChatRoom(this.userInfo).then(chatRoom => {
|
||||
this.chatId = chatRoom.id;
|
||||
this.loadChatRoom(chatRoom.id);
|
||||
this.chatService.sendMessage(this.chatId, this.messageInfo);
|
||||
this.createInProgress = false;
|
||||
});
|
||||
}
|
||||
this.newMessage = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Message send on Enter
|
||||
*
|
||||
* @param value New message
|
||||
*/
|
||||
onEnter(value: string) {
|
||||
this.newMessage = value;
|
||||
this.sendMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display chat when click on contact
|
||||
*
|
||||
* @param friendId Friend id
|
||||
*/
|
||||
showChat(data) {
|
||||
if (this.showChatInProgress || this.createInProgress) {
|
||||
return;
|
||||
}
|
||||
this.showChatInProgress = true;
|
||||
this.currentUser = this.loggedInUser.uid;
|
||||
this.currentUserImage = this.loggedInUser.photoURL;
|
||||
this.clickedUser = data.uid;
|
||||
this.contactId = data.id;
|
||||
this.senderImage = data.image;
|
||||
this.showHeaderData();
|
||||
const roomName = (this.currentUser < this.clickedUser ? this.currentUser + '_' +
|
||||
this.clickedUser : this.clickedUser + '_' + this.currentUser);
|
||||
|
||||
this.userInfo = {
|
||||
uid: this.loggedInUser.uid,
|
||||
name: roomName,
|
||||
image: this.loggedInUser.photoURL,
|
||||
time: Date.now(),
|
||||
showMessage: '',
|
||||
badge: '',
|
||||
showicon: true,
|
||||
isicon: false,
|
||||
isactive: 'online',
|
||||
isSelected: false,
|
||||
chatHistory: []
|
||||
};
|
||||
|
||||
if (this.contactChats.length === 0) {
|
||||
this.createAndLoadChatRoom();
|
||||
} else if (this.contactChats.length !== 0) {
|
||||
let chatExists = false;
|
||||
for (let i = 0; i < this.contactChats.length; i++) {
|
||||
const room = this.contactChats[i].name;
|
||||
if (room === roomName) {
|
||||
chatExists = true;
|
||||
this.chatId = this.contactChats[i].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!chatExists) {
|
||||
this.createAndLoadChatRoom();
|
||||
} else {
|
||||
// subscribe
|
||||
this.loadChatRoom(this.chatId);
|
||||
this.showChatInProgress = false;
|
||||
this.userInfo.isSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createAndLoadChatRoom() {
|
||||
this.createInProgress = true;
|
||||
this.chatService.createChatRoom(this.userInfo).then(chatRoom => {
|
||||
this.chatId = chatRoom.id;
|
||||
this.loadChatRoom(chatRoom.id);
|
||||
});
|
||||
}
|
||||
|
||||
setUserImage(chatHistory) {
|
||||
for (let i = 0; i < chatHistory.length; i++) {
|
||||
if (chatHistory.length > 0) {
|
||||
if (i > 0) {
|
||||
this.prevMsg = chatHistory[i - 1];
|
||||
}
|
||||
if (i > 0 && chatHistory[i].uid === this.prevMsg['uid']) {
|
||||
continue;
|
||||
}
|
||||
if (chatHistory[i].uid === this.loggedInUser.uid) {
|
||||
chatHistory[i]['userImage'] = this.currentUserImage;
|
||||
} else {
|
||||
chatHistory[i]['userImage'] = this.senderImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loadMyChatRoom(selectedUser) {
|
||||
this.chatId = selectedUser.chatRoomId;
|
||||
this.loadChatRoom(selectedUser.chatRoomId);
|
||||
this.clickedUser = selectedUser.uid;
|
||||
this.contactId = selectedUser.id;
|
||||
this.senderImage = selectedUser.image;
|
||||
this.headerName = selectedUser.name;
|
||||
this.headerImage = selectedUser.image;
|
||||
this.setHistoryAsRead(selectedUser, selectedUser.chatRoomId, selectedUser.chatHistory);
|
||||
}
|
||||
|
||||
setHistoryAsRead (selectedUser, chatRoomId, history) {
|
||||
let unreadMsgExists = false;
|
||||
history.forEach(element => {
|
||||
if (element.uid !== this.loggedInUser.uid && element.status !== 'read') {
|
||||
element.status = 'read';
|
||||
unreadMsgExists = true;
|
||||
}
|
||||
});
|
||||
if (unreadMsgExists) {
|
||||
this.chatService.updateChatStatus(chatRoomId, history).then(result => {
|
||||
delete selectedUser.unreadMessageCount;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
loadChatRoom(chatRoomId) {
|
||||
this.chatService.showChat(chatRoomId).subscribe(res => {
|
||||
if (chatRoomId === this.chatId) {
|
||||
this.setUserImage(res.chatHistory);
|
||||
this.displayChat = res['chatHistory'];
|
||||
this.chatId = res['chatId'];
|
||||
}
|
||||
this.showChatInProgress = false;
|
||||
this.scrollToBottom();
|
||||
});
|
||||
}
|
||||
|
||||
showDefaultChat() {
|
||||
this.currentUser = this.loggedInUser.uid;
|
||||
const roomName = (this.currentUser < this.clickedUser ? this.currentUser + '_' +
|
||||
this.clickedUser : this.clickedUser + '_' + this.currentUser);
|
||||
for (let j = 0; j < this.contactChats.length; j++) {
|
||||
if (this.contactChats[j].name === roomName) {
|
||||
if (this.contactChats[j].chatHistory && this.contactChats[j].chatHistory.length > 0) {
|
||||
this.displayChat = this.contactChats[j].chatHistory;
|
||||
this.setUserImage(this.contactChats[j].chatHistory);
|
||||
}
|
||||
this.chatId = this.contactChats[j].id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
showLastMessage() {
|
||||
for (let i = 0; i < this.contactList.length; i++) {
|
||||
if (this.contactList[i]) {
|
||||
for (let j = 0; j < this.contactChats.length; j++) {
|
||||
const room = this.contactChats[j].name;
|
||||
const index = room.indexOf(this.contactList[i].uid);
|
||||
const currentUser = this.loggedInUser.uid;
|
||||
const userUid = this.contactList[i].uid;
|
||||
const roomName = (currentUser < userUid ? currentUser + '_' +
|
||||
userUid : userUid + '_' + currentUser);
|
||||
if (index >= 0) {
|
||||
if (this.contactChats[j].chatHistory.length > 0 && roomName === room) {
|
||||
this.contactList[i]['lastmsg'] = this.contactChats[j].chatHistory[this.contactChats[j].chatHistory.length - 1].message;
|
||||
this.contactList[i]['isActive'] = this.contactChats[j].isactive;
|
||||
this.contactList[i]['icon'] = this.contactChats[j].isicon;
|
||||
this.contactList[i]['showicon'] = this.contactChats[j].showicon;
|
||||
this.contactList[i]['lastmsgTime'] = this.contactChats[j].chatHistory[this.contactChats[j].chatHistory.length - 1].date;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overlay add/remove fuction in responsive
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
|
||||
contentOverlay(event) {
|
||||
const toggleIcon = document.getElementById('chat-overlay1');
|
||||
const toggle = document.getElementById('chat-area d-none');
|
||||
if (event.currentTarget.className === 'chatSidebar ng-star-inserted') {
|
||||
this.renderer.addClass(toggleIcon, 'd-none');
|
||||
this.renderer.removeClass(toggle, 'd-none');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Show add/remove class at open profile
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
showProfile(event) {
|
||||
const toggleIcon = document.getElementById('user-profile');
|
||||
const toggle = document.getElementById('overlayChat');
|
||||
if (event.currentTarget.className === 'chat-sidebar-profile-toggle') {
|
||||
this.renderer.addClass(toggleIcon, 'show');
|
||||
this.renderer.addClass(toggle, 'show');
|
||||
} else if (event.currentTarget.className === 'chat-profile-close') {
|
||||
this.renderer.removeClass(toggleIcon, 'show');
|
||||
this.renderer.removeClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Show add/remove function in responsive
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
Sidebar(event) {
|
||||
const toggleChat = document.getElementById('sidebar-card');
|
||||
const toggleIcon = document.getElementById('chat-profile');
|
||||
const toggle = document.getElementById('overlayChat');
|
||||
if (event.currentTarget.className === 'chat-sidebar-close' || 'chat-overlay') {
|
||||
this.renderer.removeClass(toggle, 'show');
|
||||
this.renderer.removeClass(toggleIcon, 'show');
|
||||
this.renderer.removeClass(toggleChat, 'show');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Show add/remove function in responsive
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
showSidebar(event) {
|
||||
if (window.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH) {
|
||||
const toggleIcon = document.getElementById('sidebar-card');
|
||||
const toggle = document.getElementById('overlayChat');
|
||||
const toggleChat = document.getElementById('sidebar-left');
|
||||
if (event.currentTarget.className === 'ficon feather ft-message-square chat-sidebar-toggle chat-start-icon font-large-3 p-3 mb-1' ||
|
||||
'ficon feather ft-align-justify font-large-1 cursor-pointer') {
|
||||
this.renderer.addClass(toggle, 'show');
|
||||
this.renderer.addClass(toggleIcon, 'show');
|
||||
}
|
||||
if (window.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH) {
|
||||
this.renderer.removeClass(toggleChat, 'sidebar-fixed');
|
||||
}
|
||||
}
|
||||
}
|
||||
// FixChat() {
|
||||
// const toggleIcon = document.getElementById('sidebar-left');
|
||||
// if (window.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH) {
|
||||
// this.renderer.removeClass(toggleIcon, 'sidebar-fixed');
|
||||
// }
|
||||
// }
|
||||
chatFavorite(event) {
|
||||
const chatIcon = document.getElementById('chat-icon');
|
||||
if (event.currentTarget.className === 'chat-icon-favorite') {
|
||||
this.renderer.addClass(chatIcon, 'warning');
|
||||
} else if (event.currentTarget.className === 'chat-icon-favorite warning') {
|
||||
this.renderer.removeClass(chatIcon, 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
showHeaderData() {
|
||||
this.contactList.forEach(element => {
|
||||
if (this.clickedUser === element['uid']) {
|
||||
this.headerName = element.name;
|
||||
this.headerImage = element.image;
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Show add/remove function
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
ShowChatProfile(event) {
|
||||
const toggleIcon = document.getElementById('chat-profile');
|
||||
const toggle = document.getElementById('overlayChat');
|
||||
if (event.currentTarget.className === 'avatar chat-profile-toggle m-0 mr-1') {
|
||||
this.renderer.addClass(toggleIcon, 'show');
|
||||
this.renderer.addClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Show add/remove function
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
ChatProfile(event) {
|
||||
const toggleIcon = document.getElementById('chat-profile');
|
||||
const toggle = document.getElementById('overlayChat');
|
||||
if (event.currentTarget.className === 'chat-profile-close') {
|
||||
this.renderer.removeClass(toggleIcon, 'show');
|
||||
this.renderer.removeClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
13
src/app/content/applications/chat/chats.module.spec.ts
Normal file
13
src/app/content/applications/chat/chats.module.spec.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { ChatsModule } from './chats.module';
|
||||
|
||||
describe('ChatModule', () => {
|
||||
let chatsModule: ChatsModule;
|
||||
|
||||
beforeEach(() => {
|
||||
chatsModule = new ChatsModule();
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
expect(chatsModule).toBeTruthy();
|
||||
});
|
||||
});
|
||||
33
src/app/content/applications/chat/chats.module.ts
Normal file
33
src/app/content/applications/chat/chats.module.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ChatsComponent } from './chats.component';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
|
||||
import { ChatService } from 'src/app/_api/chat/chat.service';
|
||||
import { StaticChatComponent } from './static-chat/static-chat.component';
|
||||
import { ApplicationApiService } from 'src/app/_services/application-api.service';
|
||||
import { ToastrModule } from 'ngx-toastr';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
NgbModule,
|
||||
ToastrModule.forRoot(),
|
||||
PerfectScrollbarModule,
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: ChatsComponent
|
||||
},
|
||||
{
|
||||
path: 'static-chat',
|
||||
component: StaticChatComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
declarations: [ChatsComponent, StaticChatComponent],
|
||||
providers: [ChatService, ApplicationApiService]
|
||||
})
|
||||
export class ChatsModule { }
|
||||
20
src/app/content/applications/chat/chats.ts
Normal file
20
src/app/content/applications/chat/chats.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
export class Chats {
|
||||
uid: string;
|
||||
senderUid: string;
|
||||
name: string;
|
||||
image: string;
|
||||
time: Date;
|
||||
showMessage: String;
|
||||
badge: String;
|
||||
showicon: boolean;
|
||||
isicon: boolean;
|
||||
isactive: boolean;
|
||||
isSelected: boolean;
|
||||
chatHistory: Array<ChatHistory>;
|
||||
}
|
||||
|
||||
export class ChatHistory {
|
||||
date: Date;
|
||||
message: string;
|
||||
uid: string;
|
||||
}
|
||||
86
src/app/content/applications/chat/static-chat/Untitled-2.txt
Normal file
86
src/app/content/applications/chat/static-chat/Untitled-2.txt
Normal file
@@ -0,0 +1,86 @@
|
||||
<div class="content-right">
|
||||
<!-- <div class="content-wrapper"> -->
|
||||
<div class="content-header row"></div>
|
||||
<div class="content-overlay"></div>
|
||||
<div class="chat-header">
|
||||
<header class="d-flex justify-content-between align-items-center px-1 py-75">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="chat-sidebar-toggle d-block d-lg-none mr-1"><i
|
||||
class="ft-align-justify font-large-1 cursor-pointer"></i>
|
||||
</div>
|
||||
<div class="avatar chat-profile-toggle m-0 mr-1">
|
||||
<img src="../../../assets/images/portrait/small/avatar-s-26.png" class="cursor-pointer" alt="avatar"
|
||||
height="36" width="36" />
|
||||
<span class="avatar-status-busy"></span>
|
||||
</div>
|
||||
<h6 class="mb-0">Elizabeth Elliott</h6>
|
||||
</div>
|
||||
<div class="chat-header-icons">
|
||||
<span class="chat-icon-favorite">
|
||||
<i class="ficon feather ft-star font-medium-5 cursor-pointer"></i>
|
||||
</span>
|
||||
<span class="dropdown">
|
||||
<i class="ficon feather ft-more-vertical font-medium-4 ml-25 cursor-pointer dropdown-toggle nav-hide-arrow cursor-pointer"
|
||||
id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" role="menu">
|
||||
</i>
|
||||
<span class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenuButton">
|
||||
<a class="dropdown-item" href="JavaScript:void(0);"><i class="ficon feather ft-tag mr-25"></i> Pin to top</a>
|
||||
<a class="dropdown-item" href="JavaScript:void(0);"><i class="ficon feather ft-trash-2 mr-25"></i> Delete chat</a>
|
||||
<a class="dropdown-item" href="JavaScript:void(0);"><i class="ficon feather ft-x-circle mr-25"></i> Block</a>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
<div class="card chat-wrapper shadow-none mb-0">
|
||||
<div class="card-content">
|
||||
<div class="content-body chat-container">
|
||||
<div class="chat-content">
|
||||
<div class="chat">
|
||||
<div class="chat-avatar">
|
||||
<div class="content-overlay" id='content-overlay' (click)="contentOverlay($event)"></div>
|
||||
<section class="chat-app-window" #content>
|
||||
<div class="sidebar-toggle d-block d-lg-none" (click)="sidebar($event)"><i class="feather ft-menu font-large-1"></i></div>
|
||||
<div class="badge badge-secondary mb-1">Chat History</div>
|
||||
<div class="chats" #messages>
|
||||
<div class="chat" [ngClass]="{'chat-right': messages.sender == 0 , 'chat-left': messages.sender == 1 }"
|
||||
*ngFor="let messages of contactChat">
|
||||
<div class="chat-avatar">
|
||||
<a [routerLink]="" class="avatar">
|
||||
<span class="avatar-online"><img [src]="messages.senderImage" /></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="chat-body">
|
||||
<div class="chat-content">
|
||||
<p>{{messages.message}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="chat-app-form">
|
||||
<form class="chat-app-input d-flex">
|
||||
<fieldset class="form-group position-relative has-icon-left col-10 m-0">
|
||||
<div class="form-control-position">
|
||||
<i class="icon-emoticon-smile"></i>
|
||||
</div>
|
||||
<input type="text" class="form-control" [(ngModel)]="newMessage" name="newmessage" id="iconLeft4"
|
||||
placeholder="Type your message" #box (keyup.enter)="onEnter(box.value)">
|
||||
<div class="form-control-position control-position-right">
|
||||
<i class="feather ft-image"></i>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="form-group position-relative has-icon-left col-2 m-0">
|
||||
<button type="button" class="btn btn-primary" (click)="sendMessage()" keyboardShouldPersistTaps={true}><i
|
||||
class="la la-paper-plane-o d-lg-none"></i><span class="d-none d-lg-block">Send</span></button>
|
||||
</fieldset>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
:host ::ng-deep .content-right {
|
||||
width: calc(100% - 300px) !important;
|
||||
}
|
||||
:host ::ng-deep .mx-75 {
|
||||
margin-left: .75rem!important;
|
||||
margin-right: .75rem!important;
|
||||
}
|
||||
:host ::ng-deep .py-75 {
|
||||
padding-bottom: .75rem!important;
|
||||
padding-top: .75rem!important;
|
||||
}
|
||||
:host ::ng-deep .px-1 {
|
||||
padding-left: 1rem!important;
|
||||
padding-right: 1rem!important;
|
||||
}
|
||||
:host ::ng-deep .mr-50, .mx-50 {
|
||||
margin-right: .5rem!important;
|
||||
margin-left: .5rem!important;
|
||||
}
|
||||
:host ::ng-deep .mb-50, .my-50 {
|
||||
margin-bottom: .5rem!important;
|
||||
}
|
||||
:host ::ng-deep .dropdown-menu
|
||||
{
|
||||
transform: translate3d(-131px, 18px, 0px) !important;
|
||||
}
|
||||
:host ::ng-deep .chat-sidebar .chat-sidebar-list-wrapper {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
:host ::ng-deep .sidebar-fixed {
|
||||
overflow: hidden !important;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .app-content {
|
||||
overflow-y: hidden !important;
|
||||
}
|
||||
:host ::ng-deep .pb-25, .py-25 {
|
||||
padding-bottom: .25rem!important;
|
||||
}
|
||||
:host ::ng-deep .ml-25, .mx-25 {
|
||||
margin-left: .25rem!important;
|
||||
}
|
||||
@media(max-width:767px) {
|
||||
:host ::ng-deep .chat-footer
|
||||
{
|
||||
position: relative !important;
|
||||
bottom: 17px !important;
|
||||
}
|
||||
}
|
||||
@media(max-width:767px) {
|
||||
:host ::ng-deep .chat-wrapper
|
||||
{
|
||||
background-color: unset !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media(max-width:767px) {
|
||||
:host ::ng-deep .content-right {
|
||||
width: calc(100% - 0px) !important;
|
||||
}
|
||||
}
|
||||
:host ::ng-deep .d-inline-block {
|
||||
display: inline !important;
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
<div class="app-content content" >
|
||||
<div class="sidebar-left " id="sidebar-left">
|
||||
<div class="sidebar"><!-- app chat user profile left sidebar start -->
|
||||
<div class="chat-user-profile" id="user-profile" >
|
||||
<header class="chat-user-profile-header text-center border-bottom">
|
||||
<span class="chat-profile-close" (click)="showProfile($event)" >
|
||||
<i class="ficon feather ft-x" ></i>
|
||||
</span>
|
||||
<div class="my-2">
|
||||
|
||||
<img src="../../../assets/images/portrait/small/avatar-s-19.png" class="round mb-1" alt="user_avatar"
|
||||
height="100" width="100" >
|
||||
|
||||
<h5 class="mb-0">John Doe</h5>
|
||||
<span>Designer</span>
|
||||
</div>
|
||||
</header>
|
||||
<div class="chat-user-profile-content">
|
||||
<div class="chat-user-profile-scroll" fxFlex="auto" [perfectScrollbar]="config">
|
||||
<h6 class="text-uppercase mb-1">ABOUT</h6>
|
||||
<p class="mb-2">It is a long established fact that a reader will be distracted by the readable content .</p>
|
||||
<h6>PERSONAL INFORAMTION</h6>
|
||||
<ul class="list-unstyled mb-2">
|
||||
<li class="mb-25">email@gmail.com</li>
|
||||
<li>+1(789) 950 -7654</li>
|
||||
</ul>
|
||||
<h6 class="text-uppercase mb-1">CHANNELS</h6>
|
||||
<ul class="list-unstyled mb-2">
|
||||
<li><a href=""># Devlopers</a></li>
|
||||
<li><a href=""># Designers</a></li>
|
||||
</ul>
|
||||
<h6 class="text-uppercase mb-1">SETTINGS</h6>
|
||||
<ul class="list-unstyled">
|
||||
<li class="mb-50 "><a href="" class="d-flex align-items-center"><i class="ficon feather ft-tag mr-50"></i>
|
||||
Add
|
||||
Tag</a></li>
|
||||
<li class="mb-50 "><a href="" class="d-flex align-items-center"><i class="ficon feather ft-star mr-50"></i>
|
||||
Important Contact</a>
|
||||
</li>
|
||||
<li class="mb-50 "><a href="" class="d-flex align-items-center"><i
|
||||
class="ficon feather ft-image mr-50"></i>
|
||||
Shared
|
||||
Documents</a></li>
|
||||
<li class="mb-50 "><a href="" class="d-flex align-items-center"><i
|
||||
class="ficon feather ft-trash-2 mr-50"></i>
|
||||
Deleted
|
||||
Documents</a></li>
|
||||
<li><a href="" class="d-flex align-items-center"><i class="ficon feather ft-x-circle mr-50"></i> Blocked
|
||||
Contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- app chat user profile left sidebar ends -->
|
||||
<!-- app chat sidebar start -->
|
||||
<div class="chat-sidebar card " id="sidebar-card">
|
||||
<span class="chat-sidebar-close" (click) = "Sidebar($event)">
|
||||
<i class="ficon feather ft-x" ></i>
|
||||
</span>
|
||||
<div class="chat-sidebar-search">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="chat-sidebar-profile-toggle" (click)="showProfile($event)">
|
||||
<div class="avatar">
|
||||
<img src="../../../assets/images/portrait/small/avatar-s-19.png" class="cursor-pointer" alt="user_avatar"
|
||||
height="36" width="36">
|
||||
</div>
|
||||
</div>
|
||||
<fieldset class="form-group position-relative has-icon-left mx-75 mb-0">
|
||||
<input type="text" class="form-control round" id="chat-search" (keyup)="updateFilter($event)" (keyup)="updateFilter1($event)" placeholder="Search">
|
||||
<div class="form-control-position">
|
||||
<i class="ficon feather ft-search text-dark"></i>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-sidebar-list-wrapper pt-2 " [perfectScrollbar]="config" style="top: 0px; height: 450px;">
|
||||
<h6 class="px-2 pb-25 mb-0">CHANNELS<i class="ficon feather ft-plus float-right cursor-pointer"></i></h6>
|
||||
<ul class="chat-sidebar-list">
|
||||
<li>
|
||||
<h6 class="mb-0"># Devlopers</h6>
|
||||
</li>
|
||||
<li>
|
||||
<h6 class="mb-0"># Designers</h6>
|
||||
</li>
|
||||
</ul>
|
||||
<h6 class="px-2 pt-2 pb-25 mb-0">CHATS</h6>
|
||||
<ul class="chat-sidebar-list" >
|
||||
<li class = "chatSidebar" *ngFor="let chats of chatsList" id="users-list" (click)="contentOverlay($event)"
|
||||
(click)="showChat(chats.friendId,1)" [ngClass]="{'active':chats.isSelected === true, '':chats.isSelected === false}">
|
||||
<div class="d-flex align-items-center" >
|
||||
<div class="avatar m-0 mr-50" ><img [src]="chats.image" height="36"
|
||||
width="36" alt="sidebar user image">
|
||||
<span class="avatar-status-busy"></span>
|
||||
</div>
|
||||
<div class="chat-sidebar-name">
|
||||
<h6 class="mb-0">{{chats.name}}</h6><span class="text-muted">{{chats.showMessage}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<h6 class="px-2 pt-2 pb-25 mb-0">CONTACTS<i class="ficon feather ft-plus float-right cursor-pointer"></i></h6>
|
||||
<ul class="chat-sidebar-list" >
|
||||
<li class = "chatSidebar" *ngFor="let contact of contactList" (click)="contentOverlay($event)"
|
||||
(click)="showChat(contact.friendId,2)" id="_media" [ngClass]="{'active':contact.isSelected === true, '':contact.isSelected === false}">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="avatar m-0 mr-50"><img [src]="contact.image">
|
||||
<span class="avatar-status-away"></span>
|
||||
</div>
|
||||
<div class="chat-sidebar-name">
|
||||
<h6 class="mb-0">{{contact.name}}</h6><span class="text-muted"> {{contact.showMessage}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- app chat sidebar ends -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-right ">
|
||||
|
||||
<div class="content-overlay" ></div>
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row">
|
||||
</div>
|
||||
<div class="content-body"><!-- app chat overlay -->
|
||||
<div class="chat-overlay " (click) = "Sidebar($event)" id="overlayChat" ></div>
|
||||
<!-- app chat window start -->
|
||||
<section class="chat-window-wrapper">
|
||||
<div class="chat-start" id='chat-overlay1'>
|
||||
<span class="ficon feather ft-message-square chat-sidebar-toggle chat-start-icon font-large-3 p-3 mb-1" (click)="showSidebar($event)" ></span>
|
||||
<h4 class="d-none d-lg-block py-50 text-bold-500">Select a contact to start a chat!</h4>
|
||||
<button class="btn btn-light-primary chat-start-text chat-sidebar-toggle d-block d-lg-none py-50 px-1" (click)="showSidebar($event)">Start
|
||||
Conversation!</button>
|
||||
</div>
|
||||
<div class="chat-area d-none" id = "chat-area d-none">
|
||||
<div class="chat-header">
|
||||
<header class="d-flex justify-content-between align-items-center px-1 py-75">
|
||||
<div class="d-flex align-items-center" *ngFor="let chats of headerChat">
|
||||
<div class="chat-sidebar-toggle d-block d-lg-none mr-1" id="chat-sidebar"><i
|
||||
class="ficon feather ft-align-justify font-large-1 cursor-pointer" (click)="showSidebar($event)"></i>
|
||||
</div>
|
||||
<div class="avatar chat-profile-toggle m-0 mr-1" (click)="ShowChatProfile($event)">
|
||||
<span >
|
||||
<img [src]="chats.headerImage" class="cursor-pointer" alt="avatar"/>
|
||||
</span>
|
||||
<span class="avatar-status-busy"></span>
|
||||
</div>
|
||||
<h6 class="mb-0">{{chats.senderName}}</h6>
|
||||
</div>
|
||||
<div class="chat-header-icons">
|
||||
|
||||
<span class="chat-icon-favorite" id='chat-icon' (click)="chatFavorite($event)">
|
||||
<i class="ficon feather ft-star font-medium-5 cursor-pointer"></i>
|
||||
</span>
|
||||
<span ngbDropdown [open]="false" [autoClose]="true" class="d-inline-block dropdown">
|
||||
<i class="ficon feather ft-more-vertical font-medium-4 ml-25 cursor-pointer dropdown-toggle nav-hide-arrow cursor-pointer"
|
||||
id="dropdownMenuButton" dropdown-menu dropdown-menu-left show data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" role="menu" ngbDropdownToggle>
|
||||
</i>
|
||||
<div ngbDropdownMenu ="dropdownMenuButton">
|
||||
<a class="dropdown-item">Pin to top</a>
|
||||
<a class="dropdown-item">Delete chat</a>
|
||||
<a class="dropdown-item ">Block</a>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
<!-- chat card start -->
|
||||
<div class="card chat-wrapper shadow-none mb-0">
|
||||
<div class="card-content">
|
||||
<div class="card-body chat-container" id="test" fxFlex="auto" [perfectScrollbar]="config">
|
||||
<div class="chat-content">
|
||||
<div class="chat" #messages [ngClass]="{'chat-right': messages.sender === 0 , 'chat-left': messages.sender === 1 }"
|
||||
*ngFor="let messages of contactChat">
|
||||
<div class="chat-avatar">
|
||||
<a [routerLink]="" class="avatar m-0">
|
||||
<img [src]="messages.senderImage" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="chat-body">
|
||||
<div class="chat-message">
|
||||
<p>{{messages.message}}</p>
|
||||
<span class="chat-time">{{messages.time}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer chat-footer px-2 py-1 pb-0">
|
||||
<form class="d-flex align-items-center">
|
||||
<i class="ficon feather ft-user cursor-pointer"></i>
|
||||
<i class="ficon feather ft-paperclip ml-1 cursor-pointer"></i>
|
||||
<input type="text" class="form-control chat-message-send mx-1" [(ngModel)]="newMessage" name="newmessage" id="iconLeft4"
|
||||
placeholder="Type your message here...." #box (keyup.enter)="onEnter(box.value)">
|
||||
<button type="submit" class="btn btn-primary glow send d-lg-flex" (click)="sendMessage()" ><i class="ficon feather ft-play"></i>
|
||||
<span class="d-none d-lg-block mx-50">Send</span></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- chat card ends -->
|
||||
</div>
|
||||
</section>
|
||||
<section class="chat-profile " id="chat-profile">
|
||||
<header class="chat-profile-header text-center border-bottom">
|
||||
<span class="chat-profile-close" (click)="ChatProfile($event)">
|
||||
<i class="ficon feather ft-x"></i>
|
||||
</span>
|
||||
<div class="my-2" *ngFor="let chats of headerChat">
|
||||
|
||||
<img [src]="chats.headerImage"class="round mb-1" alt="chat avatar"
|
||||
height="100" width="100">
|
||||
|
||||
<h5 class="app-chat-user-name mb-0">{{chats.senderName}}</h5>
|
||||
<span>Devloper</span>
|
||||
</div>
|
||||
</header>
|
||||
<div class="chat-profile-content p-2">
|
||||
<h6 class="mt-1">ABOUT</h6>
|
||||
<p>It is a long established fact that a reader will be distracted by the readable content.</p>
|
||||
<h6 class="mt-2">PERSONAL INFORMATION</h6>
|
||||
<ul class="list-unstyled">
|
||||
<li class="mb-25">email@gmail.com</li>
|
||||
<li>+1(789) 950-7654</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
<!-- app chat window ends -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- END: Content-->
|
||||
|
||||
<!-- app chat profile right sidebar ends -->
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { StaticChatComponent } from './static-chat.component';
|
||||
|
||||
describe('StaticChatComponent', () => {
|
||||
let component: StaticChatComponent;
|
||||
let fixture: ComponentFixture<StaticChatComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ StaticChatComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(StaticChatComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,431 @@
|
||||
import {
|
||||
Component, OnInit, AfterViewInit, ViewChild, Renderer2,
|
||||
ViewChildren, QueryList, ElementRef
|
||||
} from '@angular/core';
|
||||
import { PerfectScrollbarConfigInterface, PerfectScrollbarComponent, PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
|
||||
import { ApplicationApiService } from '../../../../../../src/app/_services/application-api.service';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { AppConstants } from '../../../../_helpers/app.constants';
|
||||
/**
|
||||
* ChatHistory class
|
||||
*/
|
||||
class ChatHistory {
|
||||
constructor(
|
||||
public message: string[],
|
||||
public sender: number,
|
||||
public senderImage: string,
|
||||
public senderName: string,
|
||||
public time: string
|
||||
) { }
|
||||
}
|
||||
class ChatHeader {
|
||||
constructor(
|
||||
public senderImage: string,
|
||||
public senderName: string
|
||||
) { }
|
||||
}
|
||||
class ContactHeader {
|
||||
constructor(
|
||||
public senderImage: string,
|
||||
public senderName: string
|
||||
) { }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Chats class
|
||||
*/
|
||||
class Chats {
|
||||
constructor(
|
||||
public friendId: number,
|
||||
public name: string,
|
||||
public image: string,
|
||||
public showMessage: string,
|
||||
public _ChatHistory: Array<ChatHistory>,
|
||||
public chatHeader: Array<ChatHeader>,
|
||||
public isSelected: false
|
||||
) { }
|
||||
}
|
||||
/**
|
||||
* Contact class
|
||||
*/
|
||||
class Contact {
|
||||
constructor(
|
||||
public friendId: number,
|
||||
public name: string,
|
||||
public image: string,
|
||||
public showMessage: string,
|
||||
public isSelected: false,
|
||||
public contactHeader: Array<ContactHeader>,
|
||||
) {}
|
||||
}
|
||||
@Component({
|
||||
selector: 'app-static-chat',
|
||||
templateUrl: './static-chat.component.html',
|
||||
styleUrls: ['./static-chat.component.css']
|
||||
})
|
||||
export class StaticChatComponent implements OnInit, AfterViewInit {
|
||||
showicon: boolean;
|
||||
isicon: boolean;
|
||||
isactive: boolean;
|
||||
isSelected: boolean;
|
||||
chatArray: any;
|
||||
headerArray: any;
|
||||
status = true;
|
||||
public contactChat = [];
|
||||
public headerChat = [];
|
||||
public Contact = [];
|
||||
newMessage = '';
|
||||
newMessageArray = [];
|
||||
|
||||
public config: PerfectScrollbarConfigInterface = { wheelPropagation: false };
|
||||
|
||||
@ViewChild(PerfectScrollbarComponent) componentRef?: PerfectScrollbarComponent;
|
||||
@ViewChild(PerfectScrollbarDirective, { static: true }) directiveRef?: PerfectScrollbarDirective;
|
||||
|
||||
@ViewChildren('messages') messages: QueryList<any>;
|
||||
@ViewChild('content', { static: true }) content: ElementRef;
|
||||
|
||||
chatsList: any[] = [];
|
||||
contactList: any[] = [];
|
||||
temp = [];
|
||||
temp2 = this.chatsList;
|
||||
temp3 = this.contactList;
|
||||
ContactHeader: any[] = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param ApplicationApiService chatApiService;
|
||||
* @param Renderer2 renderer
|
||||
*/
|
||||
constructor(
|
||||
private chatApiService: ApplicationApiService,
|
||||
private renderer: Renderer2,
|
||||
private toastr: ToastrService) {
|
||||
this.headerArray = this.chatApiService.getChatContactData().subscribe(Response => {
|
||||
this.headerArray = Response;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll chat to bottom
|
||||
*/
|
||||
ngAfterViewInit() {
|
||||
this.messages.forEach(this.scrollToBottom);
|
||||
this.messages.changes.subscribe(this.scrollToBottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* OnInit
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.toastr.clear();
|
||||
this.toastr.warning('', 'Please login through a personal account to experience the Live chat. We have it disabled for demo account.',
|
||||
{ timeOut: 5000, disableTimeOut: true, closeButton: true });
|
||||
this.chatArray = this.chatApiService.getChatsData().subscribe(Response => {
|
||||
this.chatArray = Response;
|
||||
this.contactChat = this.chatArray[2].ChatHistory;
|
||||
this.chatsList.push(
|
||||
new Chats(
|
||||
2,
|
||||
'Kristopher Candy',
|
||||
'../../../assets/images/portrait/small/avatar-s-7.png',
|
||||
|
||||
' Thank you',
|
||||
|
||||
this.chatArray[1].ChatHistory,
|
||||
this.chatArray[1].chatHeader,
|
||||
false
|
||||
)
|
||||
);
|
||||
this.chatsList.push(
|
||||
new Chats(
|
||||
3,
|
||||
'Sarah Woods',
|
||||
'../../../assets/images/portrait/small/avatar-s-8.png',
|
||||
|
||||
' Hello krish!',
|
||||
|
||||
this.chatArray[2].ChatHistory,
|
||||
this.chatArray[2].chatHeader,
|
||||
false
|
||||
)
|
||||
);
|
||||
this.contactList.push(
|
||||
new Contact(
|
||||
1,
|
||||
'Kristopher Candy',
|
||||
'../../../assets/images/portrait/small/avatar-s-9.png',
|
||||
'lemon drops',
|
||||
false,
|
||||
this.headerArray[0].contactHeader,
|
||||
)
|
||||
);
|
||||
this.contactList.push(
|
||||
new Contact(
|
||||
2,
|
||||
'Jenny Perich',
|
||||
'../../../assets/images/portrait/small/avatar-s-10.png',
|
||||
'candy canes',
|
||||
false,
|
||||
this.headerArray[1].contactHeader,
|
||||
)
|
||||
);
|
||||
this.contactList.push(
|
||||
new Contact(
|
||||
3,
|
||||
'Rock Montgomery',
|
||||
'../../../assets/images/portrait/small/avatar-s-11.png',
|
||||
'powder gum',
|
||||
false,
|
||||
this.headerArray[2].contactHeader,
|
||||
)
|
||||
);
|
||||
this.contactList.push(
|
||||
new Contact(
|
||||
4,
|
||||
'Heather Howell',
|
||||
'../../../assets/images/portrait/small/avatar-s-12.png',
|
||||
'cheesecake toffee',
|
||||
false,
|
||||
this.headerArray[3].contactHeader,
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Chat scroll to bottom
|
||||
*/
|
||||
scrollToBottom = () => {
|
||||
try {
|
||||
this.content.nativeElement.scrollTop = this.content.nativeElement.scrollHeight;
|
||||
} catch (err) { }
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter Chat
|
||||
*
|
||||
* @param event search event
|
||||
*/
|
||||
updateFilter(event) {
|
||||
const value = event.target.value.toLowerCase();
|
||||
this.chatsList = [...this.temp2]; // and here you have to initialize it with your data
|
||||
this.temp = [...this.chatsList];
|
||||
// filter our data
|
||||
const temp = this.chatsList.filter(function (d) {
|
||||
return d.name.toLowerCase().indexOf(value) !== -1 || !value;
|
||||
});
|
||||
// update the rows
|
||||
this.chatsList = temp;
|
||||
// Whenever the filter changes, always go back to the first page
|
||||
}
|
||||
updateFilter1(event) {
|
||||
const value = event.target.value.toLowerCase();
|
||||
this.contactList = [...this.temp3]; // and here you have to initialize it with your data
|
||||
this.temp = [...this.contactList];
|
||||
// filter our data
|
||||
const temp = this.contactList.filter(function (d) {
|
||||
return d.name.toLowerCase().indexOf(value) !== -1 || !value;
|
||||
});
|
||||
// update the rows
|
||||
this.contactList = temp;
|
||||
// Whenever the filter changes, always go back to the first page
|
||||
}
|
||||
/**
|
||||
* Send message
|
||||
*/
|
||||
sendMessage() {
|
||||
if (this.newMessage !== null && this.newMessage !== '') {
|
||||
this.contactChat.push({
|
||||
message: [this.newMessage],
|
||||
sender: 0,
|
||||
senderImage: '',
|
||||
time: '3:35AM',
|
||||
});
|
||||
this.newMessage = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Message send on Enter
|
||||
*
|
||||
* @param value New message
|
||||
*/
|
||||
onEnter(value: string) {
|
||||
this.newMessage = value;
|
||||
if (this.newMessage !== null && this.newMessage !== '') {
|
||||
this.contactChat.push({
|
||||
message: [this.newMessage],
|
||||
sender: 0,
|
||||
senderImage: '',
|
||||
time: '3:35AM'
|
||||
});
|
||||
this.newMessage = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display chat when click on contact
|
||||
*
|
||||
* @param friendId Friend id
|
||||
*/
|
||||
showChat(friendId, number) {
|
||||
this.contactChat = [];
|
||||
if (number === 1) {
|
||||
for (let i = 0; i < this.chatsList.length; i++) {
|
||||
if (friendId !== this.chatsList[i].friendId) {
|
||||
this.chatsList[i].isSelected = false;
|
||||
}
|
||||
if (friendId === this.chatsList[i].friendId) {
|
||||
this.chatsList[i].isSelected = true;
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < this.contactList.length; i++) {
|
||||
this.contactList[i].isSelected = false;
|
||||
}
|
||||
|
||||
for (const friend of this.chatsList) {
|
||||
if (friend.friendId === friendId) {
|
||||
this.contactChat = this.chatArray[friendId - 1].ChatHistory;
|
||||
this.headerChat = this.chatArray[friendId - 1].chatHeader;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (number === 2) {
|
||||
for (let i = 0; i < this.contactList.length; i++) {
|
||||
if (friendId !== this.contactList[i].friendId) {
|
||||
this.contactList[i].isSelected = false;
|
||||
}
|
||||
if (friendId === this.contactList[i].friendId) {
|
||||
this.contactList[i].isSelected = true;
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < this.chatsList.length; i++) {
|
||||
this.chatsList[i].isSelected = false;
|
||||
}
|
||||
this.contactChat = [];
|
||||
this.headerChat = this.headerArray[friendId - 1].contactHeader;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Overlay add/remove fuction in responsive
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
contentOverlay(event) {
|
||||
const toggleIcon = document.getElementById('chat-overlay1');
|
||||
const toggle = document.getElementById('chat-area d-none');
|
||||
if (event.currentTarget.className === 'chatSidebar ng-star-inserted') {
|
||||
this.renderer.addClass(toggleIcon, 'd-none');
|
||||
this.renderer.removeClass(toggle, 'd-none');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Warning add/remove class
|
||||
*
|
||||
* @param event click event
|
||||
*/
|
||||
chatFavorite(event) {
|
||||
const chatIcon = document.getElementById('chat-icon');
|
||||
if (event.currentTarget.className === 'chat-icon-favorite') {
|
||||
this.renderer.addClass(chatIcon, 'warning');
|
||||
} else if (event.currentTarget.className === 'chat-icon-favorite warning') {
|
||||
this.renderer.removeClass(chatIcon, 'warning');
|
||||
}
|
||||
}
|
||||
showContact(friendId) {
|
||||
this.contactChat = [];
|
||||
for (let i = 0; i < this.contactList.length; i++) {
|
||||
if (friendId !== this.contactList[i].friendId) {
|
||||
this.contactList[i].isSelected = false;
|
||||
}
|
||||
if (friendId === this.contactList[i].friendId) {
|
||||
this.contactList[i].isSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Show add/remove class at open profile
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
showProfile(event) {
|
||||
const toggleIcon = document.getElementById('user-profile');
|
||||
const toggle = document.getElementById('overlayChat');
|
||||
if (event.currentTarget.className === 'chat-sidebar-profile-toggle') {
|
||||
this.renderer.addClass(toggleIcon, 'show');
|
||||
this.renderer.addClass(toggle, 'show');
|
||||
} else if (event.currentTarget.className === 'chat-profile-close') {
|
||||
this.renderer.removeClass(toggleIcon, 'show');
|
||||
this.renderer.removeClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Show add/remove function in responsive
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
showSidebar(event) {
|
||||
if (window.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH) {
|
||||
const toggleIcon = document.getElementById('sidebar-card');
|
||||
const toggle = document.getElementById('overlayChat');
|
||||
const toggleChat = document.getElementById('sidebar-left');
|
||||
if (event.currentTarget.className === 'ficon feather ft-message-square chat-sidebar-toggle chat-start-icon font-large-3 p-3 mb-1' ||
|
||||
'ficon feather ft-align-justify font-large-1 cursor-pointer') {
|
||||
this.renderer.addClass(toggle, 'show');
|
||||
this.renderer.addClass(toggleIcon, 'show');
|
||||
}
|
||||
if (window.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH) {
|
||||
this.renderer.removeClass(toggleChat, 'sidebar-fixed');
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Show add/remove function in responsive
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
Sidebar(event) {
|
||||
const toggleChat = document.getElementById('sidebar-card');
|
||||
const toggleIcon = document.getElementById('chat-profile');
|
||||
const toggle = document.getElementById('overlayChat');
|
||||
if (event.currentTarget.className === 'chat-sidebar-close' || 'chat-overlay show') {
|
||||
this.renderer.removeClass(toggle, 'show');
|
||||
this.renderer.removeClass(toggleChat, 'show');
|
||||
this.renderer.removeClass(toggleIcon, 'show');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Show add/remove function
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
ShowChatProfile(event) {
|
||||
const toggleIcon = document.getElementById('chat-profile');
|
||||
const toggle = document.getElementById('overlayChat');
|
||||
if (event.currentTarget.className === 'avatar chat-profile-toggle m-0 mr-1') {
|
||||
this.renderer.addClass(toggleIcon, 'show');
|
||||
this.renderer.addClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Show add/remove function
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
ChatProfile(event) {
|
||||
const toggleIcon = document.getElementById('chat-profile');
|
||||
const toggle = document.getElementById('overlayChat');
|
||||
if (event.currentTarget.className === 'chat-profile-close') {
|
||||
this.renderer.removeClass(toggleIcon, 'show');
|
||||
this.renderer.removeClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
}
|
||||
89
src/app/content/applications/chat/static-chat/static.txt
Normal file
89
src/app/content/applications/chat/static-chat/static.txt
Normal file
@@ -0,0 +1,89 @@
|
||||
<div class="app-content content">
|
||||
<div class="sidebar-left sidebar-fixed" fxFlex="auto" [perfectScrollbar]="config" id="sidebar-left">
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-content card">
|
||||
<div class="card-body chat-fixed-search">
|
||||
<fieldset class="form-group position-relative has-icon-left m-0">
|
||||
<input type="text" class="form-control" id="iconLeft" placeholder="Search user"
|
||||
(keyup)='updateFilter($event)'>
|
||||
<div class="form-control-position">
|
||||
<i class="feather ft-search"></i>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div id="users-list" class="list-group position-relative">
|
||||
<div class="users-list-padding media-list">
|
||||
<a [routerLink]="" class="media _media" *ngFor="let chats of contactList"
|
||||
(click)="showChat(chats.friendId)" id="_media" [ngClass]="{'active':chats.isSelected === true, '':chats.isSelected === false}">
|
||||
<div class="media-left pr-1">
|
||||
<span class="avatar avatar-md avatar-{{chats.isactive}}"><img class="media-object rounded-circle"
|
||||
[src]="chats.image" alt="avatar"><i></i></span></div>
|
||||
<i></i>
|
||||
<div class="imagename media-body w-100">
|
||||
<h6 class="list-group-item-heading">{{chats.name}}<span
|
||||
class="font-small-3 float-right info">{{chats.time}}</span>
|
||||
</h6>
|
||||
<p class="list-group-item-text text-muted mb-0">
|
||||
<i class="feather ft-check primary font-small-2"></i>{{chats.showMessage}}
|
||||
<span class="float-right primary">
|
||||
<i class="font-medium-1 icon-pin blue-grey lighten-3" *ngIf="chats.showicon"></i>
|
||||
</span>
|
||||
<span class="float-right primary">
|
||||
<i class="font-medium-1 icon-volume-off blue-grey lighten-3 mr-1" *ngIf="chats.isicon "></i>
|
||||
<span class="badge badge-pill badge-danger">{{chats.badge}}</span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-right">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header"></div>
|
||||
<div class="content-body">
|
||||
<div class="content-overlay" id='content-overlay' (click)="contentOverlay($event)"></div>
|
||||
<section class="chat-app-window" #content>
|
||||
<div class="sidebar-toggle d-block d-lg-none" (click)="sidebar($event)"><i class="feather ft-menu font-large-1"></i></div>
|
||||
<div class="badge badge-secondary mb-1">Chat History</div>
|
||||
<div class="chats" #messages>
|
||||
<div class="chat" [ngClass]="{'chat-right': messages.sender == 0 , 'chat-left': messages.sender == 1 }"
|
||||
*ngFor="let messages of contactChat">
|
||||
<div class="chat-avatar">
|
||||
<a [routerLink]="" class="avatar">
|
||||
<span class="avatar-online"><img [src]="messages.senderImage" /></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="chat-body">
|
||||
<div class="chat-content">
|
||||
<p>{{messages.message}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="chat-app-form">
|
||||
<form class="chat-app-input d-flex">
|
||||
<fieldset class="form-group position-relative has-icon-left col-10 m-0">
|
||||
<div class="form-control-position">
|
||||
<i class="icon-emoticon-smile"></i>
|
||||
</div>
|
||||
<input type="text" class="form-control" [(ngModel)]="newMessage" name="newmessage" id="iconLeft4"
|
||||
placeholder="Type your message" #box (keyup.enter)="onEnter(box.value)">
|
||||
<div class="form-control-position control-position-right">
|
||||
<i class="feather ft-image"></i>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="form-group position-relative has-icon-left col-2 m-0">
|
||||
<button type="button" class="btn btn-primary" (click)="sendMessage()" keyboardShouldPersistTaps={true}><i
|
||||
class="la la-paper-plane-o d-lg-none"></i><span class="d-none d-lg-block">Send</span></button>
|
||||
</fieldset>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ////////////////////////////////////////////////////////////////////////////-->
|
||||
374
src/app/content/applications/contacts/contacts.component.css
Normal file
374
src/app/content/applications/contacts/contacts.component.css
Normal file
@@ -0,0 +1,374 @@
|
||||
.custom-file {
|
||||
width: 440px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
position: relative !important;
|
||||
margin-left: 0px !important;
|
||||
}
|
||||
|
||||
.dropdown-toggle::after {
|
||||
content: none !important;
|
||||
}
|
||||
|
||||
.favoriteChange:hover {
|
||||
background: url("../../../../assets/images/raty/star-on.png");
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-icon-right:before {
|
||||
font-family: 'icofont';
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-icon-skip:before {
|
||||
font-family: 'icofont';
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-icon-left:before {
|
||||
font-family: 'icofont';
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-icon-left:before {
|
||||
content: "\2039";
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-icon-prev:before {
|
||||
content: "\00AB";
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-icon-right:before {
|
||||
content: "\203A";
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-icon-skip:before {
|
||||
content: "\00BB";
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-left,
|
||||
.ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-right,
|
||||
.ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-prev {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #d4d2e7;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-right,
|
||||
.ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-right {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #d4d2e7;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-skip {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #d4d2e7;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-prev {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #d4d2e7;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-footer .datatable-pager ul li:not(.disabled).active a,
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] ul[_ngcontent-c11] li[_ngcontent-c11]:not(.disabled):hover a[_ngcontent-c11] {
|
||||
background-color: #d4d2e7;
|
||||
font-weight: bold;
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager a {
|
||||
height: 32px;
|
||||
min-width: 34px;
|
||||
line-height: 22px;
|
||||
padding: 0;
|
||||
border-radius: 3px;
|
||||
margin: 0 3px;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
padding-top: 3px;
|
||||
text-decoration: none;
|
||||
vertical-align: bottom;
|
||||
color: #7c8091;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-left,
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-right[_ngcontent-c11],
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-prev[_ngcontent-c11] {
|
||||
font-size: 14px;
|
||||
line-height: 9px;
|
||||
padding: 0px 08px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-left,
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-right[_ngcontent-c11],
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-prev[_ngcontent-c11] {
|
||||
font-size: 0px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-right,
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-right[_ngcontent-c11],
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-prev[_ngcontent-c11] {
|
||||
font-size: 0px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-skip,
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-right[_ngcontent-c11],
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-prev[_ngcontent-c11] {
|
||||
font-size: 0px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager .datatable-icon-prev,
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-right[_ngcontent-c11],
|
||||
.ngx-datatable.bootstrap[_ngcontent-c11] .datatable-footer[_ngcontent-c11] .datatable-pager[_ngcontent-c11] .datatable-icon-prev[_ngcontent-c11] {
|
||||
font-size: 0px;
|
||||
line-height: 22px;
|
||||
padding: 0px 09px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager ul li:not(.disabled):hover a {
|
||||
background-color: #545454;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager ul li:not(.disabled).active a,
|
||||
.ngx-datatable.bootstrap .datatable-footer .datatable-pager ul li:not(.disabled):hover a {
|
||||
background-color: #545454;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer {
|
||||
background: #727e8e;
|
||||
color: #ededed;
|
||||
margin-top: -1px;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header .datatable-header-cell .datatable-header-cell-label {
|
||||
font-weight: bold;
|
||||
line-height: 24px;
|
||||
font-size: medium;
|
||||
color: #6b6f82;
|
||||
}
|
||||
|
||||
:host ::ng-deep .cotnblck img {
|
||||
vertical-align: middle
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
:horizontal.app-contacts .sidebar-left.show {
|
||||
margin-left: 0rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
:host ::ng-deep .heading-elements .gap_contact {
|
||||
margin-right: 0.2rem;
|
||||
}
|
||||
|
||||
:host ::ng-deep .image-name-space {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-row-center,
|
||||
:host ::ng-deep .datatable-header-inner,
|
||||
:host ::ng-deep .datatable-row-wrapper,
|
||||
:host ::ng-deep .datatable-body-row.datatable-row-even,
|
||||
:host ::ng-deep .datatable-scroll,
|
||||
:host ::ng-deep .datatable-body-row.datatable-row-odd,
|
||||
:host ::ng-deep .datatable-footer,
|
||||
:host ::ng-deep .datatable-footer-inner {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-body-cell-label,
|
||||
:host ::ng-deep .datatable-header-cell {
|
||||
padding: 0.6rem;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-body-row {
|
||||
padding: 0 !important
|
||||
}
|
||||
|
||||
:host ::ng-deep .mrless {
|
||||
margin-right: 0.4rem !important
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-header {
|
||||
font-weight: bold;
|
||||
height: unset !important;
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .datatable-header-cell {
|
||||
font-size: 13px
|
||||
}
|
||||
|
||||
@media(max-width:767px) {
|
||||
|
||||
:host ::ng-deep .page-count,
|
||||
:host ::ng-deep .datatable-pager {
|
||||
flex: 1 1 100% !important
|
||||
}
|
||||
}
|
||||
|
||||
:host ::ng-deep .my-custom-cell {
|
||||
padding: 0.1rem 1.4rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable .datatable-body-cell,
|
||||
.ngx-datatable .datatable-header-cell {
|
||||
|
||||
line-height: 3.625;
|
||||
}
|
||||
|
||||
:host ::ng-deep .avatar i {
|
||||
position: absolute;
|
||||
right: -2px;
|
||||
bottom: 5px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border: 2px solid white;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
:host ::ng-deep .icon {
|
||||
right: 0px;
|
||||
left: 26px;
|
||||
bottom: -1px !important;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border: 0px !important;
|
||||
border: 2px solid white !important;
|
||||
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
.custom-file {
|
||||
margin-left: 15px !important;
|
||||
margin-right: 15px !important;
|
||||
width: 282px !important;
|
||||
}
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body .datatable-body-row.datatable-row-even {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body .datatable-body-row {
|
||||
border-top: none !important;
|
||||
border-bottom: 1px solid #e3ebf3;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.dropdown-toggle::after {
|
||||
font-family: 'LineAwesome';
|
||||
font-size: .8rem;
|
||||
position: relative;
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin: 0 .3em 0 0;
|
||||
padding: 0 2px 0 6px;
|
||||
content: '\f110' !important;
|
||||
vertical-align: 0;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.pr-1,
|
||||
.px-1 {
|
||||
padding-right: 0rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable .datatable-body .datatable-body-row>div {
|
||||
color: #6b6f82 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .close:not(:disabled):not(.disabled):hover,
|
||||
.close:not(:disabled):not(.disabled):focus {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.datatable-header-cell-template-wrap {
|
||||
padding-top: 1rem !important;
|
||||
}
|
||||
|
||||
._center {
|
||||
padding-top: 1rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable {
|
||||
display: -webkit-box;
|
||||
}
|
||||
|
||||
:host ::ng-deep .empty-row {
|
||||
padding-left: 1rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .dropdown .dropdown-menu .space,
|
||||
:host ::ng-deep .dropup .dropdown-menu .space {
|
||||
padding: 10px 20px !important;
|
||||
height: 38px;
|
||||
line-height: 1.625;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body .datatable-body-row .datatable-body-cell {
|
||||
padding: 0rem;
|
||||
overflow-y: visible !important;
|
||||
overflow-x: visible !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-footer .datatable-pager {
|
||||
padding: 0px 25px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .contacts-table{
|
||||
padding-top: 30px;
|
||||
padding-bottom: 35px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable .datatable-footer .datatable-pager {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngx-datatable.bootstrap .datatable-body .datatable-body-row.active {
|
||||
background-color: #FFF !important;
|
||||
}
|
||||
:host ::ng-deep .content-right {
|
||||
width: calc(100% - -30px) !important;
|
||||
}
|
||||
|
||||
::ng-deep ngb-modal-backdrop {
|
||||
z-index: 1050 !important;
|
||||
}
|
||||
309
src/app/content/applications/contacts/contacts.component.html
Normal file
309
src/app/content/applications/contacts/contacts.component.html
Normal file
@@ -0,0 +1,309 @@
|
||||
<div class="app-content content">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1"></div>
|
||||
<div class="content-detached content-right">
|
||||
<div class="content-body">
|
||||
<div class="content-overlay" id='content-overlay' (click)="contentOverlay($event)"></div>
|
||||
<section class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="bug-list-search">
|
||||
<div class="bug-list-search-content">
|
||||
<div class="sidebar-toggle d-block d-lg-none" (click)="sidebar($event)"><i
|
||||
class="feather ft-menu font-large-1"></i></div>
|
||||
<form action="">
|
||||
<div class="position-relative">
|
||||
<input type="text" id="search-contacts" class="form-control" placeholder="Search contacts..."
|
||||
(keyup)='updateFilter($event)'>
|
||||
<div class="form-control-position">
|
||||
<i class="la la-search text-size-base text-muted la-rotate-270"></i>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-head">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">All Contacts</h4>
|
||||
<div class="heading-elements mt-0">
|
||||
<button class="btn btn-primary btn-sm gap_contact"
|
||||
(click)="addTableDataModal(addTableDataModalContent)">
|
||||
<i class="d-md-none d-block feather ft-plus white"></i>
|
||||
<span class="d-md-block d-none">Add Contacts</span></button>
|
||||
<span ngbDropdown class="d-inline-block dropdown gap_contact" [placement]="placement">
|
||||
<button id="btnSearchDrop1" type="button" data-toggle="dropdown" aria-haspopup="true"
|
||||
aria-expanded="true" class="btn btn-warning dropdown-toggle dropdown-menu-right btn-sm"
|
||||
ngbDropdownToggle><i class="feather ft-download-cloud white"></i></button>
|
||||
<div ngbDropdownMenu aria-labelledby="dropdownBasic1" class="mt-1">
|
||||
<button class="dropdown-item"><i class="feather ft-upload"></i> Import</button>
|
||||
<button class="dropdown-item"><i class="feather ft-download"></i> Export</button>
|
||||
<button class="dropdown-item"><i class="feather ft-shuffle"></i> Find Duplicate</button>
|
||||
</div>
|
||||
</span>
|
||||
<button class="btn btn-default btn-sm"><i class="feather ft-settings white"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<!-- Task List table -->
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<button type="button" class="btn btn-danger" (click)="deleteCheckedRow()">Delete
|
||||
All</button>
|
||||
<span class="pull-right">
|
||||
Search :
|
||||
<input type='search'
|
||||
style='padding:8px;margin:15px auto;width:200px;height: calc(1.875rem + 2px);border-radius: 0.21rem;border: 1px solid #babfc7;'
|
||||
(keyup)='updateFilter($event)' /></span>
|
||||
</div>
|
||||
</div>
|
||||
<ngx-datatable #table class="bootstrap row contacts-table" [rows]="rows" [columnMode]="'force'" [headerHeight]="50"
|
||||
[footerHeight]="50" [rowHeight]="70" [limit]="5" [selected]="selected" [selectionType]="'checkbox'"
|
||||
(select)='onSelectContact($event)' fxFlex="auto" [perfectScrollbar]="config">
|
||||
|
||||
<ngx-datatable-column [flexGrow]="1" [minWidth]="30" [maxWidth]="50">
|
||||
<ng-template ngx-datatable-header-template let-value="value" let-allRowsSelected="allRowsSelected"
|
||||
let-selectFn="selectFn">
|
||||
<span class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="selectAll" [checked]="allRowsSelected"
|
||||
(change)="selectFn(!allRowsSelected)" />
|
||||
<label class="custom-control-label" for="selectAll"></label>
|
||||
</span>
|
||||
</ng-template>
|
||||
<ng-template ngx-datatable-cell-template let-value="value" let-row="row" let-rowIndex="rowIndex"
|
||||
let-onCheckboxChangeFn="onCheckboxChangeFn" let-isSelected="isSelected">
|
||||
<div class="custom-control custom-checkbox _center">
|
||||
<input type="checkbox" class="custom-control-input" id="select{{rowIndex}}"
|
||||
[checked]="isSelected" (change)="onCheckboxChangeFn($event)" />
|
||||
<label class="custom-control-label" for="select{{rowIndex}}"></label>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column name="Name" [flexGrow]="1" [minWidth]="140">
|
||||
<ng-template ngx-datatable-cell-template let-row="row">
|
||||
<span class="avatar avatar-sm avatar-{{row.isActive}} rounded-circle">
|
||||
<img [src]="row.image"><i></i></span>{{row.name}}
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column name="Email" [flexGrow]="1" [minWidth]="140">
|
||||
<ng-template ngx-datatable-cell-template let-row="row">
|
||||
<a [routerLink]="">{{row.email}}</a>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column name="Phone" [flexGrow]="1" [minWidth]="140"></ngx-datatable-column>
|
||||
<ngx-datatable-column name="Favorite" [flexGrow]="1" [minWidth]="90" [cellClass]="'my-custom-cell'">
|
||||
<ng-template ngx-datatable-cell-template let-row="row">
|
||||
<img src="../../../assets/images/raty/star-off.png" class="favoriteChange"
|
||||
*ngIf="!row.isFavorite" (click)="favoriteChange(row)">
|
||||
<img src="../../../assets/images/raty/star-on.png" class="favoriteChange" *ngIf="row.isFavorite"
|
||||
(click)="favoriteChange(row)">
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column name="Actions" [flexGrow]="1" [minWidth]="100">
|
||||
<ng-template ngx-datatable-cell-template let-row="row">
|
||||
<a [routerLink]="" class="primary edit mr-1 mrless"
|
||||
(click)="editTableDataModal(editTableDataModalContent, row)"><i class="la la-pencil"></i>
|
||||
</a>
|
||||
<a class="danger delete mr-1 mrless"><i class="la la-trash-o" (click)="deleteRow(row)"></i></a>
|
||||
<span class="dropdown" ngbDropdown placement="left">
|
||||
<a [routerLink]="" id="btnSearchDrop27" ngbDropdownToggle id="dropdownBasic1"
|
||||
class="mrless"><i class="la la-ellipsis-v"></i></a>
|
||||
<div ngbDropdownMenu aria-labelledby="dropdownBasic1">
|
||||
<a [routerLink]="" class="dropdown-item edit space"
|
||||
(click)="editTableDataModal(editTableDataModalContent, row)"><i
|
||||
class="feather ft-edit-2"></i>Edit</a>
|
||||
<a [routerLink]="" class="dropdown-item delete space" (click)="deleteRow(row)"><i
|
||||
class="feather ft-trash-2"></i> Delete</a>
|
||||
<a [routerLink]="" class="dropdown-item space"><i class="feather ft-plus-circle primary"></i>
|
||||
Projects</a>
|
||||
<a [routerLink]="" class="dropdown-item space"><i class="feather ft-plus-circle info"></i>
|
||||
Team</a>
|
||||
<a [routerLink]="" class="dropdown-item space"><i class="feather ft-plus-circle warning"></i>
|
||||
Clients</a>
|
||||
<a [routerLink]="" class="dropdown-item space"><i class="feather ft-plus-circle success"></i>
|
||||
Friends</a>
|
||||
</div>
|
||||
|
||||
</span>
|
||||
</ng-template>
|
||||
|
||||
</ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-detached sidebar-left" id="sidebar-left" fxFlex="auto" [perfectScrollbar]="config">
|
||||
<div class="sidebar">
|
||||
<div class="bug-list-sidebar-content">
|
||||
<!-- Predefined Views -->
|
||||
<div class="card">
|
||||
<div class="card-head">
|
||||
<div class="media p-1">
|
||||
<div class="media-left pr-1"><span class="avatar avatar-sm avatar-online rounded-circle"><img
|
||||
src="../../../assets/images/portrait/small/avatar-s-1.png" alt="avatar"><i
|
||||
class="icon"></i></span></div>
|
||||
<div class="media-body media-middle">
|
||||
<h5 class="media-heading">Margaret Govan</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- contacts view -->
|
||||
<div class="card-body border-top-blue-grey border-top-lighten-5">
|
||||
<div class="list-group">
|
||||
<a [routerLink]="" class="list-group-item active active">All Contacts</a>
|
||||
<a [routerLink]="" class="list-group-item list-group-item-action">Recently contacted</a>
|
||||
<a [routerLink]="" class="list-group-item list-group-item-action">Favorite contacts</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Groups-->
|
||||
<div class="card-body">
|
||||
<p class="lead">Groups</p>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<span class="badge badge-primary badge-pill float-right">14</span> <a [routerLink]="" class="info">
|
||||
Project</a>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span class="badge badge-info badge-pill float-right">22</span> <a [routerLink]="" class="info">
|
||||
Team</a>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span class="badge badge-warning badge-pill float-right">10</span> <a [routerLink]="" class="info">
|
||||
Clients</a>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span class="badge badge-success badge-pill float-right">5</span> <a [routerLink]="" class="info">
|
||||
Friends</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--/ Groups-->
|
||||
|
||||
<!--More-->
|
||||
<div class="card-body ">
|
||||
<p class="lead">More</p>
|
||||
<ul class="list-group">
|
||||
<a [routerLink]="" class="list-group-item info">Import</a>
|
||||
<a [routerLink]="" class="list-group-item info">Export</a>
|
||||
<a [routerLink]="" class="list-group-item info">Print</a>
|
||||
<a [routerLink]="" class="list-group-item info">Restore contacts</a>
|
||||
<a [routerLink]="" class="list-group-item info">Find duplicate</a>
|
||||
</ul>
|
||||
</div>
|
||||
<!--/More-->
|
||||
</div>
|
||||
<!--/ Predefined Views -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ////////////////////////////////////////////////////////////////////////////-->
|
||||
|
||||
<ng-template #editTableDataModalContent let-c="close" let-d="dismiss">
|
||||
<form (ngSubmit)="onUpdate(editForm,selectedContact.id)" #editForm="ngForm">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">Edit Contact</h5>
|
||||
<button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group col-12">
|
||||
<input type="text" [(ngModel)]="selectedContact.name" #editname="ngModel" name="name" id="name"
|
||||
class="name form-control" placeholder="Name"
|
||||
[ngClass]="{ 'is-invalid': editForm.submitted && editname.invalid }" required>
|
||||
<div *ngIf="editForm.submitted && editname.invalid" class="invalid-feedback">
|
||||
<div *ngIf="editname.errors.required">Name is required</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12">
|
||||
<input type="text" [(ngModel)]="selectedContact.email" #editemail="ngModel" name="email" id="email"
|
||||
class="email form-control" placeholder="Email"
|
||||
[ngClass]="{ 'is-invalid':editForm.submitted && editemail.invalid }" required email>
|
||||
<div *ngIf="editForm.submitted && editemail.invalid" class="invalid-feedback">
|
||||
<div *ngIf="editemail.errors.required">Email is required</div>
|
||||
<div *ngIf="editemail.errors.email">Email must be a valid email address</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12">
|
||||
<input type="text" [(ngModel)]="selectedContact.phone" #editphone="ngModel" name="phone" id="phone"
|
||||
class="phone form-control" placeholder="Phone Number" (keyup)="onFormat()" maxlength="14">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="form-group position-relative has-icon-left mb-0">
|
||||
<button type="submit" id="edit-contact-item" class="btn btn-info edit-contact-item" data-dismiss="modal"><i
|
||||
class="la la-paper-plane-o d-lg-none"></i> <span class="d-none d-lg-block">Edit</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #addTableDataModalContent let-c="close" let-d="dismiss">
|
||||
<form (ngSubmit)="addNewContact(addForm)" #addForm="ngForm">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel1">Add New Contact</h5>
|
||||
<button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group col-12">
|
||||
<input type="text" [(ngModel)]="contactName" name="name" id="contact-name" class="contact-name form-control"
|
||||
placeholder="Name" #contactname="ngModel"
|
||||
[ngClass]="{ 'is-invalid': addForm.submitted && contactname.invalid }" required>
|
||||
<div *ngIf="addForm.submitted && contactname.invalid" class="invalid-feedback">
|
||||
<div *ngIf="contactname.errors.required">Name is required</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12">
|
||||
<input type="text" [(ngModel)]="contactEmail" name="email" id="contact-email" class="contact-email form-control"
|
||||
placeholder="Email" #contactemail="ngModel"
|
||||
[ngClass]="{ 'is-invalid':addForm.submitted && contactemail.invalid }" required email>
|
||||
<div *ngIf="addForm.submitted && contactemail.invalid" class="invalid-feedback">
|
||||
<div *ngIf="contactemail.errors.required">Email is required</div>
|
||||
<div *ngIf="contactemail.errors.email">Email must be a valid email address</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12">
|
||||
<input type="text" [(ngModel)]="contactPhone" name="contactPhone" #contactphone="ngModel" id="contact-phone"
|
||||
class="contact-phone form-control" placeholder="Phone Number" (keyup)="onFormat()" maxlength="14">
|
||||
</div>
|
||||
<div class="form-group col-12">
|
||||
<span class="custom-control custom-checkbox">
|
||||
<input type="checkbox" [(ngModel)]="contactFavorite" name="favorite" (change)="addFavoriteImage($event)"
|
||||
id="favorite" class="contact-fav input-chk custom-control-input">
|
||||
<label class="custom-control-label" for="favorite">Favorite</label>
|
||||
</span>
|
||||
</div>
|
||||
<div class="custom-file form-group col-12">
|
||||
<input type="file" class="custom-file-input" accept='contactImage/*' (change)="preview($event)" id="customFile">
|
||||
<label class="custom-file-label">Choose Image</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="form-group position-relative has-icon-left mb-0">
|
||||
<button type="submit" id="add-contact-item" class="btn btn-info add-contact-item"><i
|
||||
class="la la-paper-plane-o d-lg-none"></i> <span class="d-none d-lg-block">Add
|
||||
New</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { ContactsComponent } from './contacts.component';
|
||||
|
||||
describe('ContactsComponent', () => {
|
||||
let component: ContactsComponent;
|
||||
let fixture: ComponentFixture<ContactsComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ContactsComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ContactsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
350
src/app/content/applications/contacts/contacts.component.ts
Normal file
350
src/app/content/applications/contacts/contacts.component.ts
Normal file
@@ -0,0 +1,350 @@
|
||||
import { Component, OnInit, ViewChild, EventEmitter, Output, Renderer2 } from '@angular/core';
|
||||
import { NgForm } from '@angular/forms';
|
||||
import { DatatableComponent } from '@swimlane/ngx-datatable';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { PerfectScrollbarConfigInterface, PerfectScrollbarComponent, PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
|
||||
|
||||
class Contact {
|
||||
constructor(
|
||||
public id: number,
|
||||
public name: string,
|
||||
public email: string,
|
||||
public phone: string,
|
||||
public image: any,
|
||||
public isFavorite: boolean,
|
||||
public isActive: string
|
||||
) { }
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-contacts',
|
||||
templateUrl: './contacts.component.html',
|
||||
styleUrls: ['./contacts.component.css']
|
||||
})
|
||||
export class ContactsComponent implements OnInit {
|
||||
columns: any = [];
|
||||
contactName: any;
|
||||
contactEmail: any;
|
||||
contactPhone: any;
|
||||
contactImage: any;
|
||||
contactFavorite: boolean;
|
||||
contactactive: string;
|
||||
rows: any[] = [];
|
||||
name = 'Angular';
|
||||
public imagePath;
|
||||
imgURL: any;
|
||||
selectedContact: any;
|
||||
contactFlag: boolean;
|
||||
addContact: any;
|
||||
placement = 'bottom-right';
|
||||
imagepathdefault: any;
|
||||
addModal = null;
|
||||
editModal = null;
|
||||
value: any;
|
||||
loadingIndicator: true;
|
||||
selected = [];
|
||||
temp = [];
|
||||
temp2 = this.rows;
|
||||
|
||||
public config: PerfectScrollbarConfigInterface = { };
|
||||
|
||||
@ViewChild(PerfectScrollbarComponent) componentRef?: PerfectScrollbarComponent;
|
||||
@ViewChild(PerfectScrollbarDirective) directiveRef?: PerfectScrollbarDirective;
|
||||
|
||||
@Output() closeModalEvent = new EventEmitter<boolean>();
|
||||
@ViewChild(DatatableComponent, { static: true }) table: DatatableComponent;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param NgbModal modal;
|
||||
* @param Renderer2 _renderer
|
||||
*/
|
||||
constructor(
|
||||
private modal: NgbModal,
|
||||
private _renderer: Renderer2
|
||||
) { }
|
||||
|
||||
/**
|
||||
* OnInit
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.rows.push(new Contact(1, 'Scott Marsh', 'scott@gmail.com', '(954)-654-5641',
|
||||
'../../../assets/images/portrait/small/avatar-s-5.png', false, 'online'));
|
||||
this.rows.push(new Contact(2, 'Russell Bry', 'russell@gmail.com', '(235)-654-5642',
|
||||
'../../../assets/images/portrait/small/avatar-s-3.png', false, 'busy'));
|
||||
this.rows.push(new Contact(3, 'james john', 'john@gmail.com', '(125)-654-5643',
|
||||
'../../../assets/images/portrait/small/avatar-s-1.png', true, 'away'));
|
||||
this.rows.push(new Contact(4, 'Cynth Tuck', 'tuck@gmail.com', '(974)-654-5644',
|
||||
'../../../assets/images/portrait/small/avatar-s-4.png', false, 'busy'));
|
||||
this.rows.push(new Contact(5, 'Margi Govan', 'govan@gmail.com', '(954)-654-5645',
|
||||
'../../../assets/images/portrait/small/avatar-s-6.png', true, 'online'));
|
||||
this.rows.push(new Contact(6, 'Eugene Wood', 'wood@gmail.com', '(987)-654-5646',
|
||||
'../../../assets/images/portrait/small/avatar-s-9.png', false, 'busy'));
|
||||
this.rows.push(new Contact(7, 'Eric Marshall', 'eric@gmail.com', '(545)-654-5647',
|
||||
'../../../assets/images/portrait/small/avatar-s-7.png', false, 'online'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new contact
|
||||
*
|
||||
* @param addTableDataModalContent Id of the add contact modal;
|
||||
*/
|
||||
addTableDataModal(addTableDataModalContent) {
|
||||
this.addModal = this.modal.open(addTableDataModalContent, {
|
||||
windowClass: 'animated fadeInDown'
|
||||
});
|
||||
this.contactFlag = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit selected contact row.
|
||||
*
|
||||
* @param editTableDataModalContent Id of the edit contact model.
|
||||
* @param row The row which needs to be edited.
|
||||
*/
|
||||
editTableDataModal(editTableDataModalContent, row) {
|
||||
this.selectedContact = Object.assign({}, row);
|
||||
this.editModal = this.modal.open(editTableDataModalContent, {
|
||||
windowClass: 'animated fadeInDown'
|
||||
});
|
||||
this.contactFlag = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selected contact
|
||||
*
|
||||
* @param selected Selected contact;
|
||||
*/
|
||||
onSelectContact({ selected }) {
|
||||
this.selected.splice(0, this.selected.length);
|
||||
this.selected.push(...selected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search contact from contact table
|
||||
*
|
||||
* @param event Convert value uppercase to lowercase;
|
||||
*/
|
||||
updateFilter(event) {
|
||||
const val = event.target.value.toLowerCase();
|
||||
this.rows = [...this.temp2];
|
||||
this.temp = [...this.rows];
|
||||
const temp = this.rows.filter(function (d) {
|
||||
return d.name.toLowerCase().indexOf(val) !== -1 || !val;
|
||||
});
|
||||
this.rows = temp;
|
||||
this.table.offset = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose contact image
|
||||
*
|
||||
* @param event Select contact image;
|
||||
*/
|
||||
preview(event) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e: any) => {
|
||||
this.contactImage = e.target.result;
|
||||
};
|
||||
reader.readAsDataURL(event.target.files[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete contact row
|
||||
* @param row Selected row for delete contact
|
||||
*/
|
||||
deleteRow(row) {
|
||||
let index = 0;
|
||||
const temp = [...this.rows];
|
||||
for (const tempRow of temp) {
|
||||
if (tempRow.id === row.id) {
|
||||
temp.splice(index, 1);
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
this.rows = temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update contact details
|
||||
*
|
||||
* @param editForm Edit form for values check
|
||||
* @param id Id match to the selected row Id
|
||||
*/
|
||||
onUpdate(editForm: NgForm, id) {
|
||||
for (const row of this.rows) {
|
||||
if (row.id === id && editForm.valid === true) {
|
||||
row.name = this.selectedContact['name'];
|
||||
row.email = this.selectedContact['email'];
|
||||
row.phone = this.selectedContact['phone'];
|
||||
this.editModal.close(editForm.resetForm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contact changed to favorite or non-favorite
|
||||
*
|
||||
* @param row Row of the favorite contact
|
||||
*/
|
||||
favoriteChange(row) {
|
||||
if (row.isFavorite) {
|
||||
row.isFavorite = row.isFavorite ? false : true;
|
||||
} else {
|
||||
row.isFavorite = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete selected contact
|
||||
*/
|
||||
deleteCheckedRow() {
|
||||
let index = 0;
|
||||
const removedIndex = [];
|
||||
const temp = [...this.rows];
|
||||
for (const row of temp) {
|
||||
for (const selectedRow of this.selected) {
|
||||
if (row.id === selectedRow.id) {
|
||||
removedIndex.push(index);
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
for (let i = removedIndex.length - 1; i >= 0; i--) {
|
||||
temp.splice(removedIndex[i], 1);
|
||||
}
|
||||
this.rows = temp;
|
||||
this.selected = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* favorite set when add contact
|
||||
*
|
||||
* @param event favorite set on click event
|
||||
*/
|
||||
addFavoriteImage(event) {
|
||||
if (event.target.checked === true) {
|
||||
this.contactFavorite = true;
|
||||
} else {
|
||||
this.contactFavorite = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* New contact add to the table
|
||||
*
|
||||
* @param addForm Add contact form
|
||||
*/
|
||||
addNewContact(addForm: NgForm) {
|
||||
if (this.contactImage == null) {
|
||||
this.contactImage = '../../../assets/images/portrait/small/default.png';
|
||||
} else {
|
||||
this.contactImage = this.contactImage;
|
||||
}
|
||||
|
||||
if (this.contactactive === undefined) {
|
||||
this.contactactive = 'away';
|
||||
} else {
|
||||
this.contactactive = this.contactactive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add contact if valid addform value
|
||||
*/
|
||||
if (addForm.valid === true) {
|
||||
this.rows.push(
|
||||
new Contact(
|
||||
this.rows.length + 1,
|
||||
this.contactName,
|
||||
this.contactEmail,
|
||||
this.contactPhone,
|
||||
this.contactImage,
|
||||
this.contactFavorite,
|
||||
this.contactactive
|
||||
)
|
||||
);
|
||||
this.rows = [...this.rows];
|
||||
addForm.reset();
|
||||
this.addModal.close(addForm.resetForm);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the phone number format
|
||||
*/
|
||||
onFormat() {
|
||||
if (this.contactFlag === true) {
|
||||
this.value = this.contactPhone;
|
||||
} else if (this.contactFlag === false) {
|
||||
this.value = this.selectedContact['phone'];
|
||||
}
|
||||
|
||||
let country, city, number;
|
||||
|
||||
switch (this.value.length) {
|
||||
case 6:
|
||||
country = 1;
|
||||
city = this.value.slice(0, 3);
|
||||
number = this.value.slice(3);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
country = this.value[0];
|
||||
city = this.value.slice(1, 4);
|
||||
number = this.value.slice(4);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
country = this.value.slice(0, 3);
|
||||
city = this.value.slice(3, 5);
|
||||
number = this.value.slice(5);
|
||||
break;
|
||||
|
||||
default:
|
||||
return this.value;
|
||||
}
|
||||
if (country === 1) {
|
||||
country = '';
|
||||
}
|
||||
|
||||
number = number.slice(0, 3) + '-' + number.slice(3);
|
||||
|
||||
const no = '(' + city + ')' + '-' + number;
|
||||
if (this.contactFlag === true) {
|
||||
this.contactPhone = no;
|
||||
} else if (this.contactFlag === false) {
|
||||
this.selectedContact['phone'] = no;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sidebar open/close in responsive
|
||||
*
|
||||
* @param event Sidebar open/close
|
||||
*/
|
||||
sidebar(event) {
|
||||
const toggleIcon = document.getElementById('sidebar-left');
|
||||
const toggle = document.getElementById('content-overlay');
|
||||
if (event.currentTarget.className === 'sidebar-toggle d-block d-lg-none') {
|
||||
this._renderer.addClass(toggleIcon, 'show');
|
||||
this._renderer.addClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overlay add/remove fuction in responsive
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
contentOverlay(event) {
|
||||
const toggleIcon = document.getElementById('sidebar-left');
|
||||
const toggle = document.getElementById('content-overlay');
|
||||
if (event.currentTarget.className === 'content-overlay show') {
|
||||
this._renderer.removeClass(toggleIcon, 'show');
|
||||
this._renderer.removeClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { ContactsModule } from './contacts.module';
|
||||
|
||||
describe('ContactsModule', () => {
|
||||
let contactsModule: ContactsModule;
|
||||
|
||||
beforeEach(() => {
|
||||
contactsModule = new ContactsModule();
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
expect(contactsModule).toBeTruthy();
|
||||
});
|
||||
});
|
||||
29
src/app/content/applications/contacts/contacts.module.ts
Normal file
29
src/app/content/applications/contacts/contacts.module.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ContactsComponent } from './contacts.component';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { NgxDatatableModule } from '@swimlane/ngx-datatable';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { BreadcrumbModule } from 'src/app/_layout/breadcrumb/breadcrumb.module';
|
||||
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
NgxDatatableModule,
|
||||
BreadcrumbModule,
|
||||
FormsModule,
|
||||
NgbModule,
|
||||
PerfectScrollbarModule,
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: ContactsComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
declarations: [ContactsComponent],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class ContactsModule { }
|
||||
169
src/app/content/applications/email/email.component.css
Normal file
169
src/app/content/applications/email/email.component.css
Normal file
@@ -0,0 +1,169 @@
|
||||
:host ::ng-deep .mr-50, .mx-50 {
|
||||
margin-right: .5rem!important;
|
||||
}
|
||||
:host ::ng-deep .mr-25, .mx-25 {
|
||||
margin-right: .25rem!important;
|
||||
}
|
||||
:host ::ng-deep .pr-50, .px-50 {
|
||||
padding-right: .5rem!important;
|
||||
}
|
||||
:host ::ng-deep .content-right .email-app-list-wrapper .email-app-list .email-user-list .users-list-wrapper li {
|
||||
border-top: 1px solid #E4E5EC !important;
|
||||
}
|
||||
:host ::ng-deep .app-content .content-right {
|
||||
width: calc(100% - 300px) !important;
|
||||
background-color: #fff;
|
||||
}
|
||||
@media (max-width: 768px){
|
||||
.app-content .content-right {
|
||||
width: calc(100% - 0px) !important;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
:host ::ng-deep .ps__thumb-y {
|
||||
background-color: #aaa;
|
||||
border-radius: 6px;
|
||||
position: absolute;
|
||||
}
|
||||
:host ::ng-deep .content-right .email-app-details .email-scroll-area {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
:host ::ng-deep .d-block {
|
||||
text-align: left;
|
||||
}
|
||||
:host ::ng-deep .d-flex {
|
||||
display: flex!important;
|
||||
}
|
||||
:host ::ng-deep .btn-link {
|
||||
font-weight: 400;
|
||||
color:#6b6f82 !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
:host ::ng-deep .email-detail-head .collapse-header .card-header {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .py-1 {
|
||||
background-color: #f4f5fa;
|
||||
}
|
||||
:host ::ng-deep .ps {
|
||||
overflow: hidden!important;
|
||||
}
|
||||
:host ::ng-deep .content.app-content {
|
||||
overflow-y: hidden !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .tagDropdown {
|
||||
transform: translate3d(-118px, -16px, 0px) !important;
|
||||
top: 8px;
|
||||
}
|
||||
@media (max-width: 768px){
|
||||
.tagDropdown {
|
||||
transform: translate3d(-98px, -64px, 0px) !important;
|
||||
top: 8px;
|
||||
}
|
||||
}
|
||||
:host ::ng-deep .listDropdown {
|
||||
transform: translate3d(-123px, 30px, 0px) !important;
|
||||
}
|
||||
@media (max-width: 768px){
|
||||
.listDropdown {
|
||||
transform: translate3d(-88px, -65px, 0px) !important;
|
||||
top: 8px;
|
||||
}
|
||||
}
|
||||
:host ::ng-deep .taglistDropdown {
|
||||
transform: translate3d(-123px, -8px, 0px) !important;
|
||||
}
|
||||
@media (max-width: 768px){
|
||||
.taglistDropdown {
|
||||
transform: translate3d(-124px, -65px, 0px) !important;
|
||||
top: 8px;
|
||||
}
|
||||
}
|
||||
:host ::ng-deep .dropdown .dropdown-menu .dropdown-item {
|
||||
padding: 10px 17px !important;
|
||||
}
|
||||
:host ::ng-deep .bg-1{
|
||||
background-color: #666ee8;
|
||||
|
||||
}
|
||||
:host ::ng-deep .badge {
|
||||
display: inline-block;
|
||||
padding: .35em .4em;
|
||||
font-size: 80%;
|
||||
text-align: center;
|
||||
vertical-align: baseline;
|
||||
border-radius: .25rem;
|
||||
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
|
||||
}
|
||||
:host ::ng-deep .badge-pill {
|
||||
padding-right: .6em;
|
||||
padding-left: .6em;
|
||||
border-radius: 10rem;
|
||||
}
|
||||
:host ::ng-deep .show>.inboxDropdown {
|
||||
transform: translate3d(-118px, 30px, 0px) !important;
|
||||
}
|
||||
@media (max-width: 768px){
|
||||
.show>.inboxDropdown {
|
||||
transform: translate3d(-106px, -65px, 0px) !important;
|
||||
}
|
||||
}
|
||||
:host ::ng-deep .app-content .sidebar .email-app-sidebar {
|
||||
width: 300px !important;
|
||||
}
|
||||
:host ::ng-deep .emailtoolbar {
|
||||
float: right;
|
||||
margin-bottom: 12px;
|
||||
display: initial;
|
||||
}
|
||||
:host ::ng-deep .app-content .quill-wrapper .snow-container .send-btn {
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ql-editor {
|
||||
overflow-y: initial !important;
|
||||
padding: 0px 0px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .gradient-mint {
|
||||
background-image: linear-gradient(45deg,#28d094,#28d094)!important;
|
||||
width: 10px !important;
|
||||
height: 10px !important;
|
||||
}
|
||||
:host ::ng-deep .gradient-primary{
|
||||
background-image: linear-gradient(45deg,#666ee8,#666ee8)!important;
|
||||
width: 10px !important;
|
||||
height: 10px !important;
|
||||
}
|
||||
:host ::ng-deep .gradient-warning {
|
||||
background-image: linear-gradient(45deg,#ff9149,#ff9149)!important;
|
||||
width: 10px !important;
|
||||
height: 10px !important;
|
||||
}
|
||||
:host ::ng-deep .gradient-danger {
|
||||
background-image: linear-gradient(45deg,#ff4961,#ff4961)!important;
|
||||
width: 10px !important;
|
||||
height: 10px !important;
|
||||
}
|
||||
:host ::ng-deep .gradient-info {
|
||||
background-image: linear-gradient(45deg,#1e9ff2,#1e9ff2)!important;
|
||||
width: 10px !important;
|
||||
height: 10px !important;
|
||||
}
|
||||
:host ::ng-deep .list-group .list-group-messages :hover {
|
||||
color: #0c84d1 !important;
|
||||
}
|
||||
:host ::ng-deep .mr-75, .mx-75 {
|
||||
margin-right: .75rem!important;
|
||||
}
|
||||
.list-inline-item:not(:last-child) {
|
||||
margin-right: 0.7rem !important;
|
||||
}
|
||||
|
||||
@media (max-width: 768px){
|
||||
.list-inline-item:not(:last-child) {
|
||||
margin-right: 0.25rem !important;
|
||||
}
|
||||
}
|
||||
527
src/app/content/applications/email/email.component.html
Normal file
527
src/app/content/applications/email/email.component.html
Normal file
@@ -0,0 +1,527 @@
|
||||
<div class="app-content content">
|
||||
<div class="sidebar-left" id="sidebar-left">
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-content email-app-sidebar d-flex">
|
||||
<!-- sidebar close icon -->
|
||||
<span class="sidebar-close-icon" (click)="showSidebar($event) ">
|
||||
<i class="ficon feather ft-x"></i>
|
||||
</span>
|
||||
<!-- sidebar close icon -->
|
||||
<div class="email-app-menu">
|
||||
<div class="form-group form-group-compose">
|
||||
<!-- compose button -->
|
||||
<button type="button" class="btn btn-danger btn-glow btn-block my-2 compose-btn" id="compose-btn"
|
||||
(click)="showComposeSidebar($event)">
|
||||
<i class="ficon feather ficon feather ft-plus"></i>
|
||||
Compose
|
||||
</button>
|
||||
</div>
|
||||
<div class="sidebar-menu-list" fxFlex="auto" [perfectScrollbar]="config">
|
||||
<!-- sidebar menu -->
|
||||
<div class="list-group list-group-messages" *ngFor="let email of emailMenuList">
|
||||
<a class="list-group-item" id="inbox-menu" (click)="showEmailMenu(email.Id, emailMenuList)"
|
||||
[ngClass]="{'active':email.isSelected === true, '':email.isSelected === false}">
|
||||
<div class="d-inline mr-25">
|
||||
<i class="{{email.icon}}"></i>
|
||||
</div>
|
||||
{{email.name}}
|
||||
<span class="{{email.budgeClass}}">{{email.budge}}</span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<!-- sidebar menu end-->
|
||||
|
||||
<!-- sidebar label start -->
|
||||
<label class="sidebar-label">Labels</label>
|
||||
<div class="list-group list-group-labels " *ngFor="let email of emailLable">
|
||||
<a [routerLink]="" class="list-group-item d-flex justify-content-between align-items-center"
|
||||
(click)="showEmailMenu(email.Id, emailLable)"
|
||||
[ngClass]="{'active':email.isSelected === true, '':email.isSelected === false}">
|
||||
{{email.name}}
|
||||
<span class="{{email.bulletClass}} d-inline-block rounded-circle "></span>
|
||||
|
||||
</a>
|
||||
</div>
|
||||
<!-- sidebar label end -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- User new mail right area -->
|
||||
<div class="compose-new-mail-sidebar" id="compose-sidebar" fxFlex="auto" [perfectScrollbar]="config">
|
||||
<div class="card mb-0 shadow-none quill-wrapper p-0">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title" id="emailCompose">New Message</h3>
|
||||
<button type="button" class="close close-icon" id="showCompose" (click)="showCompose($event)">
|
||||
<i class="ficon feather ft-x"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- form start -->
|
||||
<form action="" id="compose-form">
|
||||
<div class="card-content">
|
||||
<div class="card-body pt-0">
|
||||
<div class="form-group pb-50">
|
||||
<label for="emailfrom">from</label>
|
||||
<input type="text" id="emailfrom" class="form-control" placeholder="user@example.com" disabled>
|
||||
</div>
|
||||
<div class="form-label-group mb-1">
|
||||
<input type="email" id="emailTo" class="form-control" placeholder="To" required>
|
||||
</div>
|
||||
<div class="form-label-group mb-1">
|
||||
<input type="text" id="emailSubject" class="form-control" placeholder="Subject">
|
||||
</div>
|
||||
<div class="form-label-group mb-1">
|
||||
<input type="text" id="emailCC" class="form-control" placeholder="CC">
|
||||
</div>
|
||||
<div class="form-label-group mb-1">
|
||||
<input type="text" id="emailBCC" class="form-control" placeholder="BCC">
|
||||
</div>
|
||||
<!-- Compose mail Quill editor -->
|
||||
<div class="snow-container border rounded p-50 ">
|
||||
<section class="default-editor">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="snow-container border rounded p-50">
|
||||
<quill-editor [styles]="{height: '80px'}" [modules]="quillConfig" (onFocus)="focus()"
|
||||
(onBlur)="blur()" ></quill-editor>
|
||||
|
||||
|
||||
<!-- <div class="toolbar1">
|
||||
<button class="ql-bold">Bold</button>
|
||||
<button class="ql-italic">Italic</button>
|
||||
<button class="ql-underline">Underline</button>
|
||||
<button class="ql-strike">Strike</button>
|
||||
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="form-group mt-2">
|
||||
<div class="custom-file">
|
||||
<input type="file" class="custom-file-input" id="emailAttach">
|
||||
<label class="custom-file-label" for="emailAttach">Attach file</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer border-0 d-flex justify-content-end pt-0">
|
||||
<button type="reset" class="btn btn-secondary cancel-btn mr-1" (click)="showCompose($event)">
|
||||
<i class='ficon feather ft-x mr-25'></i>
|
||||
<span class="d-sm-inline d-none">Cancel</span>
|
||||
</button>
|
||||
<button type="submit" class="btn-send btn btn-danger btn-glow">
|
||||
<i class='ficon feather ft-play mr-25'></i> <span class="d-sm-inline d-none">Send</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<!-- form start end-->
|
||||
</div>
|
||||
</div>
|
||||
<!--/ User Chat profile right area -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-right">
|
||||
<div class="content-header row">
|
||||
</div>
|
||||
<div class="content-overlay"></div>
|
||||
<div class="content-wrapper">
|
||||
<div class="content-body">
|
||||
<!-- email app overlay -->
|
||||
<div class="app-content-overlay" id="app-content-overlay" (click)="showCompose($event)"
|
||||
(click)="showSidebar($event)"></div>
|
||||
<div class="email-app-area">
|
||||
<!-- Email list Area -->
|
||||
<div class="email-app-list-wrapper">
|
||||
<div class="email-app-list">
|
||||
<div class="email-action">
|
||||
<!-- action left start here -->
|
||||
<div class="action-left d-flex align-items-center">
|
||||
|
||||
<div class="custom-control custom-checkbox selectAll mr-50">
|
||||
<input type="checkbox" class="custom-control-input" id="selectAll" [(ngModel)]="selectAll"
|
||||
(click)="selectAllEmails();">
|
||||
<label class="custom-control-label" for="selectAll"></label>
|
||||
</div>
|
||||
<!-- delete unread dropdown -->
|
||||
<ul class="list-inline m-0 d-flex">
|
||||
<li class="list-inline-item mail-delete">
|
||||
<button type="button" class="btn btn-icon action-icon" (click)="deleteCheckedRow()">
|
||||
<i class="ficon feather ft-trash-2"></i>
|
||||
</button>
|
||||
</li>
|
||||
<li class="list-inline-item mail-unread">
|
||||
<button type="button" class="btn btn-icon action-icon">
|
||||
<i class="ficon feather ft-mail"></i>
|
||||
</button>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<div class="dropdown">
|
||||
<div ngbDropdown [open]="false" [autoClose]="true" class="d-inline-block">
|
||||
<button type="button" class="dropdown-toggle btn btn-icon action-icon" id="folder"
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="dropdownMenuButton"
|
||||
dropdown-menu dropdown-menu-right show data-toggle="dropdown" aria-haspopup="true"
|
||||
aria-expanded="false" role="menu" ngbDropdownToggle>
|
||||
<i class="ficon feather ft-folder mr-0"></i>
|
||||
</button>
|
||||
<div ngbDropdownMenu="dropdownMenuButton" class="dropdown-menu dropdown-menu-right inboxDropdown" >
|
||||
<a class="dropdown-item" [routerLink]=""><i class="ficon feather ft-edit"></i>Draft</a>
|
||||
<a class="dropdown-item" [routerLink]=""><i class="ficon feather ft-info"></i>Spam</a>
|
||||
<a class="dropdown-item" [routerLink]=""><i class="ficon feather ft-trash-2"></i>Trash</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<div class="dropdown">
|
||||
<div ngbDropdown [open]="false" [autoClose]="true" class="d-inline-block">
|
||||
<button type="button" class="btn btn-icon dropdown-toggle action-icon" id="tag"
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="dropdownMenuButton"
|
||||
ropdown-menu dropdown-menu-right show data-toggle="dropdown" aria-haspopup="true"
|
||||
aria-expanded="false" role="menu" ngbDropdownToggle>
|
||||
<i class="ficon feather ft-tag mr-0"></i>
|
||||
</button>
|
||||
<div aria-labelledby="tag">
|
||||
<div ngbDropdownMenu="dropdownMenuButton" class="tagDropdown" >
|
||||
<a [routerLink]="" class="dropdown-item align-items-center">
|
||||
<span class="bullet bullet-sm gradient-mint d-inline-block rounded-circle "></span>
|
||||
<span>Product</span>
|
||||
</a>
|
||||
<a [routerLink]="" class="dropdown-item align-items-center">
|
||||
<span class="bullet bullet-sm gradient-primary d-inline-block rounded-circle "></span>
|
||||
<span>Work</span>
|
||||
</a>
|
||||
<a [routerLink]="" class="dropdown-item align-items-center">
|
||||
<span class="bullet bullet-sm gradient-warning d-inline-block rounded-circle "></span>
|
||||
<span>Misc</span>
|
||||
</a>
|
||||
<a [routerLink]="" class="dropdown-item align-items-center">
|
||||
<span class="bullet bullet-sm gradient-danger d-inline-block rounded-circle "></span>
|
||||
<span>Family</span>
|
||||
</a>
|
||||
<a [routerLink]="" class="dropdown-item align-items-center">
|
||||
<span class="bullet bullet-sm gradient-info d-inline-block rounded-circle "></span>
|
||||
<span> Design</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- action left end here -->
|
||||
|
||||
<!-- action right start here -->
|
||||
<div class="action-right d-flex flex-grow-1 align-items-center justify-content-around">
|
||||
<!-- search bar -->
|
||||
<div class="email-fixed-search flex-grow-1">
|
||||
<div class="sidebar-toggle d-block d-lg-none" (click)="showSidebar($event)">
|
||||
<i class="ficon feather ft-align-justify"></i>
|
||||
</div>
|
||||
<fieldset class="form-group position-relative has-icon-left m-0">
|
||||
<input type="text" class="form-control" id="email-search" (keyup)="search($event)"
|
||||
placeholder="Search email">
|
||||
<div class="form-control-position">
|
||||
<i class="ficon feather ft-search"></i>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<!-- pagination and page count -->
|
||||
<span class="d-none d-sm-block">1-10 of 653</span>
|
||||
<button class="btn btn-icon email-pagination-prev d-none d-sm-block">
|
||||
<i class="ficon feather ft-chevron-left"></i>
|
||||
</button>
|
||||
<button class="btn btn-icon email-pagination-next d-none d-sm-block">
|
||||
<i class="ficon feather ft-chevron-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / action right -->
|
||||
|
||||
<!-- email user list start -->
|
||||
<div class="email-user-list list-group" [perfectScrollbar]="config">
|
||||
<ul class="users-list-wrapper media-list">
|
||||
<li class="{{contact.mediaClass}}" *ngFor="let contact of emailList; let i = index">
|
||||
<div class="user-action">
|
||||
<div class="checkbox-con mr-25">
|
||||
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" [(ngModel)]="contact.isSelected" class="custom-control-input"
|
||||
id="checkboxsmall{{i}}">
|
||||
<label class="custom-control-label" for="checkboxsmall{{i}}"></label>
|
||||
</div>
|
||||
</div>
|
||||
<span class="{{contact.starClass}}" [attr.id]="'emailstar-icon' + contact.emailId" (click)="emailFavorite($event,contact.emailId)">
|
||||
<i class="{{contact.starIcon}}"></i>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="pr-50">
|
||||
<div class="avatar">
|
||||
<img [src]="contact.image" alt="avtar img holder">
|
||||
</div>
|
||||
</div>
|
||||
<div class="media-body" (click)="showEmail($event)">
|
||||
<div class="user-details">
|
||||
<div class="mail-items">
|
||||
<span class="list-group-item-text text-truncate">{{contact.title}}</span>
|
||||
</div>
|
||||
<div class="mail-meta-item">
|
||||
<span class="float-right">
|
||||
<span class="mail-date">{{contact.time}}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mail-message">
|
||||
<p class="list-group-item-text truncate mb-0">
|
||||
{{contact.message}}
|
||||
</p>
|
||||
<div class="mail-meta-item">
|
||||
<span class="float-right">
|
||||
<i class="ficon feather ft-paperclip mr-50" *ngIf="contact.showicon"></i>
|
||||
<span class="bullet bullet-sm {{contact.bullet}} d-inline-block rounded-circle"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<!-- email user list end -->
|
||||
|
||||
<!-- no result when nothing to show on list -->
|
||||
<div class="no-results">
|
||||
<i class="ficon feather ft-info font-large-2"></i>
|
||||
<h5>No Items Found</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--/ Email list Area -->
|
||||
|
||||
<!-- Detailed Email View -->
|
||||
<div class="email-app-details" id="app-details">
|
||||
<!-- email detail view header -->
|
||||
<div class="email-detail-header">
|
||||
<div class="email-header-left d-flex align-items-center mb-1">
|
||||
<span class="go-back mr-50">
|
||||
<i class="ficon feather ft-chevron-left font-medium-4 align-middle" (click)="showEmail($event)"></i>
|
||||
</span>
|
||||
<h5 class="email-detail-title font-weight-normal mb-0">
|
||||
Advertising Internet Online
|
||||
<span class="badge badge-light-danger badge-pill ml-1 bg-1">PRODUCT</span>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="email-header-right mb-1 ml-2 pl-1">
|
||||
<ul class="list-inline m-0">
|
||||
<li class="list-inline-item">
|
||||
<button class="btn btn-icon action-icon">
|
||||
<i class="ficon feather ft-trash-2"></i>
|
||||
</button>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<button class="btn btn-icon action-icon">
|
||||
<i class="ficon feather ft-mail"></i>
|
||||
</button>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<div class="dropdown">
|
||||
<div ngbDropdown [open]="false" [autoClose]="true" class="d-inline-block">
|
||||
<button type="button" class="dropdown-toggle btn btn-icon action-icon" id="folder"
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="dropdownMenuButton"
|
||||
dropdown-menu dropdown-menu-right show data-toggle="dropdown" aria-haspopup="true"
|
||||
aria-expanded="false" role="menu" ngbDropdownToggle>
|
||||
<i class="ficon feather ft-folder mr-0"></i>
|
||||
</button>
|
||||
<div ngbDropdownMenu="dropdownMenuButton" class="dropdown-menu dropdown-menu-right listDropdown" >
|
||||
<a class="dropdown-item" [routerLink]=""><i class="ficon feather ft-edit"></i>Draft</a>
|
||||
<a class="dropdown-item" [routerLink]=""><i class="ficon feather ft-info"></i>Spam</a>
|
||||
<a class="dropdown-item" [routerLink]=""><i class="ficon feather ft-trash-2"></i>Trash</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<div class="dropdown">
|
||||
<div ngbDropdown [open]="false" [autoClose]="true" class="d-inline-block">
|
||||
<button type="button" class="btn btn-icon dropdown-toggle action-icon" id="tag"
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="dropdownMenuButton"
|
||||
ropdown-menu dropdown-menu-right show data-toggle="dropdown" aria-haspopup="true"
|
||||
aria-expanded="false" role="menu" ngbDropdownToggle>
|
||||
<i class="ficon feather ft-tag mr-0"></i>
|
||||
</button>
|
||||
<div aria-labelledby="tag">
|
||||
<div ngbDropdownMenu="dropdownMenuButton" class="taglistDropdown">
|
||||
<a [routerLink]="" class="dropdown-item align-items-center">
|
||||
<span class="bullet bullet-sm gradient-mint d-inline-block rounded-circle "></span>
|
||||
<span>Product</span>
|
||||
</a>
|
||||
<a [routerLink]="" class="dropdown-item align-items-center">
|
||||
<span class="bullet bullet-sm gradient-primary d-inline-block rounded-circle "></span>
|
||||
<span>Work</span>
|
||||
</a>
|
||||
<a [routerLink]="" class="dropdown-item align-items-center">
|
||||
<span class="bullet bullet-sm gradient-warning d-inline-block rounded-circle "></span>
|
||||
<span>Misc</span>
|
||||
</a>
|
||||
<a [routerLink]="" class="dropdown-item align-items-center">
|
||||
<span class="bullet bullet-sm gradient-danger d-inline-block rounded-circle "></span>
|
||||
<span>Family</span>
|
||||
</a>
|
||||
<a [routerLink]="" class="dropdown-item align-items-center">
|
||||
<span class="bullet bullet-sm gradient-info d-inline-block rounded-circle "></span>
|
||||
<span> Design</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<span class="no-of-list d-none d-sm-block ml-1">1-10 of 653</span>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<button class="btn btn-icon email-pagination-prev action-icon">
|
||||
<i class='ficon feather ft-chevron-left'></i>
|
||||
</button>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<button class="btn btn-icon email-pagination-next action-icon">
|
||||
<i class='ficon feather ft-chevron-right'></i>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- email detail view header end-->
|
||||
<div class="email-scroll-area" fxFlex="auto" [perfectScrollbar]="config">
|
||||
<!-- email details -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="collapsible email-detail-head">
|
||||
<div class="card collapse-header" role="tablist" *ngFor="let email of emailDisplayList"
|
||||
[attr.id]="'emailThread'+ email.emailId" (click)="showMassage($event, email.emailId)">
|
||||
<div [attr.id]="'headingCollapse5'+email.emailId"
|
||||
class="card-header d-flex justify-content-between align-items-center" data-toggle="collapse"
|
||||
role="tab" [attr.data-target]="'collapse5'+email.emailId"
|
||||
[attr.aria-expanded]="email.isCollapsed" aria-controls="collapse5">
|
||||
<div class="collapse-title media">
|
||||
<div class="pr-1">
|
||||
<div class="avatar mr-75">
|
||||
<img [src]="email.image" alt="avtar img holder" width="30" height="30">
|
||||
</div>
|
||||
</div>
|
||||
<div class="media-body mt-25">
|
||||
<span class="text-primary">{{email.username}}</span>
|
||||
<span class="d-sm-inline d-none"> <{{email.email}};</span>
|
||||
<small class="text-muted d-block">{{email.title}}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="information d-sm-flex d-none align-items-center">
|
||||
<i class="ficon feather ft-paperclip mr-50"></i>
|
||||
<small class="text-muted mr-50">{{email.date}}</small>
|
||||
<span class="favorite" [attr.id]="'email-icon' + email.emailId" (click)="emailFavorite($event,email.emailId)" (click)="$event.stopPropagation();">
|
||||
<i class="ficon feather ft-star mr-25"></i>
|
||||
</span>
|
||||
<div class="dropdown">
|
||||
<div ngbDropdown [open]="false" [autoClose]="true" class="d-inline-block">
|
||||
<a class="dropdown-toggle " id="folder" data-toggle="dropdown" aria-haspopup="true"
|
||||
aria-expanded="false" id="dropdownMenuButton" dropdown-menu dropdown-menu-right show
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" role="menu"
|
||||
ngbDropdownToggle (click)="$event.stopPropagation();">
|
||||
<i class='ficon feather ft-more-vertical mr-0'></i>
|
||||
|
||||
</a>
|
||||
<div ngbDropdownMenu="dropdownMenuButton" class="dropdown-menu dropdown-menu-right ">
|
||||
<a class="dropdown-item" [routerLink]="">Add to another project</a>
|
||||
<a class="dropdown-item" [routerLink]="">Create follow up task</a>
|
||||
<a class="dropdown-item" [routerLink]="">Print</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="dropdown">
|
||||
|
||||
<a [routerLink]="" class="dropdown-toggle" id="fisrt-open-submenu" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">
|
||||
<i class='ficon feather ft-more-vertical mr-0'></i>
|
||||
</a>
|
||||
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div [attr.id]="'collapse5'+email.emailId" role="tabpanel"
|
||||
[attr.aria-labelledby]="'headingCollapse5'+ email.emailId" class="collapse">
|
||||
<div class="card-content">
|
||||
<div class="card-body py-1">
|
||||
<p class="text-bold-500">{{email.message}}</p>
|
||||
<p>
|
||||
{{email.descrition}}
|
||||
</p>
|
||||
<p>
|
||||
{{email.descrition_detail}}
|
||||
</p>
|
||||
<p class="mb-0"> {{email.sender}}</p>
|
||||
<p class="text-bold-500"> {{email.sender_name}}</p>
|
||||
</div>
|
||||
<div class="card-footer pt-0 border-top">
|
||||
<label class="sidebar-label">Attached Files</label>
|
||||
<ul class="list-unstyled mb-0">
|
||||
<li class="cursor-pointer pb-25">
|
||||
<img [src]="email.image_icon1" height="30" alt="psd.png">
|
||||
<small class="text-muted ml-1 attchement-text"> {{email.file_name1}}</small>
|
||||
</li>
|
||||
<li class="cursor-pointer">
|
||||
<img [src]="email.image_icon2" height="30" alt="sketch.png">
|
||||
<small class="text-muted ml-1 attchement-text"> {{email.file_name2}}</small>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- email details end-->
|
||||
<div class="row px-2 mb-4">
|
||||
<div class="col-12 px-0">
|
||||
<div class="card shadow-none border rounded">
|
||||
<div class="card-content">
|
||||
<div class="card-body quill-wrapper emailquillConfig">
|
||||
<div class="snow-container">
|
||||
|
||||
<quill-editor [styles]="{height: '80px'}" [modules]="quillConfig" (onFocus)="focus()"
|
||||
(onBlur)="blur()" >
|
||||
<span>Reply to Lois Jimenez</span></quill-editor>
|
||||
<!-- <quill-editor [styles]="{height: '100px'}" placeholder="Enter Text"
|
||||
[modules]="emailquillConfig" (onFocus)="focus()" (onBlur)="blur()"></quill-editor> -->
|
||||
|
||||
</div>
|
||||
<div class="emailtoolbar">
|
||||
<button class="btn btn-primary send-btn">
|
||||
<i class='ficon feather ft-play mr-25'></i>
|
||||
<span class="d-none d-sm-inline"> Send</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--/ Detailed Email View -->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END: Content-->
|
||||
25
src/app/content/applications/email/email.component.spec.ts
Normal file
25
src/app/content/applications/email/email.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { EmailComponent } from './email.component';
|
||||
|
||||
describe('EmailComponent', () => {
|
||||
let component: EmailComponent;
|
||||
let fixture: ComponentFixture<EmailComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ EmailComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(EmailComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
562
src/app/content/applications/email/email.component.ts
Normal file
562
src/app/content/applications/email/email.component.ts
Normal file
@@ -0,0 +1,562 @@
|
||||
import { Component, OnInit, ViewChild, Renderer2 } from '@angular/core';
|
||||
import { PerfectScrollbarConfigInterface, PerfectScrollbarComponent, PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
|
||||
import { ApplicationApiService } from '../../../_services/application-api.service';
|
||||
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
|
||||
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
||||
import { QuillInitializeServiceService } from '../../../_services/quill-initialize-service.service';
|
||||
|
||||
class Email {
|
||||
constructor(
|
||||
public emailId: number,
|
||||
public mediaClass: string,
|
||||
public starClass: string,
|
||||
public starIcon: string,
|
||||
public image: any,
|
||||
public time: string,
|
||||
public title: string,
|
||||
public message: string,
|
||||
public showicon: boolean,
|
||||
public bullet: string,
|
||||
|
||||
) { }
|
||||
}
|
||||
|
||||
class EmailHistory {
|
||||
constructor(
|
||||
public emailId: number,
|
||||
public username: string,
|
||||
public email: string,
|
||||
public image: any,
|
||||
public date: any,
|
||||
public title: string,
|
||||
public message: string,
|
||||
public descrition: string,
|
||||
public descrition_detail: string,
|
||||
public sender: string,
|
||||
public sender_name: string,
|
||||
public iconClass: string,
|
||||
public image_icon1: string,
|
||||
public file_name1: string,
|
||||
public image_icon2: string,
|
||||
public file_name2: string
|
||||
) { }
|
||||
}
|
||||
class EmailMenu {
|
||||
constructor(
|
||||
public Id: string,
|
||||
public name: string,
|
||||
public icon: string,
|
||||
public budge: string,
|
||||
public budgeClass: string,
|
||||
public budgeIcon: boolean,
|
||||
public isSelected: false
|
||||
) { }
|
||||
}
|
||||
class EmailLable {
|
||||
constructor(
|
||||
public Id: string,
|
||||
public name: string,
|
||||
public isSelected: boolean,
|
||||
public bulletClass: string,
|
||||
) { }
|
||||
}
|
||||
@Component({
|
||||
selector: 'app-email',
|
||||
templateUrl: './email.component.html',
|
||||
styleUrls: ['./email.component.css'],
|
||||
})
|
||||
export class EmailComponent implements OnInit {
|
||||
public config: PerfectScrollbarConfigInterface = { wheelPropagation: true };
|
||||
@ViewChild(PerfectScrollbarComponent)
|
||||
componentRef?: PerfectScrollbarComponent;
|
||||
directiveRef?: PerfectScrollbarDirective;
|
||||
@ViewChild(PerfectScrollbarDirective, { static: true })
|
||||
|
||||
isHidden = false;
|
||||
isShown = true;
|
||||
emailList: any[] = [];
|
||||
emailDisplayList: any[] = [];
|
||||
emailMenuList: any[] = [];
|
||||
email: EmailHistory[];
|
||||
emailLable: EmailLable[];
|
||||
emailArray: any;
|
||||
temp = [];
|
||||
temp2 = this.emailList;
|
||||
isSelected: boolean;
|
||||
isCollapsed = false;
|
||||
selectAll = false;
|
||||
selected: [];
|
||||
blured = false;
|
||||
focused = false;
|
||||
hide = false;
|
||||
htmlText = 'Type Something';
|
||||
form: FormGroup;
|
||||
atValues = [
|
||||
{ id: 1, value: 'Fredrik Sundqvist', link: 'https://google.com' },
|
||||
{ id: 2, value: 'Patrik Sjölin' }
|
||||
];
|
||||
hashValues = [
|
||||
{ id: 3, value: 'Fredrik Sundqvist 2' },
|
||||
{ id: 4, value: 'Patrik Sjölin 2' }
|
||||
];
|
||||
quillConfig = {
|
||||
toolbar: {
|
||||
container: [
|
||||
['bold', 'italic', 'underline', 'strike'],
|
||||
]
|
||||
},
|
||||
autoLink: true,
|
||||
keyboard: {
|
||||
bindings: {
|
||||
enter: {
|
||||
key: 13,
|
||||
handler: (range, context) => {
|
||||
console.log('enter');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
emailquillConfig = {
|
||||
toolbar: {
|
||||
container: [
|
||||
['bold', 'italic', 'underline', 'strike'],
|
||||
]
|
||||
},
|
||||
autoLink: true
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param ApplicationApiService emailApiService
|
||||
* @param Renderer2 renderer
|
||||
*/
|
||||
constructor(
|
||||
private emailApiService: ApplicationApiService,
|
||||
private renderer: Renderer2,
|
||||
private QuillInitializeServiceServicec: QuillInitializeServiceService,
|
||||
fb: FormBuilder
|
||||
) {
|
||||
this.form = fb.group({
|
||||
editor: ['']
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* OnInit
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.emailApiService.getEmailData().subscribe(Response => {
|
||||
this.emailArray = Response;
|
||||
this.emailDisplayList = Response.EmailHistory;
|
||||
this.emailMenuList = Response.EmailMenu;
|
||||
this.emailLable = Response.EmailLable;
|
||||
this.email = this.emailArray.EmailHistory[1];
|
||||
this.emailList.push(
|
||||
new Email(
|
||||
1,
|
||||
'media mail-read',
|
||||
'favorite warning',
|
||||
'ficon feather ft-star',
|
||||
'../../../assets/images/portrait/small/avatar-s-1.png',
|
||||
'4.14 AM',
|
||||
'Open source project public release 👍',
|
||||
'Hey John, bah kivu decrete epanorthotic unnotched Argyroneta nonius veratrine preimaginary ',
|
||||
false,
|
||||
'gradient-mint',
|
||||
)
|
||||
);
|
||||
this.emailList.push(
|
||||
new Email(
|
||||
2,
|
||||
'media mail-read',
|
||||
'favorite',
|
||||
'ficon feather ft-star',
|
||||
'../../../assets/images/portrait/small/avatar-s-2.png',
|
||||
'2.15 AM',
|
||||
'Ecommerce website Paypal integration 😃',
|
||||
' We will start the new application development soon once this will be completed. ',
|
||||
false,
|
||||
'gradient-danger',
|
||||
)
|
||||
);
|
||||
this.emailList.push(
|
||||
new Email(
|
||||
3,
|
||||
'media',
|
||||
'favorite warning',
|
||||
'ficon feather ft-star',
|
||||
'../../../assets/images/portrait/small/avatar-s-3.png',
|
||||
'11.18AM',
|
||||
'How To Set Intentions That Energize You',
|
||||
' I will provide you more details after this Saturday. Hope that will be fine for you.. ',
|
||||
true,
|
||||
'gradient-mint',
|
||||
)
|
||||
);
|
||||
this.emailList.push(
|
||||
new Email(
|
||||
4,
|
||||
'media',
|
||||
'favorite',
|
||||
'ficon feather ft-star',
|
||||
'../../../assets/images/portrait/small/avatar-s-4.png',
|
||||
'Yesterday',
|
||||
'Harness The Power Of Words In Your Life',
|
||||
'When the equation, first to ability the forwards, the a but travelling, outlines sentinels bad expand to goodness....',
|
||||
true,
|
||||
'gradient-warning',
|
||||
)
|
||||
);
|
||||
this.emailList.push(
|
||||
new Email(
|
||||
5,
|
||||
'media mail-read',
|
||||
'favorite',
|
||||
'ficon feather ft-star',
|
||||
'../../../assets/images/portrait/small/avatar-s-5.png',
|
||||
'24 Feb',
|
||||
'Helen Keller A Teller And A Seller',
|
||||
'Thanks for your feedback ! Here`s a new layout for a new Modern Admin theme.',
|
||||
true,
|
||||
'gradient-warning',
|
||||
)
|
||||
);
|
||||
this.emailList.push(
|
||||
new Email(
|
||||
6,
|
||||
'media mail-read',
|
||||
'favorite warning',
|
||||
'ficon feather ft-star',
|
||||
'../../../assets/images/portrait/small/avatar-s-6.png',
|
||||
'15 March',
|
||||
'Use Your Reset Button To Change Your Vibration 🎉',
|
||||
'Hey John, bah kivu decrete epanorthotic unnotched Argyroneta nonius veratrine preimaginary',
|
||||
false,
|
||||
'gradient-info',
|
||||
)
|
||||
);
|
||||
this.emailList.push(
|
||||
new Email(
|
||||
7,
|
||||
'media',
|
||||
'favorite',
|
||||
'ficon feather ft-star',
|
||||
'../../../assets/images/portrait/small/avatar-s-7.png',
|
||||
'12-07-2019',
|
||||
'Will connect you',
|
||||
'Hi Kelly!',
|
||||
false,
|
||||
'gradient-mint',
|
||||
)
|
||||
);
|
||||
this.emailList.push(
|
||||
new Email(
|
||||
8,
|
||||
'media mail-read',
|
||||
'favorite',
|
||||
'ficon feather ft-star',
|
||||
'../../../assets/images/portrait/small/avatar-s-8.png',
|
||||
'03-29-2019',
|
||||
'Harness The Power Of Words In Your Life',
|
||||
'Hope your like it, or feel free to comment, feedback or rebound !',
|
||||
false,
|
||||
'gradient-danger'
|
||||
)
|
||||
);
|
||||
this.emailList.push(
|
||||
new Email(
|
||||
9,
|
||||
'media ',
|
||||
'favorite warning',
|
||||
'ficon feather ft-star',
|
||||
'../../../assets/images/portrait/small/avatar-s-9.png',
|
||||
'19 Jun',
|
||||
'Hypnosis 12 Steps To Acquire Mind Power',
|
||||
'Monstrous with geared from far and these, morals, phase rome; Class. Called get amidst of geared from next...',
|
||||
false,
|
||||
'gradient-info'
|
||||
)
|
||||
);
|
||||
this.emailList.push(
|
||||
new Email(
|
||||
10,
|
||||
'media ',
|
||||
'favorite warning',
|
||||
'ficon feather ft-star',
|
||||
'../../../assets/images/portrait/small/avatar-s-10.png',
|
||||
'21 Mar',
|
||||
' Know Yourself Your Inner Power ',
|
||||
' Hope your like it, or feel free to comment, feedback or rebound.',
|
||||
false,
|
||||
'gradient-warning'
|
||||
)
|
||||
);
|
||||
|
||||
});
|
||||
this.form
|
||||
.controls
|
||||
.editor
|
||||
.valueChanges.pipe(
|
||||
debounceTime(400),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
.subscribe((data) => {
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Search email
|
||||
*
|
||||
* @param event Convert value uppercase to lowercase;
|
||||
*/
|
||||
updateFilter(event) {
|
||||
const value = event.target.value.toLowerCase();
|
||||
this.emailList = [...this.temp2]; // and here you have to initialize it with your data
|
||||
this.temp = [...this.emailList];
|
||||
// filter our data
|
||||
const temp = this.emailList.filter(function (d) {
|
||||
return d.name.toLowerCase().indexOf(value) !== -1 || !value;
|
||||
});
|
||||
// update the rows
|
||||
this.emailList = temp;
|
||||
// Whenever the filter changes, always go back to the first page
|
||||
}
|
||||
/**
|
||||
* Overlay add/remove fuction in responsive
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
contentOverlay(event) {
|
||||
const toggleIcon = document.getElementById('email-app-menu');
|
||||
const toggle = document.getElementById('content-overlay');
|
||||
if (event.currentTarget.className === 'content-overlay show') {
|
||||
this.renderer.removeClass(toggleIcon, 'show');
|
||||
this.renderer.removeClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add overlay when open sidebar
|
||||
*
|
||||
* @param event Content overlay
|
||||
*/
|
||||
contentRightSidebar(event) {
|
||||
const toggle = document.getElementById('content-right');
|
||||
if (event.currentTarget.className === 'media _media border-0 ng-star-inserted active') {
|
||||
this.renderer.addClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove overlay when close sidebar
|
||||
*
|
||||
* @param event Content overlay
|
||||
*/
|
||||
contentRight(event) {
|
||||
const toggle = document.getElementById('content-right');
|
||||
if (event.currentTarget.className === 'btn btn-primary go-back') {
|
||||
this.renderer.removeClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Open Media-body
|
||||
*
|
||||
* @param event Mail Read
|
||||
*/
|
||||
showEmail(event) {
|
||||
const toggleIcon = document.getElementById('app-details');
|
||||
if (event.currentTarget.className === 'media-body') {
|
||||
this.renderer.addClass(toggleIcon, 'show');
|
||||
} else if (event.currentTarget.className === 'ficon feather ft-chevron-left font-medium-4 align-middle') {
|
||||
this.renderer.removeClass(toggleIcon, 'show');
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @'param' event
|
||||
* @'param' emailId
|
||||
*/
|
||||
showMassage(event, emailId) {
|
||||
for (let i = 1; i <= this.emailDisplayList.length; i++) {
|
||||
if (emailId === i) {
|
||||
const toggleIcon = document.getElementById('headingCollapse5' + emailId);
|
||||
const toggle = document.getElementById('collapse5' + emailId);
|
||||
const toggleHeader = document.getElementById('emailThread' + emailId);
|
||||
if (event.currentTarget.className === 'card collapse-header ng-star-inserted') {
|
||||
this.renderer.addClass(toggle, 'show');
|
||||
this.renderer.addClass(toggleHeader, 'open');
|
||||
this.renderer.removeClass(toggleIcon, 'collapsed');
|
||||
this.emailDisplayList[i - 1].isCollapsed = true;
|
||||
} else if (event.currentTarget.className === 'card collapse-header ng-star-inserted open') {
|
||||
this.renderer.removeClass(toggle, 'show');
|
||||
this.renderer.removeClass(toggleHeader, 'open');
|
||||
this.renderer.addClass(toggleIcon, 'collapsed');
|
||||
this.emailDisplayList[i - 1].isCollapsed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Add overlay when open sidebar
|
||||
*
|
||||
* @param event Content overlay
|
||||
*/
|
||||
showComposeSidebar(event) {
|
||||
const toggleIcon = document.getElementById('compose-sidebar');
|
||||
const toggleSidebar = document.getElementById('sidebar-left');
|
||||
const toggleOverlay = document.getElementById('app-content-overlay');
|
||||
if (event.currentTarget.className === 'btn btn-danger btn-glow btn-block my-2 compose-btn') {
|
||||
this.renderer.addClass(toggleIcon, 'show');
|
||||
this.renderer.removeClass(toggleSidebar, 'show');
|
||||
this.renderer.addClass(toggleOverlay, 'show');
|
||||
} else if (event.currentTarget.className === 'btn btn-danger btn-glow btn-block my-2 compose-btn show') {
|
||||
this.renderer.removeClass(toggleIcon, 'show');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Remove overlay when open sidebar
|
||||
*
|
||||
* @param event Content overlay
|
||||
*/
|
||||
showCompose(event) {
|
||||
const toggleIcon = document.getElementById('compose-sidebar');
|
||||
const toggleOverlay = document.getElementById('app-content-overlay');
|
||||
if (event.currentTarget.className === 'close close-icon' || 'app-content-overlay') {
|
||||
this.renderer.removeClass(toggleIcon, 'show');
|
||||
this.renderer.removeClass(toggleOverlay, 'show');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Add overlay when open sidebar
|
||||
*
|
||||
* @param event Content overlay
|
||||
*/
|
||||
showSidebar(event) {
|
||||
const toggleIcon = document.getElementById('sidebar-left');
|
||||
const toggle = document.getElementById('app-content-overlay');
|
||||
if (event.currentTarget.className === 'sidebar-toggle d-block d-lg-none') {
|
||||
this.renderer.addClass(toggleIcon, 'show');
|
||||
this.renderer.addClass(toggle, 'show');
|
||||
} else if (event.currentTarget.className === 'sidebar-close-icon' || 'app-content-overlay') {
|
||||
this.renderer.removeClass(toggleIcon, 'show');
|
||||
this.renderer.removeClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Filter Email
|
||||
*
|
||||
* @param term search term
|
||||
*/
|
||||
search(term) {
|
||||
const searchTerm = term.currentTarget.value;
|
||||
if (searchTerm !== '') {
|
||||
this.emailList = this.emailList.filter(result => {
|
||||
if (result && searchTerm) {
|
||||
if (result.title.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1 ||
|
||||
result.message.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.emailList = this.temp2;
|
||||
}
|
||||
}
|
||||
|
||||
selectAllEmails() {
|
||||
for (let i = 0; i < this.emailList.length; i++) {
|
||||
if (this.selectAll) {
|
||||
this.emailList[i].isSelected = false;
|
||||
} else {
|
||||
this.emailList[i].isSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deleteCheckedRow() {
|
||||
let index = 0;
|
||||
const removedIndex = [];
|
||||
const temp = [...this.emailList];
|
||||
for (const row of temp) {
|
||||
if (row.isSelected === true) {
|
||||
removedIndex.push(index);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
for (let i = removedIndex.length - 1; i >= 0; i--) {
|
||||
temp.splice(removedIndex[i], 1);
|
||||
}
|
||||
this.emailList = temp;
|
||||
this.selectAll = false;
|
||||
}
|
||||
showEmailMenu(Id, emailMenu) {
|
||||
for (let j = 0; j < emailMenu.length; j++) {
|
||||
for (let i = 0; i < this.emailMenuList.length; i++) {
|
||||
for (let k = 0; k < this.emailLable.length; k++) {
|
||||
if (emailMenu[j].name === this.emailMenuList[i].name) {
|
||||
if (Id !== this.emailMenuList[i].Id) {
|
||||
this.emailMenuList[i].isSelected = false;
|
||||
}
|
||||
if (Id === this.emailMenuList[i].Id) {
|
||||
this.emailMenuList[i].isSelected = true;
|
||||
this.emailLable[k].isSelected = false;
|
||||
}
|
||||
} else if (emailMenu[j].name === this.emailLable[k].name) {
|
||||
if (Id !== this.emailLable[k].Id) {
|
||||
this.emailLable[k].isSelected = false;
|
||||
}
|
||||
if (Id === this.emailLable[k].Id) {
|
||||
this.emailLable[k].isSelected = true;
|
||||
this.emailMenuList[i].isSelected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const friend of this.emailMenuList) {
|
||||
if (friend.Id === Id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
focus() {
|
||||
this.focused = true;
|
||||
this.blured = false;
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.focused = false;
|
||||
this.blured = true;
|
||||
}
|
||||
|
||||
setControl() {
|
||||
this.form.setControl('editor', new FormControl('test - new Control'));
|
||||
}
|
||||
/**
|
||||
* Filter Email
|
||||
*
|
||||
* @ param event warning Class
|
||||
* @ param emailId
|
||||
*/
|
||||
emailFavorite(event, emailId) {
|
||||
for (let i = 1; i <= this.emailDisplayList.length; i++) {
|
||||
if (emailId === i) {
|
||||
const emailIcon = document.getElementById('email-icon' + emailId);
|
||||
const emailstarIcon = document.getElementById('emailstar-icon' + emailId);
|
||||
if (event.currentTarget.className === 'favorite') {
|
||||
this.renderer.addClass(emailIcon, 'warning');
|
||||
this.renderer.addClass(emailstarIcon, 'warning');
|
||||
} else if (event.currentTarget.className === 'favorite warning') {
|
||||
this.renderer.removeClass(emailIcon, 'warning');
|
||||
this.renderer.removeClass(emailstarIcon, 'warning');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
src/app/content/applications/email/email.module.spec.ts
Normal file
13
src/app/content/applications/email/email.module.spec.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { EmailModule } from './email.module';
|
||||
|
||||
describe('EmailModule', () => {
|
||||
let emailModule: EmailModule;
|
||||
|
||||
beforeEach(() => {
|
||||
emailModule = new EmailModule();
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
expect(emailModule).toBeTruthy();
|
||||
});
|
||||
});
|
||||
34
src/app/content/applications/email/email.module.ts
Normal file
34
src/app/content/applications/email/email.module.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { EmailComponent } from './email.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
|
||||
import { QuillModule } from 'ngx-quill';
|
||||
import { CustomFormsModule } from 'ngx-custom-validators';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { BreadcrumbModule } from 'src/app/_layout/breadcrumb/breadcrumb.module';
|
||||
import { ArchwizardModule } from 'angular-archwizard';
|
||||
import { BlockUIModule } from 'ng-block-ui';
|
||||
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
NgbModule,
|
||||
FormsModule,
|
||||
QuillModule.forRoot(),
|
||||
CustomFormsModule,
|
||||
PerfectScrollbarModule,
|
||||
ArchwizardModule,
|
||||
BreadcrumbModule,
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: EmailComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
declarations: [EmailComponent]
|
||||
})
|
||||
export class EmailModule { }
|
||||
31
src/app/content/applications/kanban/kanban.module.ts
Normal file
31
src/app/content/applications/kanban/kanban.module.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { KanbanComponent } from './kanban/kanban.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { NgSelectModule } from '@ng-select/ng-select';
|
||||
import { QuillModule } from 'ngx-quill';
|
||||
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
|
||||
import { DndListModule } from 'ngx-drag-and-drop-lists';
|
||||
|
||||
@NgModule({
|
||||
declarations: [KanbanComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
NgbModule,
|
||||
FormsModule,
|
||||
NgSelectModule,
|
||||
QuillModule.forRoot(),
|
||||
DndListModule,
|
||||
ReactiveFormsModule,
|
||||
PerfectScrollbarModule,
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: KanbanComponent
|
||||
}
|
||||
])
|
||||
]
|
||||
})
|
||||
export class KanbanModule { }
|
||||
496
src/app/content/applications/kanban/kanban/kanban.component.css
Normal file
496
src/app/content/applications/kanban/kanban/kanban.component.css
Normal file
@@ -0,0 +1,496 @@
|
||||
.mr-25, .mx-25 {
|
||||
margin-right: .25rem!important;
|
||||
}
|
||||
.mr-50, .mx-50 {
|
||||
margin-right: .5rem!important;
|
||||
}
|
||||
.dropdown .dropdown-menu
|
||||
{
|
||||
transform: translate3d(-130px, 24px, 0px) !important;
|
||||
}
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
color: #fff;
|
||||
background-color: #666ee8 !important;
|
||||
}
|
||||
:host ::ng-deep .ng-arrow {
|
||||
top: -2px;
|
||||
border-color: transparent transparent #fff !important;
|
||||
}
|
||||
:host ::ng-deep .ng-arrow-wrapper {
|
||||
top: -2px;
|
||||
border-color: transparent transparent #fff !important;
|
||||
border-width: 0 5px 5px !important;
|
||||
|
||||
}
|
||||
:host ::ng-deep .ng-select .ng-select-container {
|
||||
height: calc(1.25em + 1.5rem + 2px)!important;
|
||||
padding: .75rem 1rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.25;
|
||||
}
|
||||
:host ::ng-deep .ng-select {
|
||||
position: relative;
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:host ::ng-deep .ml-25, .mx-25 {
|
||||
margin-left: .25rem!important;
|
||||
}
|
||||
:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option {
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
min-height: 1.2em;
|
||||
padding: 0px 5px 1px;
|
||||
}
|
||||
:host ::ng-deep .text {
|
||||
/* display: block;
|
||||
width: 100%; */
|
||||
height: calc(1.25em + 1.5rem + 2px);
|
||||
padding: .75rem 1rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.25;
|
||||
/* color: #4e5154; */
|
||||
background-color: #fff;
|
||||
background-clip: padding-box;
|
||||
border: 1px solid #babfc7;
|
||||
border-radius: .25rem;
|
||||
/* transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out; */
|
||||
}
|
||||
:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option .bg-primary {
|
||||
background-color: #666ee8!important;
|
||||
}
|
||||
ng-reflect-ng-item-label{
|
||||
background-color: #ff4961!important;
|
||||
}
|
||||
:host ::ng-deep .bg-danger {
|
||||
background-color: #ff4961!important;
|
||||
}
|
||||
:host ::ng-deep .justify-scontent-between {
|
||||
justify-content: space-between!important;
|
||||
}
|
||||
/* datepicker css */
|
||||
:host ::ng-deep .btn-light:not(:disabled):not(.disabled):active {
|
||||
color: unset !important;
|
||||
background-color: unset !important;
|
||||
border-color: #d3d9df !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .btn-light:hover:not(.disabled):active {
|
||||
background-color: #e2e6ea !important;
|
||||
border-color: #dae0e5 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .btn-light {
|
||||
color: unset !important;
|
||||
background-color: unset !important;
|
||||
border-color: unset !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .bg-primary {
|
||||
background-color: #007bff !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .text-white {
|
||||
color: #fff !important;
|
||||
|
||||
}
|
||||
|
||||
:host ::ng-deep .custom-day {
|
||||
text-align: center;
|
||||
padding: .185rem .25rem;
|
||||
display: inline-block;
|
||||
height: 2rem;
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
:host ::ng-deep .custom-day:active {
|
||||
color: #6d7183 !important;
|
||||
background-color: #fff !important;
|
||||
border-block-color: rgb(2, 117, 216) !important;
|
||||
|
||||
}
|
||||
|
||||
.bg-light {
|
||||
background-color: #f8f9fa !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .hidden {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.ngb-dp-weekday {
|
||||
color: #17a2b8;
|
||||
}
|
||||
|
||||
.ngb-dp-week-number,
|
||||
.ngb-dp-weekday {
|
||||
line-height: 2rem;
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.ngb-datepicker-month-view {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 80%;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.ngb-dp-day {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
.ngb-dp-month {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.btn-light:hover {
|
||||
color: #212529 !important;
|
||||
background-color: #e2e6ea !important;
|
||||
border-color: #dae0e5 !important;
|
||||
}
|
||||
|
||||
.ngb-datepicker-month-view {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.ngb-dp-header {
|
||||
border-bottom: 0;
|
||||
border-radius: .25rem .25rem 0 0;
|
||||
padding-top: .25rem;
|
||||
}
|
||||
|
||||
.ngb-dp-day,
|
||||
.ngb-dp-week-number,
|
||||
.ngb-dp-weekday {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.custom-day {
|
||||
text-align: center;
|
||||
padding: 0.185rem 0.25rem;
|
||||
display: inline-block;
|
||||
height: 2rem;
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.custom-day.focused {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
.custom-day.range,
|
||||
.custom-day:hover {
|
||||
background-color: rgb(2, 117, 216);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.custom-day.faded {
|
||||
background-color: rgba(2, 117, 216, 0.5);
|
||||
}
|
||||
|
||||
:host ::ng-deep .block-ui-wrapper {
|
||||
background: rgba(255, 249, 249, 0.5) !important;
|
||||
}
|
||||
|
||||
.custom-day {
|
||||
text-align: center;
|
||||
padding: 0.185rem 0.25rem;
|
||||
border-radius: 0.25rem;
|
||||
display: inline-block;
|
||||
width: 2rem;
|
||||
}
|
||||
.custom-day:hover, .custom-day.focused {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
.weekend {
|
||||
background-color: #f0ad4e;
|
||||
border-radius: 1rem;
|
||||
color: white;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
:host ::ng-deep .ft-calendar{
|
||||
font-family: feather!important;
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: large;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
:host ::ng-deep .input-group-text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: unset !important;
|
||||
margin-bottom: unset !important;
|
||||
font-size: unset !important;
|
||||
font-weight: unset !important;
|
||||
line-height: unset !important;
|
||||
color:unset !important;
|
||||
text-align: unset !important;
|
||||
white-space: unset !important;
|
||||
background-color: unset !important;
|
||||
border: unset !important;
|
||||
border-radius: unset !important;
|
||||
}
|
||||
.ml-75, .mx-75 {
|
||||
margin-left: .75rem!important;
|
||||
}
|
||||
.mx-50 {
|
||||
margin-left: .5rem!important;
|
||||
}
|
||||
.sidebar {
|
||||
width : 270px !important;
|
||||
}
|
||||
.align-middle {
|
||||
margin-left: 3px;
|
||||
}
|
||||
.mr-50, .mx-50 {
|
||||
margin-right: .5rem!important;
|
||||
}
|
||||
:host ::ng-deep .ft-plus{
|
||||
margin-right: 3px !important;
|
||||
}
|
||||
control:disabled, .form-control[readonly] {
|
||||
background-color: #ffffff;
|
||||
margin-left: -12px;
|
||||
}
|
||||
/* Kanban Board Application css */
|
||||
/*------------------------------*/
|
||||
.kanban-container {
|
||||
width : 100% !important;
|
||||
}
|
||||
.kanban-container .kanban-board {
|
||||
border-radius : 0.25rem;
|
||||
padding : 1rem 0rem;
|
||||
margin : 0 1.8rem 1rem 0 !important;
|
||||
width : 18.67rem !important;
|
||||
background-color : #E7EDF3;
|
||||
}
|
||||
.kanban-container .kanban-board .kanban-board-header {
|
||||
/* kanban-header */
|
||||
font-size : 1.2rem;
|
||||
font-family : 'Quicksand', Georgia, 'Times New Roman', Times, serif;
|
||||
color : #6B6F82;
|
||||
padding : 0 0.93rem;
|
||||
display : -webkit-box;
|
||||
display : -webkit-flex;
|
||||
display : -ms-flexbox;
|
||||
display : flex;
|
||||
-webkit-box-pack : justify;
|
||||
-webkit-justify-content : space-between;
|
||||
-ms-flex-pack : justify;
|
||||
justify-content : space-between;
|
||||
}
|
||||
.kanban-container .kanban-board .kanban-board-header .dropdown {
|
||||
float : right;
|
||||
}
|
||||
.kanban-container .kanban-board .kanban-board-header .dropdown .dropdown-toggle:after {
|
||||
display : none;
|
||||
}
|
||||
.kanban-container .kanban-board .kanban-board-header .kanban-title-board {
|
||||
/* kanban title */
|
||||
font-weight : normal;
|
||||
cursor : text;
|
||||
padding : 0 0.5rem;
|
||||
width : 200px;
|
||||
}
|
||||
.kanban-container .kanban-board .kanban-board-header .kanban-title-board:hover, .kanban-container .kanban-board .kanban-board-header .kanban-title-board:focus {
|
||||
background-color : #6B6F82;
|
||||
color : #FFFFFF;
|
||||
border-radius : 0.25rem;
|
||||
outline : none;
|
||||
text-overflow : clip;
|
||||
}
|
||||
.kanban-container .kanban-board .kanban-board-header .kanban-title-button {
|
||||
/* kanban title button */
|
||||
position : absolute;
|
||||
bottom : 0;
|
||||
padding : 0.467rem 0rem;
|
||||
display : block;
|
||||
color : #6B6F82;
|
||||
font-weight : 700;
|
||||
font-size : 0.8rem;
|
||||
}
|
||||
.kanban-container .kanban-board .kanban-drag {
|
||||
padding : 13px;
|
||||
min-height : auto;
|
||||
}
|
||||
.kanban-container .kanban-board .kanban-item {
|
||||
/* kanban item */
|
||||
padding : 0.53rem 0.8rem;
|
||||
border-radius : 0.25rem;
|
||||
margin-bottom : 1rem;
|
||||
box-shadow : -4px 4px 6px 0 rgba(55, 70, 95, 0.12);
|
||||
position : relative;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
.kanban-container .kanban-board .kanban-item:before {
|
||||
content : '';
|
||||
width : 3px;
|
||||
height : 100%;
|
||||
position : absolute;
|
||||
left : 0;
|
||||
top : 0;
|
||||
border-radius : 0.5rem;
|
||||
}
|
||||
.kanban-container .kanban-board .kanban-item:hover {
|
||||
cursor : default;
|
||||
}
|
||||
.kanban-container .kanban-board .kanban-item:last-child {
|
||||
margin-bottom : 0.5rem;
|
||||
}
|
||||
.kanban-container .kanban-board .kanban-item .kanban-image img {
|
||||
border-radius : 0.25rem;
|
||||
}
|
||||
|
||||
.kanban-overlay {
|
||||
/* kanban overlay */
|
||||
top : 0;
|
||||
left : 0;
|
||||
right : 0;
|
||||
bottom : 0;
|
||||
position : absolute;
|
||||
z-index : 999;
|
||||
visibility : hidden;
|
||||
opacity : 0;
|
||||
}
|
||||
.kanban-overlay.show {
|
||||
visibility : visible;
|
||||
-webkit-transition : all 0.3s ease;
|
||||
transition : all 0.3s ease;
|
||||
opacity : 1;
|
||||
background-color : rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.badge-circle {
|
||||
display : -webkit-box;
|
||||
display : -webkit-flex;
|
||||
display : -ms-flexbox;
|
||||
display : flex;
|
||||
-webkit-box-align : center;
|
||||
-webkit-align-items : center;
|
||||
-ms-flex-align : center;
|
||||
align-items : center;
|
||||
-webkit-box-pack : center;
|
||||
-webkit-justify-content : center;
|
||||
-ms-flex-pack : center;
|
||||
justify-content : center;
|
||||
background-color : #E6EAEE;
|
||||
color : #475F7B;
|
||||
border-radius : 50%;
|
||||
height : 30px;
|
||||
width : 30px;
|
||||
}
|
||||
|
||||
.avatar img {
|
||||
border : 2px solid #FFFFFF;
|
||||
}
|
||||
|
||||
.kanban-sidebar {
|
||||
/* kanban sidebar */
|
||||
box-shadow : -8px 0 18px 0 rgba(25, 42, 70, 0.13);
|
||||
height : 100vh;
|
||||
width : 23.8rem;
|
||||
background-color : #FFFFFF;
|
||||
position : fixed;
|
||||
-webkit-transform : translateX(110%);
|
||||
-ms-transform : translateX(110%);
|
||||
transform : translateX(110%);
|
||||
-webkit-transition : all 0.3s ease;
|
||||
transition : all 0.3s ease;
|
||||
z-index : 1050;
|
||||
right : 2rem;
|
||||
left : auto;
|
||||
bottom : 0;
|
||||
top : -1px;
|
||||
opacity : 0;
|
||||
overflow : hidden;
|
||||
}
|
||||
.kanban-sidebar .card-header .close-icon {
|
||||
color : #6B6F82;
|
||||
opacity : 1 !important;
|
||||
}
|
||||
.kanban-sidebar .card-header .close-icon:focus {
|
||||
outline : none;
|
||||
}
|
||||
.kanban-sidebar.show {
|
||||
opacity : 1;
|
||||
-webkit-transform : translateX(9%) translateY(1px);
|
||||
-ms-transform : translateX(9%) translateY(1px);
|
||||
transform : translateX(9%) translateY(1px);
|
||||
}
|
||||
.kanban-sidebar .edit-kanban-item {
|
||||
height : 100vh;
|
||||
}
|
||||
.kanban-sidebar .edit-kanban-item .card-content {
|
||||
height : calc(100% - 9rem);
|
||||
}
|
||||
.kanban-sidebar .edit-kanban-item .card-content .form-group > label {
|
||||
color : #BAC0C7;
|
||||
margin-bottom : 0.67rem;
|
||||
}
|
||||
.kanban-sidebar .edit-kanban-item .card-content .form-group select {
|
||||
border-radius : 0.25rem;
|
||||
display : block;
|
||||
}
|
||||
.kanban-sidebar .edit-kanban-item .card-content .custom-file .custom-file-label:after {
|
||||
background-color : transparent;
|
||||
}
|
||||
.kanban-sidebar .edit-kanban-item .card-footer .btn i {
|
||||
top : 0;
|
||||
}
|
||||
.kanban-sidebar .edit-kanban-item .picker {
|
||||
position : relative;
|
||||
}
|
||||
.kanban-sidebar .quill-wrapper .snow-container .ql-snow, .kanban-sidebar .quill-wrapper .snow-container .ql-toolbar {
|
||||
border : none;
|
||||
}
|
||||
.kanban-sidebar .quill-wrapper .snow-container .ql-toolbar .btn {
|
||||
width : auto;
|
||||
line-height : 0.9;
|
||||
padding : 0.467rem 1.2rem;
|
||||
}
|
||||
.kanban-sidebar .quill-wrapper .snow-container .ql-toolbar .btn:hover {
|
||||
color : #FFFFFF;
|
||||
}
|
||||
.kanban-sidebar .quill-wrapper .snow-container .ql-tooltip {
|
||||
left : 0 !important;
|
||||
}
|
||||
.kanban-sidebar .quill-wrapper .snow-container .ql-tooltip input[type=text] {
|
||||
width : 100px;
|
||||
}
|
||||
.kanban-sidebar .quill-wrapper .ql-editor.ql-blank::before {
|
||||
left : 0.3rem;
|
||||
}
|
||||
.kanban-sidebar .quill-wrapper .ql-editor {
|
||||
min-height : 7.93rem;
|
||||
padding : 0;
|
||||
}
|
||||
|
||||
.kanban-title-button {
|
||||
background-color : transparent;
|
||||
box-shadow : none;
|
||||
}
|
||||
|
||||
@media (max-width: 420px) {
|
||||
.kanban-sidebar {
|
||||
width : 19rem;
|
||||
right : 1.6rem;
|
||||
}
|
||||
.kanban-sidebar .quill-wrapper .snow-container .ql-tooltip input[type=text] {
|
||||
width : 70px;
|
||||
}
|
||||
}
|
||||
204
src/app/content/applications/kanban/kanban/kanban.component.html
Normal file
204
src/app/content/applications/kanban/kanban/kanban.component.html
Normal file
@@ -0,0 +1,204 @@
|
||||
<div class="app-content content">
|
||||
<div class="content-overlay"></div>
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row">
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<!-- Basic Kanban App -->
|
||||
<div class="kanban-overlay" id="content-overlay" (click)="showSidebar($event)"></div>
|
||||
<section id="kanban-wrapper">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<button type="button" class="btn btn-primary mb-1" id="add-kanban" (click)="addKanbanBoard()">
|
||||
<i class='ficon feather ft-plus-square mr-50'></i> Add New Board
|
||||
</button>
|
||||
<div id="kanban-app"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kanban-sidebar" id="kanban_sidebar">
|
||||
<div class="card shadow-none quill-wrapper">
|
||||
<div class="card-header d-flex justify-scontent-between align-items-center border-bottom px-2 py-1">
|
||||
<h3 class="card-title">UI Design</h3>
|
||||
<button type="button" class="close close-icon">
|
||||
<i class="ficon feather ft-x" (click)="showSidebar($event)"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- form start -->
|
||||
<form [formGroup]="kanban" class="edit-kanban-item">
|
||||
<div class="card-content position-relative" [perfectScrollbar]="config">
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label>Card Title</label>
|
||||
<input type="text" formControlName="title" class="form-control edit-kanban-item-title"
|
||||
placeholder="kanban Title">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Due Date</label>
|
||||
<!-- <input type="text" formControlName="date" class="form-control edit-kanban-item-date"
|
||||
placeholder="21 August, 2019"> -->
|
||||
<div class="input-group">
|
||||
<div class="input-group-text mr-50">
|
||||
</div>
|
||||
<input class="form-control" placeholder="yyyy-mm-dd" formControlName="date" name="date"
|
||||
ngbDatepicker #d2="ngbDatepicker" (click)="d2.toggle()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<div class="col-6">
|
||||
<label>Label </label>
|
||||
<select class="form-control text-white " bindLabel="name" formControlName="selectedLabel"
|
||||
(change)="getSelectedKanbanText($event)" id="selectLable">
|
||||
<option class="bg-primary">Primary</option>
|
||||
<option class="bg-danger">Danger</option>
|
||||
<option class="bg-success">Success</option>
|
||||
<option class="bg-info">Info</option>
|
||||
<option class="bg-warning">Warning</option>
|
||||
<option class="bg-secondary">Secondary</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label>Member</label>
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="avatar m-0 mr-1">
|
||||
<img src="../../../assets/images/portrait/small/avatar-s-20.png" height="36" width="36"
|
||||
alt="avtar img holder">
|
||||
</div>
|
||||
<div class="badge-circle">
|
||||
<i class="ficon feather ft-plus"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Attachment</label>
|
||||
<div class="custom-file">
|
||||
<input type="file" class="custom-file-input" id="emailAttach">
|
||||
<label class="custom-file-label" for="emailAttach">Attach file</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Compose mail Quill editor -->
|
||||
<div class="form-group">
|
||||
<label>Comment</label>
|
||||
<div class="snow-container border rounded p-1">
|
||||
<div class="editor">
|
||||
<quill-editor calss="kanbanQuill" formControlName="description"
|
||||
[styles]="{height: '110px', border: '0px solid #ccc' }" [modules]="kanbanquillConfig"
|
||||
(onFocus)="focus()" (onBlur)="blur()" placeholder="Write a Comment... "></quill-editor>
|
||||
|
||||
</div>
|
||||
<div class="d-flex justify-content-end">
|
||||
<div class="compose-quill-toolbar ql-toolbar ql-snow kanbantoolbar">
|
||||
<span class="ql-formats mr-0">
|
||||
<button class="ql-bold">Bold</button>
|
||||
<button class="ql-italic">Italic</button>
|
||||
<button class="ql-underline">Underline</button>
|
||||
<button class="ql-link"></button>
|
||||
<button class="ql-image"></button>
|
||||
<button class="btn btn-sm btn-primary btn-comment ml-25">Comment</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer d-flex justify-content-end">
|
||||
<button type="reset" class="btn btn-danger delete-kanban-item mr-1" (click)="deleteKanban($event)">
|
||||
<i class='ficon feather ft-trash-2 mr-50'></i>
|
||||
<span>Delete</span>
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary glow update-kanban-item"
|
||||
(click)="updateKanbanItem($event)">
|
||||
<i class='ficon feather ft-play mr-50'></i>
|
||||
<span>Save</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<!-- form start end-->
|
||||
</div>
|
||||
</div>
|
||||
<!--/ User Chat profile right area -->
|
||||
<div class="kanban-container">
|
||||
<div data-id="kanban-board-1" data-order="1" class="kanban-board"
|
||||
style="width: 250px; margin-left: 15px; margin-right: 15px;" *ngFor="let kanbanList of kanbanList">
|
||||
<header class="kanban-board-header">
|
||||
<div type="text" class="kanban-title-board truncate" contenteditable="true" [innerHTML]="kanbanList.name"
|
||||
(input)="contentNew=$event.target.textContent" (click)="showSidebar($event)"
|
||||
(focusout)="validateProfile(contentNew,kanbanList)"></div>
|
||||
<button class="kanban-title-button btn btn-default btn-xs" (click)="addKanbanItem(kanbanList)">+ Add
|
||||
New Item</button>
|
||||
<div ngbDropdown>
|
||||
<i class="ficon feather ft-more-vertical" id="dropdownBasic1" ngbDropdownToggle></i>
|
||||
<div ngbDropdownMenu>
|
||||
<a class="dropdown-item" [routerLink]=""><i class="ficon feather ft-link mr-50"></i>Copy Link</a>
|
||||
<a class="dropdown-item kanban-delete" [routerLink]="" (click)="deleteKanbanList(kanbanList)"><i
|
||||
class="ficon feather ft-trash-2 mr-50"></i>Delete</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</header>
|
||||
<main class="kanban-drag">
|
||||
<div>
|
||||
<!-- <div *ngFor="let kanban of kanbanList.tickets" class="kanban"> -->
|
||||
<div>
|
||||
<div [dndList] [dndModel]="kanbanList.tickets">
|
||||
<div class="kanban-item" (click)="showSidebar($event)" (click)="editItem(kanban,kanbanList.tickets)"
|
||||
*ngFor="let kanban of kanbanList.tickets"
|
||||
[dndType]="'kanban'"
|
||||
(dndMoved)="removeItem(kanban, kanbanList)"
|
||||
[dndDraggable] [dndObject]="kanban">
|
||||
{{kanban.name}}
|
||||
<div class="kanban-image mb-1" [hidden]="!kanban.showImage"><img class="img-fluid"
|
||||
[src]="kanban.bg_image" alt="kanban-image"></div>
|
||||
<div class="kanban-footer d-flex justify-content-between mt-1">
|
||||
<div class="kanban-footer-left d-flex">
|
||||
<div class="kanban-due-date mr-50"><i
|
||||
[ngClass]="{'ficon feather ft-clock font-size-small mr-25': kanban.date}"></i><span
|
||||
class="font-size-small">{{kanban.date| date: 'MMM d' }}</span></div>
|
||||
<div class="kanban-comment mr-50"><i
|
||||
[ngClass]="{'ficon feather ft-message-square font-size-small mr-25': kanban.comment}"></i><span
|
||||
class="font-size-small">{{kanban.comment}}</span></div>
|
||||
<div class="kanban-attachment"><i
|
||||
[ngClass]="{'ficon feather ft-link font-size-small mr-25':kanban.attachment}"></i><span
|
||||
class="font-size-small">{{kanban.attachment}}</span></div>
|
||||
</div>
|
||||
<div class="kanban-footer-right">
|
||||
<div class="kanban-users">
|
||||
<ul class="list-unstyled users-list cursor-pointer m-0 d-flex align-items-center">
|
||||
<li class="avatar pull-up my-0" *ngFor="let imageUrl of kanban.image"><img
|
||||
class="media-object" [src]="imageUrl" alt="Avatar" height="18" width="18"></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer></footer>
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
<form class="itemform not-draggable" [hidden]="!kanbanList.showNewItem">
|
||||
<div class="form-group">
|
||||
<textarea class="form-control add-new-item" [(ngModel)]="addTitle" rows="2" autofocus="" required=""
|
||||
[ngModelOptions]="{standalone: true}"></textarea>
|
||||
</div>
|
||||
<div class="form-group"><button type="submit" class="btn btn-primary btn-sm mr-50"
|
||||
(click)="submitItem(kanbanList)">Submit</button><button type="button" id="CancelBtn"
|
||||
class="btn btn-sm btn-danger" (click)="cancleKanban(kanbanList)">Cancel</button></div>
|
||||
</form>
|
||||
</main>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--/ User Chat profile right area -->
|
||||
</section>
|
||||
<!--/ Sample Project kanban -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END: Content-->
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { KanbanComponent } from './kanban.component';
|
||||
|
||||
describe('KanbanComponent', () => {
|
||||
let component: KanbanComponent;
|
||||
let fixture: ComponentFixture<KanbanComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ KanbanComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(KanbanComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
365
src/app/content/applications/kanban/kanban/kanban.component.ts
Normal file
365
src/app/content/applications/kanban/kanban/kanban.component.ts
Normal file
@@ -0,0 +1,365 @@
|
||||
import { Component, Renderer2, OnInit, AfterViewInit } from "@angular/core";
|
||||
import { PerfectScrollbarConfigInterface } from "ngx-perfect-scrollbar";
|
||||
import { FormGroup, FormControl, FormBuilder } from "@angular/forms";
|
||||
import { QuillInitializeServiceService } from "../../../../_services/quill-initialize-service.service";
|
||||
import "quill-mention";
|
||||
declare var require: any;
|
||||
const data = require("../../../../../assets/data/application/kanban.json");
|
||||
|
||||
@Component({
|
||||
selector: "app-kanban",
|
||||
templateUrl: "./kanban.component.html",
|
||||
styleUrls: ["./kanban.component.css"],
|
||||
})
|
||||
export class KanbanComponent implements OnInit, AfterViewInit {
|
||||
public config: PerfectScrollbarConfigInterface = { wheelPropagation: true };
|
||||
selectKanbanClass: any;
|
||||
kanbanList: any[] = [];
|
||||
kanbanValue: any;
|
||||
selectKanbanArray: any[] = [];
|
||||
kanban: FormGroup;
|
||||
showImage: boolean;
|
||||
showNewItem: boolean;
|
||||
selectedLabel: any;
|
||||
addTitle: string;
|
||||
header: string;
|
||||
blured = false;
|
||||
focused = false;
|
||||
atValues = [
|
||||
{ id: 1, value: "Fredrik Sundqvist", link: "https://google.com" },
|
||||
{ id: 2, value: "Patrik Sjölin" },
|
||||
];
|
||||
hashValues = [
|
||||
{ id: 3, value: "Fredrik Sundqvist 2" },
|
||||
{ id: 4, value: "Patrik Sjölin 2" },
|
||||
];
|
||||
list = [
|
||||
{ id: 1, name: 'item1', children: [] },
|
||||
{ id: 2, name: 'item2', children: [] },
|
||||
{ id: 3, name: 'item3', children: [] },
|
||||
];
|
||||
|
||||
kanbanquillConfig = {
|
||||
toolbar: ".kanbantoolbar",
|
||||
autoLink: true,
|
||||
|
||||
keyboard: {
|
||||
bindings: {
|
||||
enter: {
|
||||
key: 13,
|
||||
handler: (range, context) => {
|
||||
console.log("enter");
|
||||
return true;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
constructor(
|
||||
private _renderer: Renderer2,
|
||||
private formBuilder: FormBuilder,
|
||||
private QuillInitializeServiceServicec: QuillInitializeServiceService
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.showNewItem = false;
|
||||
this.selectKanbanClass = "bg-primary";
|
||||
this.kanban = this.formBuilder.group({
|
||||
title: new FormControl(['']),
|
||||
date: new FormControl(['']),
|
||||
selectedLabel: new FormControl(['']),
|
||||
description: new FormControl([''])
|
||||
});
|
||||
this.kanbanList = JSON.parse(localStorage.getItem("kanban"));
|
||||
if (this.kanbanList == null || this.kanbanList.length == 0) {
|
||||
this.kanbanList = data;
|
||||
} else { }
|
||||
localStorage.setItem("kanban", JSON.stringify(this.kanbanList));
|
||||
}
|
||||
ngAfterViewInit(): void {
|
||||
const items = localStorage.getItem("kanban");
|
||||
if (items) {
|
||||
this.kanbanList = JSON.parse(items);
|
||||
}
|
||||
}
|
||||
|
||||
draggable = {
|
||||
// note that data is handled with JSON.stringify/JSON.parse
|
||||
// only set simple data or POJO's as methods will be lost
|
||||
data: "myDragData",
|
||||
effectAllowed: "all",
|
||||
disable: false,
|
||||
handle: false
|
||||
};
|
||||
|
||||
onDragStart(event: DragEvent) {
|
||||
|
||||
console.log("drag started", JSON.stringify(event, null, 2));
|
||||
}
|
||||
|
||||
onDragEnd(event: DragEvent) {
|
||||
|
||||
console.log("drag ended", JSON.stringify(event, null, 2));
|
||||
}
|
||||
|
||||
onDraggableCopied(event: DragEvent) {
|
||||
|
||||
console.log("draggable copied", JSON.stringify(event, null, 2));
|
||||
}
|
||||
|
||||
onDraggableLinked(event: DragEvent) {
|
||||
|
||||
console.log("draggable linked", JSON.stringify(event, null, 2));
|
||||
}
|
||||
|
||||
onDraggableMoved(event: DragEvent) {
|
||||
|
||||
console.log("draggable moved", JSON.stringify(event, null, 2));
|
||||
}
|
||||
|
||||
onDragCanceled(event: DragEvent) {
|
||||
|
||||
console.log("drag cancelled", JSON.stringify(event, null, 2));
|
||||
}
|
||||
|
||||
onDragover(event: DragEvent) {
|
||||
|
||||
console.log("dragover", JSON.stringify(event, null, 2));
|
||||
}
|
||||
|
||||
|
||||
showSidebar(event) {
|
||||
const toggleIcon = document.getElementById("kanban_sidebar");
|
||||
const toggle = document.getElementById("content-overlay");
|
||||
if (event.currentTarget.className === "kanban-item") {
|
||||
this._renderer.addClass(toggleIcon, "show");
|
||||
this._renderer.addClass(toggle, "show");
|
||||
} else if (
|
||||
event.currentTarget.className === "ficon feather ft-x" ||
|
||||
"kanban-overlay"
|
||||
) {
|
||||
this._renderer.removeClass(toggleIcon, "show");
|
||||
this._renderer.removeClass(toggle, "show");
|
||||
}
|
||||
}
|
||||
editItem(value, kanban) {
|
||||
const date1 = value.date;
|
||||
const split = date1.split('/');
|
||||
let dateObj = {
|
||||
"year": Number(split[2]),
|
||||
"month": Number([split[0]]),
|
||||
"day": Number(split[1])
|
||||
}
|
||||
this.kanban.setValue({
|
||||
title: value.name,
|
||||
date: dateObj,
|
||||
selectedLabel: value.selectedLabel,
|
||||
description: value.description,
|
||||
})
|
||||
this.kanbanValue = value
|
||||
this.selectKanbanArray = kanban
|
||||
if (value.selectedLabel == 'Primary') {
|
||||
const toggleIcon = document.getElementById('selectLable');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-sucess');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-danger');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-info');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-warning');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-secondary');
|
||||
this._renderer.addClass(toggleIcon, 'bg-primary');
|
||||
} else if (value.selectedLabel == 'Danger') {
|
||||
const toggleIcon = document.getElementById('selectLable');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-primary');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-sucess');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-info');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-warning');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-secondary');
|
||||
this._renderer.addClass(toggleIcon, 'bg-danger');
|
||||
}
|
||||
else if (value.selectedLabel == 'Success') {
|
||||
const toggleIcon = document.getElementById('selectLable');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-primary');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-danger');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-info');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-warning');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-secondary');
|
||||
this._renderer.addClass(toggleIcon, 'bg-success');
|
||||
}
|
||||
else if (value.selectedLabel == 'Info') {
|
||||
const toggleIcon = document.getElementById('selectLable');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-primary');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-danger');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-success');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-warning');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-secondary');
|
||||
this._renderer.addClass(toggleIcon, 'bg-info');
|
||||
}
|
||||
else if (value.selectedLabel == 'Warning') {
|
||||
const toggleIcon = document.getElementById('selectLable');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-primary');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-danger');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-success');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-info');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-secondary');
|
||||
this._renderer.addClass(toggleIcon, 'bg-warning');
|
||||
}
|
||||
else if (value.selectedLabel == 'Secondary') {
|
||||
const toggleIcon = document.getElementById('selectLable');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-primary');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-danger');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-success');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-warning');
|
||||
this._renderer.removeClass(toggleIcon, 'bg-info');
|
||||
this._renderer.addClass(toggleIcon, 'bg-secondary');
|
||||
}
|
||||
}
|
||||
deleteKanban(event) {
|
||||
this.kanbanValue;
|
||||
for (let i = 0; i < this.kanbanList.length; i++) {
|
||||
if (this.selectKanbanArray.length == this.kanbanList[i].tickets.length) {
|
||||
for (var j = 0; j < this.selectKanbanArray.length; j++)
|
||||
if (JSON.stringify(this.selectKanbanArray) === JSON.stringify(this.kanbanList[i].tickets)) {
|
||||
for (var k = 0; k < this.kanbanList[i].tickets.length; k++) {
|
||||
if (this.kanbanValue.name == this.kanbanList[i].tickets[k].name) {
|
||||
this.kanbanList[i].tickets.splice(k, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const toggleIcon = document.getElementById("kanban_sidebar");
|
||||
const toggle = document.getElementById("content-overlay");
|
||||
if (
|
||||
event.currentTarget.className === "btn btn-danger delete-kanban-item mr-1"
|
||||
) {
|
||||
this._renderer.removeClass(toggleIcon, "show");
|
||||
this._renderer.removeClass(toggle, "show");
|
||||
}
|
||||
}
|
||||
addKanbanBoard() {
|
||||
let defaultobject = {
|
||||
name: "Default Title",
|
||||
tickets: [],
|
||||
type: "",
|
||||
kanbanId: this.kanbanList.length + 1,
|
||||
showNewItem: false
|
||||
};
|
||||
this.kanbanList.push(defaultobject);
|
||||
}
|
||||
public kanbanArray: any;
|
||||
submitItem(kanbanArray) {
|
||||
let dateObj = new Date();
|
||||
var date = (dateObj.getMonth() + 1) + '/' + dateObj.getDate() + '/' + dateObj.getFullYear();
|
||||
let object = {
|
||||
'name': this.addTitle,
|
||||
'date': date,
|
||||
'selectedLabel': "Primary",
|
||||
'description': this.addTitle
|
||||
}
|
||||
for (let i = 0; i < this.kanbanList.length; i++) {
|
||||
if (kanbanArray.kanbanId == this.kanbanList[i].kanbanId && kanbanArray.tickets.length == this.kanbanList[i].tickets.length && JSON.stringify(kanbanArray.tickets) === JSON.stringify(this.kanbanList[i].tickets)) {
|
||||
this.kanbanList[i].tickets.push(object),
|
||||
this.kanbanList[i].showNewItem = false;
|
||||
}
|
||||
}
|
||||
this.addTitle = null;
|
||||
}
|
||||
|
||||
addKanbanItem(kanabanArray) {
|
||||
this.addTitle = null;
|
||||
for (let i = 0; i < this.kanbanList.length; i++) {
|
||||
if (kanabanArray.kanbanId == this.kanbanList[i].kanbanId) {
|
||||
this.kanbanList[i].showNewItem = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
updateKanbanItem(event) {
|
||||
let dateObj = this.kanban.value.date;
|
||||
var date = dateObj.month + '/' + dateObj.day + '/' + dateObj.year
|
||||
this.kanbanValue;
|
||||
for (let i = 0; i < this.kanbanList.length; i++) {
|
||||
if (this.selectKanbanArray.length == this.kanbanList[i].tickets.length) {
|
||||
for (
|
||||
var j = 0;
|
||||
j < this.selectKanbanArray.length;
|
||||
j++ // assert each element equal
|
||||
)
|
||||
JSON.stringify(this.selectKanbanArray) === JSON.stringify(this.kanbanList[i].kanabanArray);
|
||||
for (var k = 0; k < this.kanbanList[i].tickets.length; k++) {
|
||||
if (this.kanbanValue.name == this.kanbanList[i].tickets[k].name) {
|
||||
|
||||
(this.kanbanList[i].tickets[k].name = this.kanban.value.title),
|
||||
(this.kanbanList[i].tickets[k].date = date),
|
||||
(this.kanbanList[i].tickets[k].selectedLabel = this.kanban.value.selectedLabel),
|
||||
(this.kanbanList[i].tickets[k].description = this.kanban.value.description);
|
||||
}
|
||||
}
|
||||
this.kanbanList[i].tickets;
|
||||
}
|
||||
}
|
||||
const toggleIcon = document.getElementById("kanban_sidebar");
|
||||
const toggle = document.getElementById("content-overlay");
|
||||
if (
|
||||
event.currentTarget.className ===
|
||||
"btn btn-primary glow update-kanban-item"
|
||||
) {
|
||||
this._renderer.removeClass(toggleIcon, "show");
|
||||
this._renderer.removeClass(toggle, "show");
|
||||
}
|
||||
}
|
||||
public removeItem(kanban: any, kanbanList): void {
|
||||
for (let i = 0; i < this.kanbanList.length; i++) {
|
||||
if (kanbanList.kanbanId == this.kanbanList[i].kanbanId) {
|
||||
for (var k = 0; k < this.kanbanList[i].tickets.length; k++) {
|
||||
if (kanban.name == this.kanbanList[i].tickets[k].name) {
|
||||
kanbanList.tickets.splice(kanbanList.tickets.indexOf(kanban), 1);
|
||||
this.kanbanList[i].tickets == kanbanList.tickets;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cancleKanban(kanbanList) {
|
||||
kanbanList.showNewItem = false;
|
||||
}
|
||||
|
||||
deleteKanbanList(kanbanList) {
|
||||
for (let i = 0; i < this.kanbanList.length; i++) {
|
||||
if (JSON.stringify(kanbanList) === JSON.stringify(this.kanbanList[i])) {
|
||||
this.kanbanList.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
updateHeader(kanbanList) {
|
||||
for (let i = 0; i < this.kanbanList.length; i++) {
|
||||
if (JSON.stringify(kanbanList) === JSON.stringify(this.kanbanList[i])) {
|
||||
this.kanbanList[i].name = this.header
|
||||
}
|
||||
}
|
||||
}
|
||||
focus() {
|
||||
this.focused = true;
|
||||
this.blured = false;
|
||||
}
|
||||
blur() {
|
||||
this.focused = false;
|
||||
this.blured = true;
|
||||
}
|
||||
validateProfile(content, kanbanList) {
|
||||
this.header = content;
|
||||
console.log(content);
|
||||
setTimeout(() => {
|
||||
this.updateHeader(kanbanList);
|
||||
}, 2500);
|
||||
}
|
||||
getSelectedKanbanText(event: Event) {
|
||||
let temp = event.target['options'][event.target['options'].selectedIndex].className;
|
||||
const toggleIcon = document.getElementById('selectLable');
|
||||
this._renderer.removeClass(toggleIcon, this.selectKanbanClass);
|
||||
this._renderer.addClass(toggleIcon, temp);
|
||||
this.selectKanbanClass = temp;
|
||||
temp = null;
|
||||
}
|
||||
}
|
||||
106
src/app/content/applications/quill/quillAutolinks.ts
Normal file
106
src/app/content/applications/quill/quillAutolinks.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import Delta from 'quill-delta';
|
||||
import Autolinker from 'autolinker';
|
||||
|
||||
const defaults = {
|
||||
globalRegularExpression: /https?:\/\/[\S]+/g,
|
||||
urlRegularExpression: /(https?:\/\/[\S]+)/
|
||||
}
|
||||
|
||||
export default class QuillAutoLink {
|
||||
autolinker = new Autolinker();
|
||||
quill;
|
||||
options;
|
||||
constructor (quill, options) {
|
||||
this.quill = quill;
|
||||
options = options || {};
|
||||
this.options = {...defaults, ...options};
|
||||
this.registerTypeListener();
|
||||
this.registerPasteListener();
|
||||
}
|
||||
registerPasteListener () {
|
||||
this.quill.clipboard.addMatcher(Node.TEXT_NODE, (node, delta) => {
|
||||
if (typeof node.data !== 'string') {
|
||||
return;
|
||||
}
|
||||
const matches = node.data.match(this.options.globalRegularExpression)
|
||||
if (matches && matches.length > 0) {
|
||||
const newDelta = new Delta();
|
||||
let str = node.data;
|
||||
matches.forEach(match => {
|
||||
const split = str.split(match);
|
||||
const beforeLink = split.shift();
|
||||
newDelta.insert(beforeLink);
|
||||
newDelta.insert(match, {link: match});
|
||||
str = split.join(match);
|
||||
})
|
||||
newDelta.insert(str);
|
||||
delta.ops = newDelta.ops;
|
||||
}
|
||||
return delta;
|
||||
})
|
||||
}
|
||||
registerTypeListener () {
|
||||
this.quill.on('text-change', (delta) => {
|
||||
let ops = delta.ops
|
||||
// Only return true, if last operation includes whitespace inserts
|
||||
// Equivalent to listening for enter, tab or space
|
||||
if (!ops || ops.length < 1 || ops.length > 2) {
|
||||
return
|
||||
}
|
||||
let lastOp = ops[ops.length - 1]
|
||||
if (!lastOp.insert || typeof lastOp.insert !== 'string' || !lastOp.insert.match(/\s/)) {
|
||||
return
|
||||
}
|
||||
this.checkTextForUrl()
|
||||
})
|
||||
}
|
||||
checkTextForUrl () {
|
||||
let sel = this.quill.getSelection();
|
||||
if (!sel) {
|
||||
return;
|
||||
}
|
||||
let [leaf] = this.quill.getLeaf(sel.index);
|
||||
if (!leaf.text) {
|
||||
return;
|
||||
}
|
||||
if(leaf.parent != undefined && leaf.parent.domNode != undefined && leaf.parent.domNode.tagName.toLowerCase() == "a"){
|
||||
return;
|
||||
}
|
||||
var temp = leaf.text.substring(0,leaf.text.length - 1);
|
||||
var to_check_str = temp.substring(temp.lastIndexOf(' '));
|
||||
this.checkIfHasLink(sel.index, to_check_str);
|
||||
}
|
||||
textToUrl (index,text, url) {
|
||||
const ops = new Delta()
|
||||
.retain(index)
|
||||
.delete(text.length)
|
||||
.insert(text,{link: url});
|
||||
this.quill.updateContents(ops);
|
||||
}
|
||||
|
||||
|
||||
checkIfHasLink = (currentIndex: number, input: string) =>{
|
||||
var hasLink = false;
|
||||
var linkedText = Autolinker.link( input, {
|
||||
replaceFn : ( match ) => {
|
||||
switch(match.getType()){
|
||||
// case 'url' :
|
||||
// //console.log( "url: ", match.getUrl() );
|
||||
// var index = (currentIndex - match.matchedText.length) - 1;
|
||||
// this.textToUrl(index,match.matchedText,match.getUrl());
|
||||
// return true; // let Autolinker perform its normal anchor tag replacement
|
||||
|
||||
// case 'email' :
|
||||
// var email = match.getEmail();
|
||||
// console.log( "email: ", email );
|
||||
// return true;
|
||||
|
||||
// case 'phone' :
|
||||
// console.log( "Phone Number: ", match.getNumber() );
|
||||
}
|
||||
}
|
||||
} );
|
||||
return hasLink;
|
||||
}
|
||||
|
||||
}
|
||||
42
src/app/content/applications/todo-app/todo-app.module.ts
Normal file
42
src/app/content/applications/todo-app/todo-app.module.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule, DatePipe } from '@angular/common';
|
||||
import { TodoappComponent } from './todoapp.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { PerfectScrollbarModule, PerfectScrollbarConfigInterface } from 'ngx-perfect-scrollbar';
|
||||
import { AngularFireModule } from '@angular/fire/compat';
|
||||
import { environment } from 'src/environments/environment.prod';
|
||||
import { AngularFirestoreModule } from '@angular/fire/compat/firestore';
|
||||
import { TodoService } from 'src/app/_api/todo/todo.service';
|
||||
import { ToastrModule } from 'ngx-toastr';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { NgSelectModule } from '@ng-select/ng-select';
|
||||
import { QuillModule } from 'ngx-quill';
|
||||
import { ImagePreloadDirective } from '../../../_directives/image.preload.directive';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [TodoappComponent, ImagePreloadDirective],
|
||||
providers: [TodoService],
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
PerfectScrollbarModule,
|
||||
FormsModule,
|
||||
NgbModule,
|
||||
NgSelectModule,
|
||||
QuillModule.forRoot(),
|
||||
ToastrModule.forRoot(),
|
||||
AngularFireModule.initializeApp(environment.firebase),
|
||||
AngularFirestoreModule.enablePersistence(),
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: TodoappComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [ImagePreloadDirective]
|
||||
})
|
||||
export class TodoAppModule { }
|
||||
304
src/app/content/applications/todo-app/todoapp.component.css
Normal file
304
src/app/content/applications/todo-app/todoapp.component.css
Normal file
@@ -0,0 +1,304 @@
|
||||
:host ::ng-deep .todo-app-menu {
|
||||
width: 100% !important;
|
||||
padding: .5rem 0;
|
||||
}
|
||||
:host ::ng-deep .ml-25 {
|
||||
margin-left: .25rem!important;
|
||||
}
|
||||
:host ::ng-deep .todo-sidebar .todo-app-menu .sidebar-menu-list .filter-label {
|
||||
font-family: Quicksand,Georgia,"Times New Roman",Times,serif;
|
||||
letter-spacing: 1px;
|
||||
color: #bac0c7;
|
||||
}
|
||||
:host ::ng-deep .border {
|
||||
border: 1px solid #dde1e6 !important;
|
||||
}
|
||||
:host ::ng-deep .ql-container.ql-snow {
|
||||
border: 0px solid #ccc;
|
||||
}
|
||||
:host ::ng-deep .ql-toolbar.ql-snow {
|
||||
border: 0px solid #ccc;
|
||||
|
||||
}
|
||||
:host ::ng-deep .btn-primary {
|
||||
height: fit-content;
|
||||
margin-right: 7px;
|
||||
}
|
||||
:host ::ng-deep .new-taskDropdown::after {
|
||||
content: "" !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .show > .dropdownnew-task {
|
||||
left: -166px !important;
|
||||
}
|
||||
:host ::ng-deep .show > .dropdown-sort {
|
||||
left: -48px !important;
|
||||
}
|
||||
@media (max-width: 991.98px){
|
||||
.app-content .content-right {
|
||||
width: 100%!important;
|
||||
}
|
||||
}
|
||||
:host ::ng-deep .py-75 {
|
||||
padding-top: .75rem!important;
|
||||
}
|
||||
:host ::ng-deep .py-75 {
|
||||
padding-bottom: .75rem!important;
|
||||
}
|
||||
:host ::ng-deep .ImageUpload {
|
||||
width: 10%;
|
||||
height: 10%;
|
||||
}
|
||||
:host ::ng-deep .add-todo{
|
||||
margin-left: 10px;
|
||||
}
|
||||
:host ::ng-deep .todo-new-task-sidebar .avatar i {
|
||||
right : 18px;
|
||||
bottom : 18px;
|
||||
}
|
||||
:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items {
|
||||
width: fit-content !important;
|
||||
}
|
||||
:host ::ng-deep .ng-select {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
@media (max-width: 349.98px) {
|
||||
.sidebar .todo-sidebar {
|
||||
width : 230px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 575.98px) {
|
||||
.todo-new-task-sidebar {
|
||||
width : 88%;
|
||||
}
|
||||
}
|
||||
:host ::ng-deep .gradient-mint {
|
||||
background-image: linear-gradient(45deg,#28d094,#28d094)!important;
|
||||
width: 10px !important;
|
||||
height: 10px !important;
|
||||
}
|
||||
:host ::ng-deep .gradient-primary{
|
||||
background-image: linear-gradient(45deg,#666ee8,#666ee8)!important;
|
||||
width: 10px !important;
|
||||
height: 10px !important;
|
||||
}
|
||||
:host ::ng-deep .gradient-warning {
|
||||
background-image: linear-gradient(45deg,#ff9149,#ff9149)!important;
|
||||
width: 10px !important;
|
||||
height: 10px !important;
|
||||
}
|
||||
:host ::ng-deep .gradient-danger {
|
||||
background-image: linear-gradient(45deg,#ff4961,#ff4961)!important;
|
||||
width: 10px !important;
|
||||
height: 10px !important;
|
||||
}
|
||||
:host ::ng-deep .gradient-info {
|
||||
background-image: linear-gradient(45deg,#1e9ff2,#1e9ff2)!important;
|
||||
width: 10px !important;
|
||||
height: 10px !important;
|
||||
}
|
||||
/* date picker css */
|
||||
:host ::ng-deep .btn-light:not(:disabled):not(.disabled):active {
|
||||
color: unset !important;
|
||||
background-color: unset !important;
|
||||
border-color: #d3d9df !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .btn-light:hover:not(.disabled):active {
|
||||
background-color: #e2e6ea !important;
|
||||
border-color: #dae0e5 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .btn-light {
|
||||
color: unset !important;
|
||||
background-color: unset !important;
|
||||
border-color: unset !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .bg-primary {
|
||||
background-color: #007bff !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .text-white {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .custom-day {
|
||||
text-align: center;
|
||||
padding: .185rem .25rem;
|
||||
display: inline-block;
|
||||
height: 2rem;
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
:host ::ng-deep .custom-day:active {
|
||||
color: #6d7183 !important;
|
||||
background-color: #fff !important;
|
||||
border-block-color: rgb(2, 117, 216) !important;
|
||||
|
||||
}
|
||||
|
||||
.bg-light {
|
||||
background-color: #f8f9fa !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .hidden {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.ngb-dp-weekday {
|
||||
color: #17a2b8;
|
||||
}
|
||||
|
||||
.ngb-dp-week-number,
|
||||
.ngb-dp-weekday {
|
||||
line-height: 2rem;
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.ngb-datepicker-month-view {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 80%;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.ngb-dp-day {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
.ngb-dp-month {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.btn-light:hover {
|
||||
color: #212529 !important;
|
||||
background-color: #e2e6ea !important;
|
||||
border-color: #dae0e5 !important;
|
||||
}
|
||||
|
||||
.ngb-datepicker-month-view {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.ngb-dp-header {
|
||||
border-bottom: 0;
|
||||
border-radius: .25rem .25rem 0 0;
|
||||
padding-top: .25rem;
|
||||
}
|
||||
|
||||
.ngb-dp-day,
|
||||
.ngb-dp-week-number,
|
||||
.ngb-dp-weekday {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.custom-day {
|
||||
text-align: center;
|
||||
padding: 0.185rem 0.25rem;
|
||||
display: inline-block;
|
||||
height: 2rem;
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.custom-day.focused {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
.custom-day.range,
|
||||
.custom-day:hover {
|
||||
background-color: rgb(2, 117, 216);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.custom-day.faded {
|
||||
background-color: rgba(2, 117, 216, 0.5);
|
||||
}
|
||||
|
||||
:host ::ng-deep .block-ui-wrapper {
|
||||
background: rgba(255, 249, 249, 0.5) !important;
|
||||
}
|
||||
|
||||
.custom-day {
|
||||
text-align: center;
|
||||
padding: 0.185rem 0.25rem;
|
||||
border-radius: 0.25rem;
|
||||
display: inline-block;
|
||||
width: 2rem;
|
||||
}
|
||||
.custom-day:hover, .custom-day.focused {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
.weekend {
|
||||
background-color: #f0ad4e;
|
||||
border-radius: 1rem;
|
||||
color: white;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
:host ::ng-deep .ft-calendar{
|
||||
font-family: feather!important;
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: large;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
:host ::ng-deep .input-group-text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: unset !important;
|
||||
margin-bottom: unset !important;
|
||||
font-size: unset !important;
|
||||
font-weight: unset !important;
|
||||
line-height: unset !important;
|
||||
color:unset !important;
|
||||
text-align: unset !important;
|
||||
white-space: unset !important;
|
||||
background-color: unset !important;
|
||||
border: unset !important;
|
||||
border-radius: unset !important;
|
||||
}
|
||||
.ml-75, .mx-75 {
|
||||
margin-left: .75rem!important;
|
||||
}
|
||||
.mx-50 {
|
||||
margin-left: .5rem!important;
|
||||
}
|
||||
.sidebar {
|
||||
width : 270px !important;
|
||||
}
|
||||
.align-middle {
|
||||
margin-left: 3px;
|
||||
}
|
||||
.mr-50, .mx-50 {
|
||||
margin-right: .5rem!important;
|
||||
}
|
||||
:host ::ng-deep .ft-plus{
|
||||
margin-right: 3px !important;
|
||||
}
|
||||
control:disabled, .form-control[readonly] {
|
||||
background-color: #ffffff;
|
||||
margin-left: -12px;
|
||||
}
|
||||
:host ::ng-deep .ngb-dp-header {
|
||||
background-color: var(--light) !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngb-dp-weekdays {
|
||||
background-color: var(--light);
|
||||
}
|
||||
|
||||
:host ::ng-deep .ngb-dp-month-name {
|
||||
background-color: var(--light);
|
||||
}
|
||||
318
src/app/content/applications/todo-app/todoapp.component.html
Normal file
318
src/app/content/applications/todo-app/todoapp.component.html
Normal file
@@ -0,0 +1,318 @@
|
||||
<div class="app-content content">
|
||||
<div class="sidebar-left" id="sidebar-left">
|
||||
<div class="sidebar">
|
||||
<div class="todo-sidebar d-flex">
|
||||
<span class="sidebar-close-icon" (click)="sidebar($event)">
|
||||
<i class="ficon feather ft-x"></i>
|
||||
</span>
|
||||
<!-- todo app menu -->
|
||||
<div class="todo-app-menu">
|
||||
<div class="form-group text-center add-task">
|
||||
<!-- new task button -->
|
||||
<button type="button" class="btn btn-danger btn-glow add-task-btn btn-block my-1"
|
||||
(click)="sidebartask($event)" (click)="open()">
|
||||
<i class="ficon feather ft-plus"></i>
|
||||
<span>New Task</span>
|
||||
</button>
|
||||
</div>
|
||||
<!-- sidebar list start -->
|
||||
<div class="sidebar-menu-list" fxFlex="auto" [perfectScrollbar]="config">
|
||||
<div class="list-group">
|
||||
<a href="#" class="list-group-item border-0 ">
|
||||
<span class="fonticon-wrap mr-50">
|
||||
<i class="ficon feather ft-align-justify"></i>
|
||||
</span>
|
||||
<span> All</span>
|
||||
</a>
|
||||
</div>
|
||||
<label class="filter-label mt-2 mb-1 pt-25">Filters</label>
|
||||
<div class="list-group" *ngFor="let todo of todoFilterList">
|
||||
<a [routerLink]="" class="list-group-item border-0" (click)="showTodoMenu(todo.Id, todoFilterList)"
|
||||
[ngClass]="{'active':todo.isSelected === true, '':todo.isSelected === false}">
|
||||
<span class="fonticon-wrap mr-50">
|
||||
<i class="{{todo.lableIcon}}"></i>
|
||||
</span>
|
||||
<span>{{todo.lableName}}</span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<label class="filter-label mt-2 mb-1 pt-25">Labels</label>
|
||||
<div class="list-group" *ngFor="let todo of todoLableList">
|
||||
<a [routerLink]="" class="list-group-item border-0 d-flex align-items-center justify-content-between"
|
||||
(click)="showTodoMenu(todo.Id, todoLableList)"
|
||||
[ngClass]="{'active':todo.isSelected === true, '':todo.isSelected === false}">
|
||||
<span>{{todo.lableName}}</span>
|
||||
<span class="{{todo.bulletClass}} d-inline-block rounded-circle "></span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- sidebar list end -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- todo new task sidebar -->
|
||||
<div class="todo-new-task-sidebar" id="todo-new-task" fxFlex="auto" [perfectScrollbar]="config">
|
||||
<div class="card shadow-none p-0 m-0">
|
||||
<div class="card-header border-bottom py-75">
|
||||
<div class="task-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="new-task-title mb-0" *ngIf="todoId === null">New Task</h5>
|
||||
<button class="mark-complete-btn btn btn-primary btn-sm" *ngIf="todoId !== null">
|
||||
<i class="ficon feather ft-check align-middle"></i>
|
||||
<span class="mark-complete align-middle">Mark Complete</span>
|
||||
</button>
|
||||
<span class="dropdown mr-1">
|
||||
<i class='ficon feather ft-paperclip cursor-pointer mr-50'></i>
|
||||
|
||||
<span ngbDropdown [open]="false" [autoClose]="true" class="d-inline-block">
|
||||
<a class="dropdown-toggle new-taskDropdown" id="folder" data-toggle="dropdown" aria-haspopup="true"
|
||||
aria-expanded="false" id="dropdownMenuButton" dropdown-menu dropdown-menu-right show
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" role="menu" ngbDropdownToggle>
|
||||
<i class='ficon feather ft-more-vertical'></i>
|
||||
|
||||
</a>
|
||||
<div ngbDropdownMenu="dropdownMenuButton" class="dropdown-menu dropdown-menu-right dropdownnew-task">
|
||||
<a class="dropdown-item" [routerLink]="">Add to another project</a>
|
||||
<a class="dropdown-item" [routerLink]="">Create follow up task</a>
|
||||
<a class="dropdown-item" [routerLink]="">Print</a>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
</div>
|
||||
<button type="button" class="close close-icon" (click)="sidebartask($event)">
|
||||
<i class="ficon feather ft-x"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- form start -->
|
||||
<form [formGroup]="todo" id="compose-form" class="mt-1" (ngSubmit)="onSubmit($event)">
|
||||
<div class="card-content">
|
||||
<div class="card-body py-0 border-bottom">
|
||||
<div class="form-group">
|
||||
<!-- text area for task title -->
|
||||
<textarea formControlName="title" name="title" class="form-control task-title" cols="1" rows="2"
|
||||
placeholder="Write a Task Name" required>
|
||||
</textarea>
|
||||
</div>
|
||||
<!-- Modal -->
|
||||
|
||||
<div class="assigned d-flex justify-content-between">
|
||||
<div class="form-group d-flex align-items-center mr-1">
|
||||
|
||||
<div class="avatar avatar-image">
|
||||
|
||||
<img *ngIf="todoId === null"
|
||||
[src]="selectedUserImage?selectedUserImage:'../../../../assets/images/portrait/small/default.png'"
|
||||
class="avatar-user-image " id="avatar-user" alt="#" width="38" height="38">
|
||||
<img *ngIf="todoId !== null"
|
||||
[src]="selectedAssignee?selectedAssignee.image:'../../../../assets/images/portrait/small/default.png'"
|
||||
class="avatar-user-image " id="avatar-user" alt="#" width="38" height="38">
|
||||
<div class="avatar-content d-none" id="avatar-content">
|
||||
<i class='ficon feather ft-user font-medium-4'></i>
|
||||
</div>
|
||||
</div>
|
||||
<!-- select2 for user name -->
|
||||
<div class="select-box mr-1">
|
||||
<ng-select [items]="contact" bindLabel="name" formControlName="assignedTo"
|
||||
[(ngModel)]="selectedAssignee" (change)="getSelectedTODOTypeImage($event)">
|
||||
</ng-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group d-flex align-items-center position-relative">
|
||||
<!-- date picker -->
|
||||
<div class="input-group">
|
||||
|
||||
<div class="input-group-text mr-50" (click)="d2.toggle()">
|
||||
<i class="ficon feather ft-calendar" style="cursor: pointer;"></i>
|
||||
</div>
|
||||
|
||||
<input class="form-control" placeholder="yyyy-mm-dd" formControlName="assignDate"
|
||||
name="assignDate" ngbDatepicker #d2="ngbDatepicker">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body border-bottom task-description">
|
||||
<!-- Quill editor for task description -->
|
||||
<div class="snow-container border rounded p-50">
|
||||
<div class="compose-editor mx-75 ql-container ql-snow"></div>
|
||||
<quill-editor [styles]="{height: '90px'}" [modules]="newTodoquillConfig" (onFocus)="focus()"
|
||||
(onBlur)="blur()" formControlName="description"></quill-editor>
|
||||
|
||||
</div>
|
||||
<div class="tag d-flex justify-content-between align-items-center pt-1">
|
||||
<div class="flex-grow-1 d-flex align-items-center">
|
||||
<i class="ficon feather ft-tag align-middle mr-25"></i>
|
||||
<select class="custom-select form-control" id="todo-select" placeholder="Select Tag"
|
||||
formControlName="type" name="type" (change)="getSelectedTODOTypeText($event)">
|
||||
<option value="" selected>Select Tag</option>
|
||||
<option value="warning">Project</option>
|
||||
<option value="secondary">Product</option>
|
||||
<option value="primary">Bug</option>
|
||||
<option value="success">API</option>
|
||||
<option value="danger">UI</option>
|
||||
</select>
|
||||
<!-- <ng-select [items]="multipleSelectArray" [multiple]="true" bindLabel="item_text"
|
||||
formControlName="type" name="type" (change)="getSelectedTODOTypeText($event)">
|
||||
</ng-select> -->
|
||||
</div>
|
||||
<div class="ml-25">
|
||||
<i class="ficon feather ft-plus-circle cursor-pointer add-tags"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pb-1">
|
||||
<div class="d-flex align-items-center mb-1">
|
||||
<div class="avatar mr-75">
|
||||
<img *ngIf="!selectedItem && loggedInUser.photoURL" src="{{currentUserImage}}" width="38"
|
||||
height="38">
|
||||
<img *ngIf="selectedItem && selectedItem.creator && selectedItem.creator.image"
|
||||
src="{{selectedItem.creator.image}}" width="38" height="38">
|
||||
<img *ngIf="(!selectedItem && !loggedInUser.photoURL) || (selectedItem && !selectedItem.creator)"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-19.png" width="38" height="38">
|
||||
</div>
|
||||
<div *ngIf="!selectedItem && currentUserName" class="avatar-content">
|
||||
{{currentUserName}} creating this task
|
||||
</div>
|
||||
<div *ngIf="selectedItem && selectedItem.creator" class="avatar-content">
|
||||
{{selectedItem.creator.name}} created this task
|
||||
</div>
|
||||
<div *ngIf="!currentUserName && (!selectedItem || !selectedItem.creator)" class="avatar-content">
|
||||
John Doe creating this task
|
||||
</div>
|
||||
</div>
|
||||
<h4 style="font-family:bold;">Comments:</h4>
|
||||
<div class="d-flex align-items-center mb-1" *ngFor="let todo of todoComments">
|
||||
<div class="avatar avatar-image">
|
||||
<img [src]="todo.userid?todo.userid:'../../../../assets/images/portrait/small/default.png'"
|
||||
class="avatar-user-image " id="avatar-user" alt="#" width="38" height="38">
|
||||
</div>
|
||||
<div class="avatar-content">
|
||||
{{todo.comment}}
|
||||
</div>
|
||||
<small class="ml-75 text-muted">{{todo.created_at_date | date: 'dd/MMM HH:mm'}}</small>
|
||||
</div>
|
||||
<!-- quill editor for comment -->
|
||||
<div class="snow-container border rounded p-50 ">
|
||||
<div class="comment-editor mx-75 ql-container ql-snow"></div>
|
||||
|
||||
<div class="editor">
|
||||
<quill-editor [styles]="{height: '90px'}" #quill="ngModel" [modules]="TodoquillConfig"
|
||||
(onFocus)="focus()" (onBlur)="blur()" [(ngModel)]="todoCommentsField"
|
||||
[ngModelOptions]="{standalone: true}"></quill-editor>
|
||||
|
||||
</div>
|
||||
<div class="d-flex justify-content-end">
|
||||
<button type="button" *ngIf="todoId !== null" class="btn btn-sm btn-primary comment-btn"
|
||||
(click)="submitComment(selectedItem.id, todoCommentsField)">
|
||||
<span>Comment</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-1 d-flex justify-content-end">
|
||||
<button type="submit" class="btn btn-danger add-todo" *ngIf="todoId === null">Add Task</button>
|
||||
<button type="button" class="btn btn-danger update-todo"
|
||||
(click)="onUpdate(selectedItem.id, todo.value, $event)" *ngIf="todoId !== null">Save
|
||||
Changes</button>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<!-- form start end-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-right">
|
||||
<div class="content-overlay"></div>
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row">
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<div class="app-content-overlay" id="content-overlay" (click)="sidebartask($event)"></div>
|
||||
<div class="todo-app-area">
|
||||
<div class="todo-app-list-wrapper">
|
||||
<div class="todo-app-list">
|
||||
<div class="todo-fixed-search d-flex justify-content-between align-items-center">
|
||||
<div class="sidebar-toggle d-block d-lg-none" (click)="sidebar($event)">
|
||||
<i class="ficon feather ft-align-justify"></i>
|
||||
</div>
|
||||
<fieldset class="form-group position-relative has-icon-left m-0 flex-grow-1 pl-2">
|
||||
<input type="text" class="form-control todo-search" id="todo-search" (keyup)="search($event)"
|
||||
placeholder="Search Task">
|
||||
<div class="form-control-position">
|
||||
<i class="ficon feather ft-search"></i>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="todo-sort dropdown mr-1">
|
||||
<div ngbDropdown [open]="false" [autoClose]="true" class="d-inline-block">
|
||||
<button type="button" class="btn dropdown-toggle sorting" id="folder" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false" id="dropdownMenuButton" dropdown-menu
|
||||
dropdown-menu-right show data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
|
||||
role="menu" ngbDropdownToggle>
|
||||
<i class="ficon feather ft-filter"></i>
|
||||
<span>Sort</span>
|
||||
</button>
|
||||
<div ngbDropdownMenu="dropdownMenuButton" class="dropdown-menu dropdown-menu-right dropdown-sort">
|
||||
<a class="dropdown-item" [routerLink]="">Ascending</a>
|
||||
<a class="dropdown-item" [routerLink]="">Descending</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="todo-task-list list-group" [perfectScrollbar]="config">
|
||||
<!-- task list start -->
|
||||
<ul class="todo-task-list-wrapper list-unstyled" id="todo-task-list-drag"
|
||||
*ngFor="let item of todos let i = index">
|
||||
<li class="todo-item " [checked]="item.completed" [ngClass]="{'completed': item.completed}"
|
||||
(click)="sidebartask($event)" (click)="editModal(item,$event)">
|
||||
<div
|
||||
class="todo-title-wrapper d-flex justify-content-sm-between justify-content-end align-items-center">
|
||||
<div class="todo-title-area d-flex">
|
||||
<i class='ficon feather ft-more-vertical handle'></i>
|
||||
<div class="custom-control custom-checkbox" (click)="$event.stopPropagation();">
|
||||
<input type="checkbox" [checked]="item.completed" (change)="completeTODO(item, $event)"
|
||||
class="custom-control-input" id="checkbox{{i}}">
|
||||
<label class="custom-control-label" for="checkbox{{i}}"></label>
|
||||
</div>
|
||||
<p class="todo-title mx-50 m-0 truncate">{{item.title}}</p>
|
||||
</div>
|
||||
<div class="todo-item-action d-flex align-items-center">
|
||||
<div class="todo-badge-wrapper d-flex">
|
||||
<span class="badge badge-{{item.type}} badge-pill">{{item.badge}}</span>
|
||||
</div>
|
||||
<div class="avatar ml-1" *ngIf="item.assignedTo">
|
||||
<img src="{{item.assignedTo.image}}"
|
||||
default="../../../../assets/images/portrait/small/default.png" alt="avatar" height="30"
|
||||
width="30">
|
||||
</div>
|
||||
<a class='todo-item-favorite ml-75' [attr.id]="'todo-icon' + item.id"
|
||||
(click)="todoFavorite($event,item.id)" (click)="$event.stopPropagation();"><i
|
||||
class="ficon feather ft-star"></i></a>
|
||||
<a class='todo-item-delete ml-75' (click)="onDelete(item.id)"
|
||||
(click)="$event.stopPropagation();"><i class="ficon feather ft-trash-2"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<!-- task list end -->
|
||||
<div class="no-results">
|
||||
<h5>No Items Found</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END: Content-->
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { TodoappComponent } from './todoapp.component';
|
||||
|
||||
describe('TodoappComponent', () => {
|
||||
let component: TodoappComponent;
|
||||
let fixture: ComponentFixture<TodoappComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ TodoappComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(TodoappComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
765
src/app/content/applications/todo-app/todoapp.component.ts
Normal file
765
src/app/content/applications/todo-app/todoapp.component.ts
Normal file
@@ -0,0 +1,765 @@
|
||||
import { Component, OnInit, Renderer2, ViewChild } from '@angular/core';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { NgbDateStruct, NgbTimeStruct, NgbDate } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { PerfectScrollbarConfigInterface, PerfectScrollbarComponent, PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
|
||||
import { TodoService } from '../../../_api/todo/todo.service';
|
||||
import { AngularFirestore } from '@angular/fire/compat/firestore';
|
||||
import { NgForm, FormGroup, FormControl, FormBuilder, Validators, FormArray } from '@angular/forms';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { forkJoin } from 'rxjs';
|
||||
import { QuillEditorComponent } from 'ngx-quill';
|
||||
import { UserService } from '../../../_api/user/user.service';
|
||||
import { QuillInitializeServiceService } from '../../../_services/quill-initialize-service.service';
|
||||
import 'quill-mention';
|
||||
declare let require: any;
|
||||
|
||||
class TodoFilter {
|
||||
constructor(
|
||||
public Id: string,
|
||||
public lableName: string,
|
||||
public isSelected: boolean
|
||||
) { }
|
||||
}
|
||||
class Comment {
|
||||
public userid: string;
|
||||
public comment: string;
|
||||
public created_at_date: number;
|
||||
}
|
||||
@Component({
|
||||
selector: 'app-todoapp',
|
||||
templateUrl: './todoapp.component.html',
|
||||
styleUrls: ['./todoapp.component.css']
|
||||
})
|
||||
export class TodoappComponent implements OnInit {
|
||||
|
||||
initialData = require('../../../../assets/data/application/todo.json');
|
||||
LableData = require('../../../../assets/data/application/todo_lable.json');
|
||||
private demoUserEmail = 'john@pixinvent.com';
|
||||
todo: FormGroup;
|
||||
submitted = false;
|
||||
commentList: Comment[] = [];
|
||||
date: any;
|
||||
todoDisplayList: any[] = [];
|
||||
todoLableList: any[] = [];
|
||||
todoFilterList: TodoFilter[] = [];
|
||||
todoId: any;
|
||||
todoType: 'secondary';
|
||||
assignedTo: any;
|
||||
selectedUserId = '';
|
||||
selectedUserImage: any;
|
||||
selectedAssignee: any;
|
||||
assignDate: any;
|
||||
todoComments: any[] = [];
|
||||
todoCommentsField: string;
|
||||
selectedTodoTypeText = '';
|
||||
selectedTodoTypeValue = '';
|
||||
isShown = true;
|
||||
selectedItem: any;
|
||||
completedTodo = false;
|
||||
TodoId: any;
|
||||
id: any;
|
||||
temp: any;
|
||||
todosAssigned: any;
|
||||
loader = true;
|
||||
blured = false;
|
||||
focused = false;
|
||||
hide = false;
|
||||
hasFocus = false;
|
||||
d2: any;
|
||||
model: NgbDateStruct;
|
||||
createdDate: any;
|
||||
contact: any;
|
||||
commentArray: any[] = [];
|
||||
public isShowCropper = false;
|
||||
loggedInUser = JSON.parse(localStorage.getItem('currentUser'));
|
||||
demoUserImage = '../../../assets/images/portrait/small/avatar-s-19.png';
|
||||
currentUserImage = this.loggedInUser.photoURL;
|
||||
currentUserName = this.loggedInUser.name;
|
||||
public config: PerfectScrollbarConfigInterface = {};
|
||||
@ViewChild(PerfectScrollbarComponent) componentRef?: PerfectScrollbarComponent;
|
||||
@ViewChild(PerfectScrollbarDirective, { static: true }) directiveRef?: PerfectScrollbarDirective;
|
||||
@ViewChild('editor', { static: true }) editor: QuillEditorComponent;
|
||||
todos: any;
|
||||
atValues = [
|
||||
{ id: 1, value: 'Fredrik Sundqvist', link: 'https://google.com' },
|
||||
{ id: 2, value: 'Patrik Sjölin' }
|
||||
];
|
||||
hashValues = [
|
||||
{ id: 3, value: 'Fredrik Sundqvist 2' },
|
||||
{ id: 4, value: 'Patrik Sjölin 2' }
|
||||
];
|
||||
newTodoquillConfig = {
|
||||
toolbar: {
|
||||
container: [
|
||||
['bold', 'italic', 'underline', 'strike', 'image'],
|
||||
]
|
||||
},
|
||||
autoLink: true,
|
||||
mention: {
|
||||
allowedChars: /^[A-Za-z\sÅÄÖåäö]*$/,
|
||||
mentionDenotationChars: ['@', '#'],
|
||||
source: (searchTerm, renderList, mentionChar) => {
|
||||
let values;
|
||||
|
||||
if (mentionChar === '@') {
|
||||
values = this.atValues;
|
||||
} else {
|
||||
values = this.hashValues;
|
||||
}
|
||||
if (searchTerm.length === 0) {
|
||||
renderList(values, searchTerm);
|
||||
} else {
|
||||
const matches = [];
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
if (values[i].value.toLowerCase().indexOf(searchTerm.toLowerCase())) {
|
||||
matches.push(values[i]);
|
||||
renderList(matches, searchTerm);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
keyboard: {
|
||||
bindings: {
|
||||
enter: {
|
||||
key: 13,
|
||||
handler: (range, context) => {
|
||||
console.log('enter');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
TodoquillConfig = {
|
||||
toolbar: {
|
||||
container: [
|
||||
['bold', 'italic', 'underline', 'strike'],
|
||||
]
|
||||
},
|
||||
autoLink: true,
|
||||
// mention: {
|
||||
// allowedChars: /^[A-Za-z\sÅÄÖåäö]*$/,
|
||||
// mentionDenotationChars: ['@', '#'],
|
||||
// source: (searchTerm: string, renderList: (arg0: any[], arg1: any) => void, mentionChar: string) => {
|
||||
// let values;
|
||||
|
||||
// if (mentionChar === '@') {
|
||||
// values = this.atValues;
|
||||
// } else {
|
||||
// values = this.hashValues;
|
||||
// }
|
||||
// if (searchTerm.length === 0) {
|
||||
// renderList(values, searchTerm);
|
||||
// } else {
|
||||
// const matches = [];
|
||||
// for (let i = 0; i < values.length; i++) {
|
||||
// if (values[i].value.toLowerCase().indexOf(searchTerm.toLowerCase())) {
|
||||
// matches.push(values[i]);
|
||||
// renderList(matches, searchTerm);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// },
|
||||
keyboard: {
|
||||
bindings: {
|
||||
enter: {
|
||||
key: 13,
|
||||
handler: (range, context) => {
|
||||
console.log('enter');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
get TodoFormGroup() {
|
||||
return this.todo.get('todoComments') as FormArray;
|
||||
}
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param NgbModal modal
|
||||
* @param FormBuilder formBuilder
|
||||
* @param Renderer2 _renderer
|
||||
* @param TodoService firebaseService
|
||||
* @param AngularFirestore firestore
|
||||
* @param ToastrService toastr
|
||||
*/
|
||||
constructor(private modal: NgbModal,
|
||||
private formBuilder: FormBuilder,
|
||||
private _renderer: Renderer2,
|
||||
private firebaseService: TodoService,
|
||||
private firestore: AngularFirestore,
|
||||
private toastr: ToastrService,
|
||||
private modalService: NgbModal,
|
||||
private userService: UserService,
|
||||
private QuillInitializeServiceServicec: QuillInitializeServiceService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* OnInit
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.loader = true;
|
||||
this.resetForm();
|
||||
this.todos = [];
|
||||
this.currentUserImage = this.loggedInUser.photoURL;
|
||||
this.currentUserName = this.loggedInUser.displayName;
|
||||
this.todoLableList = this.LableData.todoLableList;
|
||||
this.todoFilterList = this.LableData.todoFilterList;
|
||||
this.userService.getUsers().subscribe(users => {
|
||||
let contactList = users.map(item => {
|
||||
return {
|
||||
...item.payload.doc.data() as {},
|
||||
id: item.payload.doc['id']
|
||||
};
|
||||
});
|
||||
contactList = contactList.filter(element => {
|
||||
return this.loggedInUser.uid !== element['uid'] || this.loggedInUser.uid === element['uid'];
|
||||
});
|
||||
this.contact = contactList;
|
||||
});
|
||||
if (this.loggedInUser.email === this.demoUserEmail) {
|
||||
// To load default todo for demo account
|
||||
this.getDemoAccTodos().then(todos => {
|
||||
if (todos.length === 0) {
|
||||
this.addDemoAccountTodos().then(result => {
|
||||
if (result) {
|
||||
this.loadTodos();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.loadTodos();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.loadTodos();
|
||||
}
|
||||
|
||||
this.todo = this.formBuilder.group({
|
||||
title: new FormControl(['', Validators.required]),
|
||||
type: new FormControl(''),
|
||||
description: new FormControl(''),
|
||||
createdDate: new FormControl(''),
|
||||
assignedTo: new FormControl(''),
|
||||
assignDate: new FormControl(['', Validators.nullValidator]),
|
||||
todoComments: this.formBuilder.array([
|
||||
this.formBuilder.group({
|
||||
comment: '',
|
||||
created_at_date: '',
|
||||
userid: ''
|
||||
})]),
|
||||
});
|
||||
}
|
||||
|
||||
// Load TODO of user
|
||||
loadTodos() {
|
||||
this.firebaseService.getTODOS(this.loggedInUser.uid).subscribe(todos => {
|
||||
let todo = [];
|
||||
todo = todos.map(item => {
|
||||
return {
|
||||
...item.payload.doc.data() as {},
|
||||
id: item.payload.doc['id']
|
||||
};
|
||||
});
|
||||
this.firebaseService.getAssignedTODOS(this.loggedInUser.uid).subscribe(assignedTodos => {
|
||||
let todoAssigned = [];
|
||||
todoAssigned = assignedTodos.map(item => {
|
||||
const toDoObj = item.payload.doc.data() as {};
|
||||
if (toDoObj && toDoObj['uid'] !== this.loggedInUser.uid) {
|
||||
return {
|
||||
...item.payload.doc.data() as {},
|
||||
id: item.payload.doc['id']
|
||||
};
|
||||
}
|
||||
});
|
||||
todoAssigned = todoAssigned.filter(item => {
|
||||
return item && item['uid'];
|
||||
});
|
||||
this.todos = todo.concat(todoAssigned);
|
||||
this.temp = this.todos;
|
||||
this.loader = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Get the add todo Form value
|
||||
*/
|
||||
get add() {
|
||||
return this.todo.controls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the update todo Form value
|
||||
*/
|
||||
get update() {
|
||||
return this.todo.controls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset form value
|
||||
*
|
||||
* @param form Form fields with previous value
|
||||
*/
|
||||
resetForm(form?: NgForm) {
|
||||
if (form != null) {
|
||||
form.resetForm();
|
||||
}
|
||||
}
|
||||
addDemoAccountTodos() {
|
||||
const dataPromise = new Promise((resolve, reject) => {
|
||||
const promises = [];
|
||||
// Add default TODO for demo account
|
||||
for (let i = 0; i < this.initialData.length; i++) {
|
||||
const promise = this.firestore.collection('todo').add({
|
||||
title: this.initialData[i].title,
|
||||
description: this.initialData[i].description,
|
||||
badge: this.initialData[i].badge,
|
||||
type: this.initialData[i].type,
|
||||
completed: this.initialData[i].completed,
|
||||
isDeleted: this.initialData[i].isDeleted,
|
||||
createdDate: new Date(),
|
||||
uid: this.loggedInUser.uid,
|
||||
assignedTo: this.initialData[i].assignedTo,
|
||||
assignDate: this.initialData[i].assignDate,
|
||||
todoComments: this.initialData[i].todoComments
|
||||
});
|
||||
promises.push(promise);
|
||||
}
|
||||
forkJoin(promises).subscribe(results => {
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
return dataPromise;
|
||||
}
|
||||
/**
|
||||
* Initial todo display
|
||||
*/
|
||||
getDemoAccTodos(): Promise<any> {
|
||||
const dataPromise = new Promise((resolve, reject) => {
|
||||
this.firebaseService.getTODOS(this.loggedInUser.uid).subscribe(todos => {
|
||||
resolve(todos);
|
||||
});
|
||||
});
|
||||
return dataPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new todo
|
||||
*
|
||||
* Update todo
|
||||
*
|
||||
* @param value Form field values
|
||||
* @param id todo id
|
||||
*/
|
||||
onSubmit(event) {
|
||||
this.submitted = true;
|
||||
let temp: any[] = [];
|
||||
this.todo.controls.assignDate.clearValidators();
|
||||
this.todo.get('assignDate').clearValidators();
|
||||
this.todo.get('assignDate').updateValueAndValidity();
|
||||
|
||||
if (this.assignedTo) {
|
||||
this.selectedAssignee = this.assignedTo;
|
||||
}
|
||||
if (this.todoCommentsField == null) {
|
||||
temp = null;
|
||||
} else if (this.todoCommentsField !== null) {
|
||||
this.todoCommentsField = this.todoCommentsField.replace(/(<p>|<\/p>)/g, '');
|
||||
temp = [{
|
||||
comment: this.todoCommentsField,
|
||||
created_at_date: Date.now(),
|
||||
userid: this.currentUserImage
|
||||
}];
|
||||
}
|
||||
if (this.todo.invalid) {
|
||||
return;
|
||||
} else if (this.todo.valid) {
|
||||
this.todo.setValue({
|
||||
uid: this.loggedInUser.uid,
|
||||
title: this.todo.value.title,
|
||||
description: this.todo.value.description,
|
||||
type: this.selectedTodoTypeValue,
|
||||
completed: false,
|
||||
isDeleted: false,
|
||||
createdDate: new Date(),
|
||||
badge: this.selectedTodoTypeText,
|
||||
assignedTo: this.todo.value.assignedTo,
|
||||
assignDate: this.todo.value.assignDate,
|
||||
todoComments: temp,
|
||||
});
|
||||
this.firebaseService.createTodo(this.todo.value).subscribe(res => {
|
||||
this.toastr.success('Added', 'Todo Created Successfully.', { timeOut: 500, closeButton: true });
|
||||
}, (err) => {
|
||||
this.toastr.error('Error', 'Add Todo Error.', { timeOut: 500, closeButton: true });
|
||||
});
|
||||
const toggleIcon = document.getElementById('todo-new-task');
|
||||
const toggle = document.getElementById('content-overlay');
|
||||
if (event.currentTarget.className === 'mt-1 ng-dirty ng-valid ng-touched' || 'mt-1 ng-dirty ng-touched ng-valid') {
|
||||
this._renderer.removeClass(toggleIcon, 'show');
|
||||
this._renderer.removeClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Submit Comment
|
||||
*/
|
||||
submitComment(id, comments) {
|
||||
if (comments != null) {
|
||||
comments = comments.replace(/(<p>|<\/p>)/g, '');
|
||||
}
|
||||
if (!comments) {
|
||||
comments = null;
|
||||
}
|
||||
if (this.loggedInUser.email === this.demoUserEmail) {
|
||||
this.currentUserImage = this.demoUserImage;
|
||||
}
|
||||
if (!this.todoComments || this.todoComments.length === 0) {
|
||||
this.todoComments = [];
|
||||
}
|
||||
// TODO Add todo comment from parameters to todoComments first
|
||||
if (comments != null) {
|
||||
this.todoComments.push({
|
||||
comment: comments,
|
||||
created_at_date: Date.now(),
|
||||
userid: this.currentUserImage
|
||||
});
|
||||
}
|
||||
if (this.todoId !== null) {
|
||||
this.todo.setValue({
|
||||
uid: this.todo.value.uid,
|
||||
title: this.todo.value.title,
|
||||
description: this.todo.value.description,
|
||||
type: this.todo.value.type,
|
||||
completed: false,
|
||||
isDeleted: false,
|
||||
createdDate: this.todo.value.createdDate,
|
||||
badge: this.todo.value.badge,
|
||||
assignedTo: this.todo.value.assignedTo,
|
||||
assignDate: this.todo.value.assignDate,
|
||||
todoComments: this.todoComments,
|
||||
});
|
||||
|
||||
this.todoCommentsField = null;
|
||||
comments = null;
|
||||
this.firebaseService.updateTODO(id, this.todo.value)
|
||||
.subscribe(res => {
|
||||
this.toastr.success('Update', 'Todo Comment Updated Successfully.', { timeOut: 500, closeButton: true });
|
||||
}, (err) => {
|
||||
this.toastr.error('Error', 'Todo Comment Updated Error', { timeOut: 500, closeButton: true });
|
||||
});
|
||||
console.log(this.todo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update todo
|
||||
*
|
||||
* @param value Form field values
|
||||
* @param id todo id
|
||||
*/
|
||||
onUpdate(id, value, event) {
|
||||
this.submitted = true;
|
||||
this.todo.controls.assignDate.clearValidators();
|
||||
this.todo.get('assignDate').clearValidators();
|
||||
this.todo.get('assignDate').updateValueAndValidity();
|
||||
if (this.todo.invalid) {
|
||||
return;
|
||||
} else if (this.todo.valid) {
|
||||
this.todo.setValue({
|
||||
uid: this.loggedInUser.uid,
|
||||
title: value.title,
|
||||
description: value.description,
|
||||
type: this.selectedTodoTypeValue,
|
||||
completed: value.completed,
|
||||
isDeleted: false,
|
||||
createdDate: this.selectedItem.createdDate,
|
||||
badge: this.selectedTodoTypeText,
|
||||
assignedTo: value.assignedTo,
|
||||
assignDate: value.assignDate,
|
||||
todoComments: this.todoComments
|
||||
});
|
||||
this.firebaseService.updateTODO(id, this.todo.value)
|
||||
.subscribe(res => {
|
||||
this.toastr.success('Update', 'Todo Updated Successfully.', { timeOut: 500, closeButton: true });
|
||||
}, (err) => {
|
||||
this.toastr.error('Error', 'Todo Update Error!', { timeOut: 500, closeButton: true });
|
||||
});
|
||||
const toggleIcon = document.getElementById('todo-new-task');
|
||||
const toggle = document.getElementById('content-overlay');
|
||||
if (event.currentTarget.className === 'btn btn-danger update-todo ng-star-inserted' || 'btn btn-danger update-todo') {
|
||||
this._renderer.removeClass(toggleIcon, 'show');
|
||||
this._renderer.removeClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Delete todo
|
||||
*
|
||||
* @param id todo id
|
||||
*/
|
||||
onDelete(id: string) {
|
||||
|
||||
this.firebaseService.deleteTodo(id)
|
||||
.then(res => {
|
||||
this.toastr.success('Deleted', 'Todo Deleted Successfully!', { timeOut: 500, closeButton: true });
|
||||
}, (err) => {
|
||||
this.toastr.error('Error', 'Todo Delete Error!', { timeOut: 500, closeButton: true });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* filter task
|
||||
*/
|
||||
search(term) {
|
||||
const searchTerm = term.currentTarget.value;
|
||||
if (searchTerm !== '') {
|
||||
this.todos = this.todos.filter(result => {
|
||||
if (result && searchTerm) {
|
||||
if (result.title.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1 ||
|
||||
result.description.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.todos = this.temp;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Open add todo modal
|
||||
*
|
||||
* @param content Add todo modal id
|
||||
*/
|
||||
open() {
|
||||
this.selectedItem = null;
|
||||
this.selectedTodoTypeValue = '';
|
||||
this.selectedTodoTypeText = '';
|
||||
this.todoComments = [];
|
||||
this.todoCommentsField = null;
|
||||
this.resetForm();
|
||||
this.selectedUserImage = '';
|
||||
this.todoId = null;
|
||||
this.todo = this.formBuilder.group({
|
||||
uid: this.loggedInUser.uid,
|
||||
title: '',
|
||||
description: '',
|
||||
type: '',
|
||||
completed: false,
|
||||
isDeleted: false,
|
||||
createdDate: new Date(),
|
||||
badge: '',
|
||||
assignedTo: '',
|
||||
assignDate: '',
|
||||
todoComments: '',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open edit todo modal
|
||||
*
|
||||
* @param editContent edit todo modal id
|
||||
* @param item edit todo modal values
|
||||
*/
|
||||
editModal(value, event) {
|
||||
this.selectedItem = value;
|
||||
if (this.contact.length > 0) {
|
||||
for (let index = 0; index < this.contact.length; index++) {
|
||||
const element = this.contact[index];
|
||||
if (element.uid === this.selectedItem.uid) {
|
||||
this.selectedItem['creator'] = element;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.todoId = this.loggedInUser.uid;
|
||||
this.TodoId = this.loggedInUser.uid;
|
||||
this.todo = this.formBuilder.group({
|
||||
uid: this.loggedInUser.uid,
|
||||
title: this.selectedItem.title,
|
||||
description: this.selectedItem.description,
|
||||
type: this.selectedItem.type,
|
||||
completed: value.completed,
|
||||
isDeleted: false,
|
||||
badge: this.selectedItem.badge,
|
||||
createdDate: value.createdDate,
|
||||
assignDate: value.assignDate,
|
||||
assignedTo: value.assignedTo,
|
||||
todoComments: value.todoComments,
|
||||
});
|
||||
this.todoCommentsField = value.todoComments;
|
||||
if (value.assignedTo) {
|
||||
this.selectedAssignee = value.assignedTo;
|
||||
}
|
||||
// this.firebaseService.getTODOS(this.loggedInUser.uid).subscribe(todos => {
|
||||
// this.todos = todos.map(item => {
|
||||
// return {
|
||||
// ...item.payload.doc.data() as {},
|
||||
// id: item.payload.doc.id
|
||||
// };
|
||||
// });
|
||||
// });
|
||||
for (let i = 0; i < this.todos.length; i++) {
|
||||
if (value.id === this.todos[i].id) {
|
||||
this.todoComments = this.todos[i].todoComments;
|
||||
}
|
||||
}
|
||||
const toggleIcon = document.getElementById('todo-new-task');
|
||||
const toggle = document.getElementById('content-overlay');
|
||||
const userImage = document.getElementById('avatar-user');
|
||||
const contentImage = document.getElementById('avatar-content');
|
||||
if (event.currentTarget.className === 'todo-item ng-star-inserted') {
|
||||
this._renderer.addClass(toggleIcon, 'show');
|
||||
this._renderer.addClass(toggle, 'show');
|
||||
} else if (this.todoId !== null) {
|
||||
this._renderer.addClass(contentImage, 'd-none');
|
||||
this._renderer.removeClass(userImage, 'd-none');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get text and value
|
||||
*
|
||||
* @param event Dropdown event
|
||||
*/
|
||||
getSelectedTODOTypeText(event: Event) {
|
||||
this.selectedTodoTypeText = event.target['options'][event.target['options'].selectedIndex].text;
|
||||
this.selectedTodoTypeValue = event.target['options'][event.target['options'].selectedIndex].value;
|
||||
}
|
||||
getSelectedTODOTypeImage(event) {
|
||||
this.selectedUserId = event.id;
|
||||
this.selectImage();
|
||||
}
|
||||
selectImage() {
|
||||
this.contact.forEach(element => {
|
||||
if (this.selectedUserId === element.id) {
|
||||
this.selectedUserImage = element.image;
|
||||
}
|
||||
});
|
||||
}
|
||||
completeTODO(data) {
|
||||
if (data.completed) {
|
||||
data.completed = false;
|
||||
} else {
|
||||
data.completed = true;
|
||||
}
|
||||
this.todo = this.formBuilder.group({
|
||||
uid: this.loggedInUser.uid,
|
||||
title: data.title,
|
||||
description: data.description,
|
||||
type: data.type,
|
||||
completed: data.completed,
|
||||
isDeleted: data.isDeleted,
|
||||
createdDate: data.createdDate,
|
||||
badge: data.badge,
|
||||
assignDate: data.assignDate,
|
||||
assignedTo: data.assignedTo,
|
||||
// todoImage: data.todoImage,
|
||||
todoComments: data.todoComments,
|
||||
});
|
||||
|
||||
this.firebaseService.updateTODO(data.id, this.todo.value)
|
||||
.subscribe(res => {
|
||||
if (this.todo.value.completed === true) {
|
||||
this.toastr.success('Success', 'Todo Completed.', { timeOut: 500, closeButton: true });
|
||||
} else {
|
||||
this.toastr.success('Success', 'Todo Updated.', { timeOut: 500, closeButton: true });
|
||||
}
|
||||
}, (err) => {
|
||||
this.toastr.error('Error', 'Something went wrong!', { timeOut: 500, closeButton: true });
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Overlay add/remove fuction in responsive
|
||||
*
|
||||
* @param event Overlay click event
|
||||
*/
|
||||
sidebartask(event) {
|
||||
const toggleIcon = document.getElementById('todo-new-task');
|
||||
const toggle = document.getElementById('content-overlay');
|
||||
const toggleSidebarIcon = document.getElementById('sidebar-left');
|
||||
const userImage = document.getElementById('avatar-user');
|
||||
const contentImage = document.getElementById('avatar-content');
|
||||
if (event.currentTarget.className === 'btn btn-danger btn-glow add-task-btn btn-block my-1') {
|
||||
this._renderer.addClass(toggleIcon, 'show');
|
||||
this._renderer.addClass(toggle, 'show');
|
||||
this._renderer.removeClass(toggleSidebarIcon, 'show');
|
||||
} else if (event.currentTarget.className.indexOf('todo-item') !== -1) {
|
||||
this._renderer.addClass(toggleIcon, 'show');
|
||||
this._renderer.addClass(toggle, 'show');
|
||||
|
||||
} else if (event.currentTarget.className === 'close close-icon' || 'app-content-overlay show') {
|
||||
this._renderer.removeClass(toggleIcon, 'show');
|
||||
this._renderer.removeClass(toggle, 'show');
|
||||
this._renderer.removeClass(toggleSidebarIcon, 'show');
|
||||
}
|
||||
}
|
||||
|
||||
sidebartaskedit(event) {
|
||||
const toggleIcon = document.getElementById('todo-new-task');
|
||||
const toggle = document.getElementById('content-overlay');
|
||||
if (event.currentTarget.className === 'btn btn-danger btn-glow add-task-btn btn-block my-1') {
|
||||
this._renderer.addClass(toggleIcon, 'show');
|
||||
this._renderer.addClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
showTodoMenu(Id, todo) {
|
||||
for (let j = 0; j < todo.length; j++) {
|
||||
for (let i = 0; i < this.todoLableList.length; i++) {
|
||||
for (let k = 0; k < this.todoFilterList.length; k++) {
|
||||
if (todo[j].lableName === this.todoLableList[i].lableName) {
|
||||
if (Id !== this.todoLableList[i].Id) {
|
||||
this.todoLableList[i].isSelected = false;
|
||||
}
|
||||
if (Id === this.todoLableList[i].Id) {
|
||||
this.todoLableList[i].isSelected = true;
|
||||
this.todoFilterList[k].isSelected = false;
|
||||
}
|
||||
} else if (todo[j].lableName === this.todoFilterList[k].lableName) {
|
||||
if (Id !== this.todoFilterList[k].Id) {
|
||||
this.todoFilterList[k].isSelected = false;
|
||||
}
|
||||
if (Id === this.todoFilterList[k].Id) {
|
||||
this.todoFilterList[k].isSelected = true;
|
||||
this.todoLableList[i].isSelected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sidebar(event) {
|
||||
const toggleIcon = document.getElementById('sidebar-left');
|
||||
const toggle = document.getElementById('content-overlay');
|
||||
if (event.currentTarget.className === 'sidebar-toggle d-block d-lg-none') {
|
||||
this._renderer.addClass(toggleIcon, 'show');
|
||||
this._renderer.addClass(toggle, 'show');
|
||||
} else if (event.currentTarget.className === 'sidebar-close-icon') {
|
||||
this._renderer.removeClass(toggleIcon, 'show');
|
||||
this._renderer.removeClass(toggle, 'show');
|
||||
}
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.focused = true;
|
||||
this.blured = false;
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.focused = false;
|
||||
this.blured = true;
|
||||
}
|
||||
todoFavorite(event, todoId) {
|
||||
const todoIcon = document.getElementById('todo-icon' + todoId);
|
||||
if (event.currentTarget.className === 'todo-item-favorite ml-75') {
|
||||
this._renderer.addClass(todoIcon, 'warning');
|
||||
} else if (event.currentTarget.className === 'todo-item-favorite ml-75 warning') {
|
||||
this._renderer.removeClass(todoIcon, 'warning');
|
||||
}
|
||||
}
|
||||
}
|
||||
11
src/app/content/cards/bootstrap/bootstrap.component.css
vendored
Normal file
11
src/app/content/cards/bootstrap/bootstrap.component.css
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
:host ::ng-deep .block-ui-wrapper {
|
||||
background: rgba(255, 249, 249, 0.5) !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .list-group-item {
|
||||
border: 1px solid #E4E7ED !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .carousel-item-next:not(.carousel-item-left){
|
||||
transform: unset !important;
|
||||
}
|
||||
1082
src/app/content/cards/bootstrap/bootstrap.component.html
Normal file
1082
src/app/content/cards/bootstrap/bootstrap.component.html
Normal file
File diff suppressed because it is too large
Load Diff
25
src/app/content/cards/bootstrap/bootstrap.component.spec.ts
Normal file
25
src/app/content/cards/bootstrap/bootstrap.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { BootstrapComponent } from './bootstrap.component';
|
||||
|
||||
describe('BootstrapComponent', () => {
|
||||
let component: BootstrapComponent;
|
||||
let fixture: ComponentFixture<BootstrapComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ BootstrapComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(BootstrapComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
110
src/app/content/cards/bootstrap/bootstrap.component.ts
Normal file
110
src/app/content/cards/bootstrap/bootstrap.component.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { NgbCarouselConfig } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { NgBlockUI, BlockUI } from 'ng-block-ui';
|
||||
|
||||
@Component({
|
||||
selector: 'app-bootstrap',
|
||||
templateUrl: './bootstrap.component.html',
|
||||
styleUrls: ['./bootstrap.component.css']
|
||||
})
|
||||
export class BootstrapComponent implements OnInit {
|
||||
@BlockUI('projectInfo') blockUIProjectInfo: NgBlockUI;
|
||||
@BlockUI('userProfile') blockUIUserProfile: NgBlockUI;
|
||||
|
||||
public breadcrumb: any;
|
||||
options = {
|
||||
close: true,
|
||||
expand: true,
|
||||
minimize: true,
|
||||
reload: true
|
||||
};
|
||||
|
||||
contactForm: FormGroup;
|
||||
projectInfo: FormGroup;
|
||||
userProfile: FormGroup;
|
||||
|
||||
interestedIn = ['design', 'development', 'illustration', 'branding', 'video'];
|
||||
budget = [
|
||||
'less than 500$',
|
||||
'500$ - 1000$',
|
||||
'1000$ - 2000$',
|
||||
'more than 20000$'
|
||||
];
|
||||
|
||||
carouselOne = [
|
||||
'../../../assets/images/carousel/02.jpg',
|
||||
'../../../assets/images/carousel/03.jpg',
|
||||
'../../../assets/images/carousel/01.jpg'
|
||||
];
|
||||
|
||||
carouselTwo = [
|
||||
'../../../assets/images/carousel/08.jpg',
|
||||
'../../../assets/images/carousel/03.jpg',
|
||||
'../../../assets/images/carousel/01.jpg'
|
||||
];
|
||||
|
||||
constructor(private formBuilder: FormBuilder, config: NgbCarouselConfig) {
|
||||
config.interval = 3000;
|
||||
config.keyboard = false;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.breadcrumb = {
|
||||
mainlabel: 'Bootstrap Cards',
|
||||
links: [
|
||||
{
|
||||
name: 'Home',
|
||||
isLink: true,
|
||||
link: '/dashboard/sales'
|
||||
},
|
||||
{
|
||||
name: 'Cards',
|
||||
isLink: true,
|
||||
link: '#'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.contactForm = this.formBuilder.group({
|
||||
name: ['', Validators.required],
|
||||
email: ['', Validators.required],
|
||||
message: ['', Validators.required]
|
||||
});
|
||||
|
||||
this.projectInfo = this.formBuilder.group({
|
||||
firstName: ['', Validators.required],
|
||||
lastName: ['', Validators.required],
|
||||
email: ['', [Validators.required, Validators.email]],
|
||||
phone: ['', Validators.required],
|
||||
company: ['', Validators.required],
|
||||
interestedIn: ['', Validators.required],
|
||||
budget: ['', Validators.required],
|
||||
aboutProject: ['', Validators.required]
|
||||
});
|
||||
|
||||
this.userProfile = this.formBuilder.group({
|
||||
firstName: ['', Validators.required],
|
||||
lastName: ['', Validators.required],
|
||||
userName: ['', Validators.required],
|
||||
nickName: ['', Validators.required],
|
||||
email: ['', Validators.required],
|
||||
website: ['', Validators.required],
|
||||
bio: ['', Validators.required]
|
||||
});
|
||||
}
|
||||
reloadProjectInfo() {
|
||||
this.blockUIProjectInfo.start('Loading..');
|
||||
|
||||
setTimeout(() => {
|
||||
this.blockUIProjectInfo.stop();
|
||||
}, 2500);
|
||||
}
|
||||
reloadUserProfile() {
|
||||
this.blockUIUserProfile.start('Loading..');
|
||||
|
||||
setTimeout(() => {
|
||||
this.blockUIUserProfile.stop();
|
||||
}, 2500);
|
||||
}
|
||||
}
|
||||
13
src/app/content/cards/cards.module.spec.ts
Normal file
13
src/app/content/cards/cards.module.spec.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { CardsModule } from './cards.module';
|
||||
|
||||
describe('CardsModule', () => {
|
||||
let cardsModule: CardsModule;
|
||||
|
||||
beforeEach(() => {
|
||||
cardsModule = new CardsModule();
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
expect(cardsModule).toBeTruthy();
|
||||
});
|
||||
});
|
||||
33
src/app/content/cards/cards.module.ts
Normal file
33
src/app/content/cards/cards.module.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { BootstrapComponent } from './bootstrap/bootstrap.component';
|
||||
import { CardModule } from '../partials/general/card/card.module';
|
||||
import { BreadcrumbModule } from 'src/app/_layout/breadcrumb/breadcrumb.module';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { BlockTemplateComponent } from 'src/app/_layout/blockui/block-template.component';
|
||||
import { BlockUIModule } from 'ng-block-ui';
|
||||
import { MatchHeightModule } from '../partials/general/match-height/match-height.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
CardModule,
|
||||
NgbModule,
|
||||
MatchHeightModule,
|
||||
BreadcrumbModule,
|
||||
ReactiveFormsModule,
|
||||
BlockUIModule.forRoot({
|
||||
template: BlockTemplateComponent
|
||||
}),
|
||||
RouterModule.forChild([{
|
||||
path: 'bootstrap',
|
||||
component: BootstrapComponent
|
||||
},
|
||||
])
|
||||
],
|
||||
declarations: [BootstrapComponent],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class CardsModule { }
|
||||
13
src/app/content/charts-maps/chartjs/chartjs.module.spec.ts
Normal file
13
src/app/content/charts-maps/chartjs/chartjs.module.spec.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { ChartjsModule } from './chartjs.module';
|
||||
|
||||
describe('ChartjsModule', () => {
|
||||
let chartjsModule: ChartjsModule;
|
||||
|
||||
beforeEach(() => {
|
||||
chartjsModule = new ChartjsModule();
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
expect(chartjsModule).toBeTruthy();
|
||||
});
|
||||
});
|
||||
29
src/app/content/charts-maps/chartjs/chartjs.module.ts
Normal file
29
src/app/content/charts-maps/chartjs/chartjs.module.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { NgChartsModule } from 'ng2-charts';
|
||||
import { ChartsComponent } from './charts/charts.component';
|
||||
import { CardModule } from '../../partials/general/card/card.module';
|
||||
import { BreadcrumbModule } from 'src/app/_layout/breadcrumb/breadcrumb.module';
|
||||
import { BlockTemplateComponent } from 'src/app/_layout/blockui/block-template.component';
|
||||
import { BlockUIModule } from 'ng-block-ui';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
BreadcrumbModule,
|
||||
NgChartsModule,
|
||||
CardModule,
|
||||
BlockUIModule.forRoot({
|
||||
template: BlockTemplateComponent
|
||||
}),
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'charts',
|
||||
component: ChartsComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
declarations: [ChartsComponent]
|
||||
})
|
||||
export class ChartjsModule { }
|
||||
636
src/app/content/charts-maps/chartjs/charts/chartjs.ts
Normal file
636
src/app/content/charts-maps/chartjs/charts/chartjs.ts
Normal file
@@ -0,0 +1,636 @@
|
||||
///////////////////// start linechart ///////////
|
||||
export const lineChartData: Array<any> = [
|
||||
{
|
||||
data: [56, 70, 55, 46, 67, 52, 70], label: 'Series C',
|
||||
backgroundColor: 'rgb(138,233,204,0.5)',
|
||||
borderColor: 'rgb(138,233,204,1)',
|
||||
pointBackgroundColor: 'rgb(138,233,204,1)',
|
||||
pointBorderColor: '#fff',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: 'rgb(138,233,204,0.2)',
|
||||
fill: true,
|
||||
lineTension: 0.4,
|
||||
},
|
||||
{
|
||||
data: [28, 48, 35, 29, 46, 27, 60], label: 'Series B',
|
||||
backgroundColor: 'rgb(68,186,239,0.7)',
|
||||
borderColor: 'rgb(168,186,239,1)',
|
||||
pointBackgroundColor: 'rgb(168,186,239,1)',
|
||||
pointBorderColor: '#fff',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: 'rgb(168,186,239,1)',
|
||||
fill: true,
|
||||
lineTension: 0.4,
|
||||
},
|
||||
{
|
||||
data: [0, 20, 11, 19, 10, 22, 9], label: 'Series A',
|
||||
backgroundColor: 'rgb(1,57,204,2.11)',
|
||||
borderColor: 'rgb(166,157,204,1)',
|
||||
pointBackgroundColor: 'rgb(166,157,204,1)',
|
||||
pointBorderColor: '#fff',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: 'rgb(166,157,204,1)',
|
||||
fill: true,
|
||||
lineTension: 0.4,
|
||||
}
|
||||
];
|
||||
export const lineChartLabels: Array<any> = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
|
||||
export const lineChartOptions: any = {
|
||||
animation: {
|
||||
duration: 1000, // general animation timebar
|
||||
easing: 'easeOutBack'
|
||||
},
|
||||
hover: {
|
||||
animationDuration: 1000, // duration of animations when hovering an item
|
||||
},
|
||||
responsiveAnimationDuration: 1000, // animation duration after a resize
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
display: true,
|
||||
ticks: {
|
||||
padding: 4
|
||||
},
|
||||
gridLines: {
|
||||
color: '#f3f3f3',
|
||||
drawTicks: false,
|
||||
},
|
||||
title:'Month',
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
text: 'Month',
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
gridLines: {
|
||||
color: '#f3f3f3',
|
||||
drawTicks: false,
|
||||
},
|
||||
ticks: {
|
||||
padding: 4
|
||||
},
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Value',
|
||||
}
|
||||
}]
|
||||
},
|
||||
};
|
||||
export const lineChartColors: Array<any> = [
|
||||
{
|
||||
backgroundColor: 'rgb(138,233,204,0.5)',
|
||||
borderColor: 'rgb(138,233,204,1)',
|
||||
pointBackgroundColor: 'rgb(138,233,204,1)',
|
||||
pointBorderColor: '#fff',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: 'rgb(138,233,204,0.2)'
|
||||
},
|
||||
{
|
||||
backgroundColor: 'rgb(68,186,239,0.8)',
|
||||
borderColor: 'rgb(168,186,239,1)',
|
||||
pointBackgroundColor: 'rgb(168,186,239,1)',
|
||||
pointBorderColor: '#fff',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: 'rgb(168,186,239,1)'
|
||||
},
|
||||
{
|
||||
backgroundColor: 'rgb(1,57,204,2.5)',
|
||||
borderColor: 'rgb(166,157,204,1)',
|
||||
pointBackgroundColor: 'rgb(166,157,204,1)',
|
||||
pointBorderColor: '#fff',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: 'rgb(166,157,204,1)'
|
||||
}
|
||||
|
||||
];
|
||||
export const lineChartLegend = true;
|
||||
export const lineChartType = 'line';
|
||||
|
||||
///////////////////// Start AreaChart///////////
|
||||
|
||||
export const areaChartData: Array<any> = [
|
||||
{
|
||||
data: [0, 150, 140, 105, 190, 230, 270], label: 'Series A',
|
||||
backgroundColor: 'rgb(237,238,240,0.4)',
|
||||
borderColor: 'transparent',
|
||||
pointBackgroundColor: '#FFF',
|
||||
pointBorderColor: 'rgb(237,238,240,0.4)',
|
||||
pointHoverBackgroundColor: 'rgb(237,238,240,0.4)',
|
||||
pointRadius: '5',
|
||||
pointHoverBorderColor: '#FFF',
|
||||
pointHoverRadius: '5',
|
||||
pointBorderWidth: '2',
|
||||
fill: true,
|
||||
lineTension: 0.4, },
|
||||
{
|
||||
data: [0, 90, 120, 240, 140, 250, 190], label: 'Series B',
|
||||
backgroundColor: 'rgb(133,158,233,0.9)',
|
||||
borderColor: 'transparent',
|
||||
pointBackgroundColor: '#FFF',
|
||||
pointBorderColor: 'rgb(133,158,233,0.9)',
|
||||
pointHoverBackgroundColor: 'rgb(133,158,233,0.9)',
|
||||
pointRadius: '5',
|
||||
pointHoverBorderColor: '#FFF',
|
||||
pointHoverRadius: '5',
|
||||
pointBorderWidth: '2' ,
|
||||
fill: true,
|
||||
lineTension: 0.4,}
|
||||
];
|
||||
export const areaChartLabels: Array<any> = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
|
||||
export const areaChartOptions: any = {
|
||||
animation: {
|
||||
duration: 1000, // general animation time
|
||||
easing: 'easeOutBack'
|
||||
},
|
||||
hover: {
|
||||
animationDuration: 1000, // duration of animations when hovering an item
|
||||
},
|
||||
responsiveAnimationDuration: 1000, // animation duration after a resize
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
display: true,
|
||||
gridLines: {
|
||||
color: '#f3f3f3',
|
||||
drawTicks: false,
|
||||
},
|
||||
ticks: {
|
||||
padding: 4
|
||||
},
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Month'
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
gridLines: {
|
||||
color: '#f3f3f3',
|
||||
drawTicks: false,
|
||||
},
|
||||
ticks: {
|
||||
padding: 4
|
||||
},
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Value'
|
||||
}
|
||||
}]
|
||||
},
|
||||
};
|
||||
export const areaChartColors: Array<any> = [
|
||||
{
|
||||
backgroundColor: 'rgb(237,238,240,0.4)',
|
||||
borderColor: 'transparent',
|
||||
pointBackgroundColor: '#FFF',
|
||||
pointBorderColor: 'rgb(237,238,240,0.4)',
|
||||
pointHoverBackgroundColor: 'rgb(237,238,240,0.4)',
|
||||
pointRadius: '5',
|
||||
pointHoverBorderColor: '#FFF',
|
||||
pointHoverRadius: '5',
|
||||
pointBorderWidth: '2'
|
||||
},
|
||||
{
|
||||
|
||||
backgroundColor: 'rgb(133,158,233,0.9)',
|
||||
borderColor: 'transparent',
|
||||
pointBackgroundColor: '#FFF',
|
||||
pointBorderColor: 'rgb(133,158,233,0.9)',
|
||||
pointHoverBackgroundColor: 'rgb(133,158,233,0.9)',
|
||||
pointRadius: '5',
|
||||
pointHoverBorderColor: '#FFF',
|
||||
pointHoverRadius: '5',
|
||||
pointBorderWidth: '2'
|
||||
},
|
||||
|
||||
];
|
||||
export const areaChartLegend = true;
|
||||
export const areaChartType = 'line';
|
||||
|
||||
///////////////////// End AreaChart///////////
|
||||
|
||||
///////////////////// End ScatterChart///////////
|
||||
// scatterChart//
|
||||
export const scatterChartData: Array<any> = [
|
||||
{
|
||||
data: [
|
||||
{
|
||||
x: 1,
|
||||
y: -0.01711,
|
||||
}, {
|
||||
x: 1.26,
|
||||
y: -2.708e-2,
|
||||
}, {
|
||||
x: 1.58,
|
||||
y: -4.285e-2,
|
||||
}, {
|
||||
x: 2.0,
|
||||
y: -6.772e-2,
|
||||
}, {
|
||||
x: 2.51,
|
||||
y: -1.068e-1,
|
||||
}, {
|
||||
x: 3.16,
|
||||
y: -1.681e-1,
|
||||
}, {
|
||||
x: 3.98,
|
||||
y: -2.635e-1,
|
||||
}, {
|
||||
x: 5.01,
|
||||
y: -4.106e-1,
|
||||
}, {
|
||||
x: 6.31,
|
||||
y: -6.339e-1,
|
||||
}, {
|
||||
x: 7.94,
|
||||
y: -9.659e-1,
|
||||
}, {
|
||||
x: 10.00,
|
||||
y: -1.445,
|
||||
}, {
|
||||
x: 12.6,
|
||||
y: -2.110,
|
||||
}, {
|
||||
x: 15.8,
|
||||
y: -2.992,
|
||||
}, {
|
||||
x: 20.0,
|
||||
y: -4.102,
|
||||
}, {
|
||||
x: 25.1,
|
||||
y: -5.429,
|
||||
}, {
|
||||
x: 31.6,
|
||||
y: -6.944,
|
||||
}, {
|
||||
x: 39.8,
|
||||
y: -8.607,
|
||||
}, {
|
||||
x: 50.1,
|
||||
y: -1.038e1,
|
||||
}, {
|
||||
x: 63.1,
|
||||
y: -1.223e1,
|
||||
}, {
|
||||
x: 79.4,
|
||||
y: -1.413e1,
|
||||
}, {
|
||||
x: 100.00,
|
||||
y: -1.607e1,
|
||||
}, {
|
||||
x: 126,
|
||||
y: -1.803e1,
|
||||
}, {
|
||||
x: 158,
|
||||
y: -2e1,
|
||||
}, {
|
||||
x: 200,
|
||||
y: -2.199e1,
|
||||
}, {
|
||||
x: 251,
|
||||
y: -2.398e1,
|
||||
}, {
|
||||
x: 316,
|
||||
y: -2.597e1,
|
||||
}, {
|
||||
x: 398,
|
||||
y: -2.797e1,
|
||||
}, {
|
||||
x: 501,
|
||||
y: -2.996e1,
|
||||
}, {
|
||||
x: 631,
|
||||
y: -3.196e1,
|
||||
}, {
|
||||
x: 794,
|
||||
y: -3.396e1,
|
||||
}, {
|
||||
x: 1000,
|
||||
y: -3.596e1,
|
||||
}
|
||||
],
|
||||
label: 'V(node2)',
|
||||
backgroundColor: 'rgba(81,117,224,.6)',
|
||||
borderColor: 'transparent',
|
||||
pointBorderColor: '#5175E0',
|
||||
pointBackgroundColor: '#FFF',
|
||||
pointBorderWidth: 2,
|
||||
pointHoverBorderWidth: 2,
|
||||
pointRadius: 4,
|
||||
}
|
||||
|
||||
];
|
||||
export const scatterChartLabels: Array<any> = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
|
||||
export const scatterChartOptions: any = {
|
||||
animation: {
|
||||
duration: 1000, // general animation time
|
||||
easing: 'easeOutBack'
|
||||
},
|
||||
hover: {
|
||||
animationDuration: 1000, // duration of animations when hovering an item
|
||||
},
|
||||
responsiveAnimationDuration: 1000, // animation duration after a resize
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
|
||||
scales: {
|
||||
myScale: {
|
||||
type: 'logarithmic',
|
||||
position: 'bottom',
|
||||
gridLines: {
|
||||
zeroLineColor: 'rgba(0,0,0,.1)',
|
||||
color: '#f3f3f3',
|
||||
drawTicks: false,
|
||||
},
|
||||
ticks: {
|
||||
padding: 4
|
||||
},
|
||||
scaleLabel: {
|
||||
labelString: 'Frequency',
|
||||
display: true,
|
||||
}
|
||||
},
|
||||
yAxes: [{
|
||||
type: 'linear',
|
||||
ticks: {
|
||||
padding: 4,
|
||||
userCallback: function (tick) {
|
||||
return tick.toString() + 'dB';
|
||||
}
|
||||
},
|
||||
gridLines: {
|
||||
zeroLineColor: 'rgba(81,117,224,1)',
|
||||
color: '#f3f3f3',
|
||||
drawTicks: false,
|
||||
},
|
||||
scaleLabel: {
|
||||
labelString: 'Voltage',
|
||||
display: true
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
export const scatterChartLegend = true;
|
||||
export const scatterChartType = 'scatter';
|
||||
|
||||
///////////////////// Start scatterChart ///////////////
|
||||
|
||||
///////////////////// Start Barchart ///////////////
|
||||
export const barChartOptions: any = {
|
||||
responsive: true,
|
||||
scaleShowVerticalLines: false,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
categoryPercentage: 0.5
|
||||
}]
|
||||
}
|
||||
};
|
||||
export const barChartLabels: string[] = ['2006', '2007', '2008', '2009', '2010', '2011', '2012'];
|
||||
export const barChartType = 'bar';
|
||||
export const barChartLegend = true;
|
||||
export const barChartData: any[] = [
|
||||
{
|
||||
data: [65, 59, 80, 81, 56, 55, 40], label: 'Series A',
|
||||
backgroundColor: '#28d094',
|
||||
borderColor: '#28d094',
|
||||
pointBackgroundColor: '#28d094',
|
||||
pointBorderColor: '#28d094',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: '#28d094',
|
||||
barPercentage: 0.9,
|
||||
categoryPercentage: 0.5 },
|
||||
{
|
||||
data: [28, 48, 40, 59, 86, 27, 90], label: 'Series B',
|
||||
backgroundColor: '#f98e76',
|
||||
borderColor: '#f98e76',
|
||||
pointBackgroundColor: '#f98e76',
|
||||
pointBorderColor: '#f98e76',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: '#f98e76',
|
||||
barPercentage: 0.9,
|
||||
categoryPercentage: 0.5 }
|
||||
];
|
||||
export const barChartColors: Array<any> = [
|
||||
{
|
||||
|
||||
},
|
||||
{
|
||||
|
||||
},
|
||||
];
|
||||
|
||||
///////////////////// End barchart////////////////
|
||||
|
||||
///////////////////// Start Doughnut////////////////
|
||||
|
||||
export const doughnutChartLabels: string[] = ['January', 'February', 'March', 'April', 'May'];
|
||||
export const doughnutChartData: any[] = [350, 250, 100, 200, 80];
|
||||
export const doughnutChartType = 'doughnut';
|
||||
export const doughnutChartColors: any[] = ['#00a5a8', '#28d094', '#ff4558', '#ff7d4d', '#626e82'];
|
||||
export const doughnutChartOptions: any = {
|
||||
animation: false,
|
||||
responsive: true,
|
||||
maintainAspectRatio: false
|
||||
};
|
||||
|
||||
///////////////////// End Doughnut////////////////
|
||||
|
||||
///////////////////// Start Radar////////////////
|
||||
|
||||
export const radarChartLabels: string[] = ['Eating', 'Drinking', 'Sleeping', 'Designing', 'Coding', 'Cycling', 'Running'];
|
||||
export const radarChartData: any[] = [
|
||||
{ label: 'Series A',
|
||||
data: [65, 59, 90, 81, 56, 55, 40],
|
||||
fill: true,
|
||||
backgroundColor: 'rgba(245,0,87,.3)',
|
||||
borderColor: 'rgba(229,229,229,0.7)',
|
||||
pointBackgroundColor: 'rgba(245,0,87,.3)',
|
||||
pointBorderColor: '#fff',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: 'rgb(245,0,87)'},
|
||||
|
||||
{ label: 'Series B',
|
||||
data: [28, 48, 40, 19, 96, 27, 100],
|
||||
fill: true,
|
||||
backgroundColor: 'rgba(29,233,182,.6)',
|
||||
borderColor: 'rgba(229,229,229,0.7)',
|
||||
pointBackgroundColor: 'rgb(29, 233,182)',
|
||||
pointBorderColor: '#fff',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: 'rgb(29, 233,182)' }
|
||||
];
|
||||
export const radarChartType = 'radar';
|
||||
|
||||
export const radarChartOptions: any = {
|
||||
animation: false,
|
||||
responsive: true,
|
||||
maintainAspectRatio: false
|
||||
};
|
||||
///////////////////// End Radar////////////////
|
||||
|
||||
|
||||
///////////////////// start PieChart////////////////
|
||||
|
||||
export const pieChartLabels: string[] = ['January', 'February', 'March', 'April', 'May'];
|
||||
export const pieChartData: any[] = [300, 200, 100, 150, 80];
|
||||
export const pieChartType = 'pie';
|
||||
export const pieChartColors: any[] = ['#00a5a8', '#28d094', '#ff4558', '#ff7d4d', '#626e82'];
|
||||
export const pieChartOptions: any = {
|
||||
animation: false,
|
||||
responsive: true,
|
||||
maintainAspectRatio: false
|
||||
};
|
||||
///////////////////// end Pie chart ////////////////
|
||||
|
||||
///////////////////// start polar-chart///////////
|
||||
// PolarArea
|
||||
export const polarAreaChartLabels: string[] = ['January', 'February', 'March', 'April', 'May'];
|
||||
export const polarAreaChartData: any[] = [300, 500, 100, 40, 120];
|
||||
export const polarAreaLegend = true;
|
||||
export const ploarChartColors: any[] = ['#00a5a8', '#28d094', '#ff4558', '#ff7d4d', '#626e82'];
|
||||
export const polarChartBorderColor: any = '#fff';
|
||||
export const polarAreaChartType = 'polarArea';
|
||||
export const polarChartOptions: any = {
|
||||
animation: false,
|
||||
responsive: true,
|
||||
maintainAspectRatio: false
|
||||
};
|
||||
///////////////////// end polar-chart///////////
|
||||
|
||||
// lineChartsData//
|
||||
export const lineChartsData: Array<any> = [
|
||||
|
||||
{
|
||||
data: [65, 59, 80, 81, 56, 55, 40],
|
||||
label: 'My First dataset',
|
||||
fill: false,
|
||||
borderDash: [5, 5],
|
||||
borderColor: '#9C27B0',
|
||||
pointBorderColor: '#9C27B0',
|
||||
pointBackgroundColor: '#FFF',
|
||||
pointBorderWidth: 2,
|
||||
pointHoverBorderWidth: 2,
|
||||
pointRadius: 4,
|
||||
lineTension: 0.4,
|
||||
},
|
||||
{
|
||||
data: [28, 48, 40, 19, 86, 27, 90], label: 'My Second dataset',
|
||||
fill: false,
|
||||
borderDash: [5, 5],
|
||||
borderColor: '#00A5A8',
|
||||
pointBorderColor: '#00A5A8',
|
||||
pointBackgroundColor: '#FFF',
|
||||
pointBorderWidth: 2,
|
||||
pointHoverBorderWidth: 2,
|
||||
pointRadius: 4,
|
||||
lineTension: 0.4,
|
||||
},
|
||||
|
||||
{
|
||||
data: [45, 25, 16, 36, 67, 18, 76], label: 'My Third dataset - No bezier',
|
||||
lineTension: 0,
|
||||
fill: false,
|
||||
borderColor: '#FF7D4D',
|
||||
pointBorderColor: '#FF7D4D',
|
||||
pointBackgroundColor: '#FFF',
|
||||
pointBorderWidth: 2,
|
||||
pointHoverBorderWidth: 2,
|
||||
pointRadius: 4,
|
||||
}
|
||||
|
||||
];
|
||||
export const lineChartsLabels: Array<any> = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
|
||||
export const lineChartsOptions: any = {
|
||||
animation: {
|
||||
duration: 1000, // general animation time
|
||||
},
|
||||
hover: {
|
||||
animationDuration: 1000, // duration of animations when hovering an item
|
||||
mode: 'label'
|
||||
},
|
||||
responsiveAnimationDuration: 1000, // animation duration after a resize
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
},
|
||||
scales: {
|
||||
myScale: [{
|
||||
display: true,
|
||||
gridLines: {
|
||||
color: 'f3f3f3',
|
||||
drawTicks: false,
|
||||
},
|
||||
ticks: {
|
||||
padding: 4
|
||||
},
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Month'
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
gridLines: {
|
||||
color: '#f3f3f3',
|
||||
drawTicks: false,
|
||||
},
|
||||
ticks: {
|
||||
padding: 4
|
||||
},
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Value'
|
||||
}
|
||||
}]
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Line Chart - Legend'
|
||||
}
|
||||
};
|
||||
export const lineChartsColors: Array<any> = [
|
||||
{
|
||||
fill: false,
|
||||
borderDash: [5, 5],
|
||||
borderColor: '#9C27B0',
|
||||
pointBorderColor: '#9C27B0',
|
||||
pointBackgroundColor: '#FFF',
|
||||
pointBorderWidth: 2,
|
||||
pointHoverBorderWidth: 2,
|
||||
pointRadius: 4,
|
||||
},
|
||||
{
|
||||
|
||||
fill: false,
|
||||
borderDash: [5, 5],
|
||||
borderColor: '#00A5A8',
|
||||
pointBorderColor: '#00A5A8',
|
||||
pointBackgroundColor: '#FFF',
|
||||
pointBorderWidth: 2,
|
||||
pointHoverBorderWidth: 2,
|
||||
pointRadius: 4,
|
||||
},
|
||||
{
|
||||
lineTension: 0,
|
||||
fill: false,
|
||||
borderColor: '#FF7D4D',
|
||||
pointBorderColor: '#FF7D4D',
|
||||
pointBackgroundColor: '#FFF',
|
||||
pointBorderWidth: 2,
|
||||
pointHoverBorderWidth: 2,
|
||||
pointRadius: 4,
|
||||
},
|
||||
];
|
||||
export const lineChartsLegend = true;
|
||||
export const lineChartsType = 'line';
|
||||
|
||||
// lineChartsData//
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
|
||||
:host ::ng-deep .barchart {
|
||||
-webkit-animation: chartjs-render-animation 0.001s;
|
||||
animation: chartjs-render-animation 0.001s;
|
||||
|
||||
}
|
||||
:host ::ng-deep .lineCharts {
|
||||
-webkit-animation: chartjs-render-animation 0.001s;
|
||||
animation: chartjs-render-animation 0.001s;
|
||||
|
||||
}
|
||||
|
||||
:host ::ng-deep .radarChart {
|
||||
height: 470px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .doughnutChart {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .pieChart {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .block-ui-wrapper {
|
||||
background: rgba(255, 249, 249, 0.5) !important;
|
||||
}
|
||||
@media(max-width:767px) {
|
||||
:host ::ng-deep .chart
|
||||
{
|
||||
height:400px !important;
|
||||
}
|
||||
}
|
||||
200
src/app/content/charts-maps/chartjs/charts/charts.component.html
Normal file
200
src/app/content/charts-maps/chartjs/charts/charts.component.html
Normal file
@@ -0,0 +1,200 @@
|
||||
<!----- start barchart------->
|
||||
<div class="app-content content">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<!-- Bar Chart -->
|
||||
<section id="chartjs-bar-charts">
|
||||
<div class="row">
|
||||
<div class="col-12" *blockUI="'barCharts'; message: 'Loading'">
|
||||
<m-card [options]="options" (reloadFunction)="reloadBarCharts($event)">
|
||||
<ng-container mCardHeaderTitle>
|
||||
Bar charts
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<div class="z">
|
||||
<canvas class="barchart" height="400" baseChart [datasets]="barChartData" [labels]="barChartLabels"
|
||||
[options]="barChartOptions" [legend]="barChartLegend" [chartType]="barChartType"></canvas>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- End Bar charts-->
|
||||
<!-- line Chart -->
|
||||
<section id="chartjs-line-charts">
|
||||
<div class="row">
|
||||
<div class="col-12" *blockUI="'lineCharts'; message: 'Loading'">
|
||||
<m-card [options]="options" (reloadFunction)="reloadLineCharts($event)">
|
||||
<ng-container mCardHeaderTitle>
|
||||
Line Charts
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<div class="card-block">
|
||||
<div class="height-400">
|
||||
<canvas height="400" baseChart class="chart" [datasets]="lineChartsData" [labels]="lineChartsLabels"
|
||||
[options]="lineChartsOptions" [colors]="lineChartsColors" [legend]="lineChartsLegend"
|
||||
[type]="lineChartsType"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- End line chart-->
|
||||
<!-- Area Line chart-->
|
||||
<section id="chartjs-arealine-charts">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<m-card>
|
||||
<ng-container mCardHeaderTitle>
|
||||
Area Line charts
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<div class="card-block">
|
||||
<div class="height-400">
|
||||
<canvas height="400" baseChart class="chart" [datasets]="areaChartData" [labels]="areaChartLabels"
|
||||
[options]="areaChartOptions" [legend]="areaChartLegend"
|
||||
[type]="areaChartType">
|
||||
</canvas>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- End Area Line chart------->
|
||||
<!-- Line Stacked Area Chart -->
|
||||
<section id="chartjs-line-stacked-charts">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<m-card>
|
||||
<ng-container mCardHeaderTitle>
|
||||
Line Stacked Area Chart
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<!-- <div class="lineStackedArea"> -->
|
||||
<div class="card-block">
|
||||
<div class="height-400">
|
||||
<canvas height="400" baseChart class="chart" [datasets]="lineChartData" [labels]="lineChartLabels"
|
||||
[options]="lineChartOptions" [legend]="lineChartLegend" [type]="lineChartType">
|
||||
</canvas>
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- End Line Stacked Area Chart -->
|
||||
<!-- Scatter Logx Chart -->
|
||||
<section id="chartjs-scatter-charts">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<m-card>
|
||||
<ng-container mCardHeaderTitle>
|
||||
Scatter Logx Chart
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<div class="card-block">
|
||||
<div class="height-400">
|
||||
<canvas height="400" id="scatter-chart" baseChart class="chart" [datasets]="scatterChartData"
|
||||
[labels]="scatterChartLabels" [options]="scatterChartOptions" [legend]="scatterChartLegend"
|
||||
[type]="scatterChartType"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- End Scatter Logx Chart -->
|
||||
<!-- Pie Chart -->
|
||||
<section id="chartjs-pie-charts">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-content collapse show">
|
||||
<div class="card-body">
|
||||
<h3>Pie Chart</h3>
|
||||
<div class="pieChart height-400">
|
||||
<canvas baseChart width="400" style="display: unset;" [type]="'pie'" [datasets]="pieChartData"
|
||||
[labels]="pieChartLabels" [options]="pieChartOptions" [plugins]="pieChartPlugins"
|
||||
[legend]="pieChartLegend">
|
||||
</canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- End Pie Chart -->
|
||||
<!-- Doughnut Chart -->
|
||||
<section id="chartjs-doughnut-charts">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-content collapse show">
|
||||
<div class="card-body">
|
||||
<h3>Doughnut Chart</h3>
|
||||
<div class="doughnutChart height-400">
|
||||
<canvas baseChart width="400" style="display: unset;" [datasets]="doughnutChartData"
|
||||
[options]="doughnutChartOptions" [labels]="doughnutChartLabels" [type]="'doughnut'"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- End Doughnut Chart -->
|
||||
<!-- Polar Chart -->
|
||||
<section id="chartjs-polar-charts">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-content collapse show">
|
||||
<div class="card-body">
|
||||
<h3>Polar Chart</h3>
|
||||
<div class="polarchart height-400">
|
||||
<canvas baseChart [datasets]="polarAreaChartData" [labels]="polarAreaChartLabels"
|
||||
[legend]="polarAreaLegend" [options]="polarChartOptions" [type]="polarAreaChartType"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- End Polar Chart -->
|
||||
<!-- Radar Chart -->
|
||||
<section id="chartjs-radar-charts">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card radarChart">
|
||||
<div class="card-content collapse show">
|
||||
<div class="card-body">
|
||||
<div class="height-400">
|
||||
<h3>Radar Chart</h3>
|
||||
<canvas baseChart [datasets]="radarChartData" [options]="radarChartOptions"
|
||||
[labels]="radarChartLabels" [type]="radarChartType"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- End Radar Chart -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ////////////////////////////////////////////////////////////////////////////-->
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { ChartsComponent } from './charts.component';
|
||||
|
||||
describe('ChartsComponent', () => {
|
||||
let component: ChartsComponent;
|
||||
let fixture: ComponentFixture<ChartsComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ChartsComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ChartsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
165
src/app/content/charts-maps/chartjs/charts/charts.component.ts
Normal file
165
src/app/content/charts-maps/chartjs/charts/charts.component.ts
Normal file
@@ -0,0 +1,165 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { NgBlockUI, BlockUI } from "ng-block-ui";
|
||||
import { ChartConfiguration, ChartOptions } from 'chart.js';
|
||||
|
||||
import * as chartsData from "./chartjs";
|
||||
import { title } from "process";
|
||||
|
||||
@Component({
|
||||
selector: "app-charts",
|
||||
templateUrl: "./charts.component.html",
|
||||
styleUrls: ["./charts.component.css"],
|
||||
})
|
||||
export class ChartsComponent implements OnInit {
|
||||
@BlockUI("barCharts") blockUIBarCharts: NgBlockUI;
|
||||
@BlockUI("lineCharts") blockUILineCharts: NgBlockUI;
|
||||
|
||||
public breadcrumb: any;
|
||||
showNew: false;
|
||||
|
||||
options = {
|
||||
close: true,
|
||||
expand: true,
|
||||
minimize: true,
|
||||
reload: true,
|
||||
};
|
||||
|
||||
/**
|
||||
* barChart
|
||||
*/
|
||||
public barChartOptions = chartsData.barChartOptions;
|
||||
public barChartLabels = chartsData.barChartLabels;
|
||||
public barChartType = chartsData.barChartType;
|
||||
public barChartLegend = chartsData.barChartLegend;
|
||||
public barChartData = chartsData.barChartData;
|
||||
public barChartColors = chartsData.barChartColors;
|
||||
|
||||
/**
|
||||
* lineChart
|
||||
*/
|
||||
public lineChartData = chartsData.lineChartData;
|
||||
public lineChartLabels = chartsData.lineChartLabels;
|
||||
public lineChartOptions = chartsData.lineChartOptions;
|
||||
public lineChartColors = chartsData.lineChartColors;
|
||||
public lineChartLegend = chartsData.lineChartLegend;
|
||||
public lineChartType = chartsData.lineChartType;
|
||||
|
||||
/**
|
||||
* areaChart
|
||||
*/
|
||||
public areaChartData = chartsData.areaChartData;
|
||||
public areaChartLabels = chartsData.areaChartLabels;
|
||||
public areaChartOptions = chartsData.areaChartOptions;
|
||||
public areaChartColors = chartsData.areaChartColors;
|
||||
public areaChartLegend = chartsData.areaChartLegend;
|
||||
public areaChartType = chartsData.areaChartType;
|
||||
|
||||
/**
|
||||
* scatterChartData
|
||||
*/
|
||||
public scatterChartData = chartsData.scatterChartData;
|
||||
public scatterChartLabels = chartsData.scatterChartLabels;
|
||||
public scatterChartOptions = chartsData.scatterChartOptions;
|
||||
// public scatterChartColors = chartsData.scatterChartColors;
|
||||
public scatterChartLegend = chartsData.scatterChartLegend;
|
||||
public scatterChartType = chartsData.scatterChartType;
|
||||
/**
|
||||
* Doughnut
|
||||
*/
|
||||
|
||||
|
||||
public doughnutChartLabels: string[] = chartsData.doughnutChartLabels;;
|
||||
public doughnutChartData: ChartConfiguration<'doughnut'>['data']['datasets'] = [
|
||||
{
|
||||
data: chartsData.doughnutChartData,
|
||||
backgroundColor: chartsData.doughnutChartColors,
|
||||
},
|
||||
];
|
||||
public doughnutChartOptions = chartsData.doughnutChartOptions;
|
||||
/**
|
||||
* Radar
|
||||
*/
|
||||
public radarChartLabels = chartsData.radarChartLabels;
|
||||
public radarChartData = chartsData.radarChartData;
|
||||
public radarChartType = chartsData.radarChartType;
|
||||
public radarChartOptions = chartsData.radarChartOptions;
|
||||
|
||||
/**
|
||||
* Pie
|
||||
*/
|
||||
public pieChartOptions: ChartOptions<'pie'> = {
|
||||
responsive: true,
|
||||
};
|
||||
public pieChartLabels = chartsData.pieChartLabels;
|
||||
public pieChartData = [{
|
||||
data: chartsData.pieChartData,
|
||||
backgroundColor: chartsData.pieChartColors,
|
||||
}];
|
||||
public pieChartLegend = true;
|
||||
public pieChartPlugins = [];
|
||||
public pieChartType = chartsData.pieChartType;
|
||||
|
||||
/**
|
||||
* PolarArea
|
||||
*/
|
||||
public polarAreaChartLabels = chartsData.polarAreaChartLabels;
|
||||
public polarAreaChartData: ChartConfiguration<'polarArea'>['data']['datasets'] = [
|
||||
{
|
||||
data: chartsData.polarAreaChartData,
|
||||
backgroundColor: chartsData.ploarChartColors,
|
||||
borderColor: chartsData.polarChartBorderColor,
|
||||
}
|
||||
];
|
||||
public polarAreaLegend = chartsData.polarAreaLegend;
|
||||
public polarAreaChartType = chartsData.polarAreaChartType;
|
||||
public polarChartOptions = chartsData.polarChartOptions;
|
||||
|
||||
/**
|
||||
* lineChart
|
||||
*/
|
||||
public lineChartsData = chartsData.lineChartsData;
|
||||
public lineChartsLabels = chartsData.lineChartsLabels;
|
||||
public lineChartsOptions = chartsData.lineChartsOptions;
|
||||
public lineChartsColors = chartsData.lineChartsColors;
|
||||
public lineChartsLegend = chartsData.lineChartsLegend;
|
||||
public lineChartsType = chartsData.lineChartsType;
|
||||
|
||||
/**
|
||||
* OnInit
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.breadcrumb = {
|
||||
mainlabel: "Chartjs Charts",
|
||||
links: [
|
||||
{
|
||||
name: "Home",
|
||||
isLink: true,
|
||||
link: "/dashboard/sales",
|
||||
},
|
||||
{
|
||||
name: "Chartjs",
|
||||
isLink: true,
|
||||
link: "#",
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Reload card
|
||||
*/
|
||||
reloadBarCharts() {
|
||||
this.blockUIBarCharts.start("Loading..");
|
||||
|
||||
setTimeout(() => {
|
||||
this.blockUIBarCharts.stop();
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
reloadLineCharts() {
|
||||
this.blockUILineCharts.start("Loading..");
|
||||
|
||||
setTimeout(() => {
|
||||
this.blockUILineCharts.stop();
|
||||
}, 2500);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
:host ::ng-deep .lineArea2 .ct-point-circle {
|
||||
stroke-width: 2px;
|
||||
fill: #fff;
|
||||
stroke: #ff8d60;
|
||||
}
|
||||
|
||||
:host ::ng-deep .dragdrop-container {
|
||||
min-height: 200px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-series-b .ct-line {
|
||||
stroke: #ff8d60;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-series-a .ct-line {
|
||||
stroke: #84cfd1;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-series-c .ct-line {
|
||||
stroke: #ff586b;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-series-a .ct-area {
|
||||
fill: #0eb8de;
|
||||
}
|
||||
:host ::ng-deep .ct-series-a .ct-point {
|
||||
stroke: #84cfd1;
|
||||
}
|
||||
:host ::ng-deep .lineArea2 .ct-series-a .ct-point-circle {
|
||||
stroke: #84cfd1;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .lineChart1 .ct-series-a .ct-point {
|
||||
stroke-width: 0px;
|
||||
|
||||
stroke: #84cfd1;
|
||||
}
|
||||
|
||||
:host ::ng-deep .lineChart1 .ct-series-b .ct-point {
|
||||
stroke-width: 0px;
|
||||
|
||||
stroke: #ff8d60;
|
||||
}
|
||||
|
||||
:host ::ng-deep .lineChart1 .ct-series-c .ct-point {
|
||||
stroke-width: 0px;
|
||||
|
||||
stroke: #ff586b;
|
||||
}
|
||||
|
||||
:host ::ng-deep .lineChart3 .ct-series-a .ct-point {
|
||||
stroke-width: 10px;
|
||||
|
||||
stroke: #84cfd1;
|
||||
}
|
||||
|
||||
:host ::ng-deep .lineChart3 .ct-series-b .ct-point {
|
||||
stroke-width: 10px;
|
||||
|
||||
stroke: #ff8d60;
|
||||
}
|
||||
|
||||
:host ::ng-deep .lineChart3 .ct-series-c .ct-point {
|
||||
stroke-width: 10px;
|
||||
|
||||
stroke: #ff586b;
|
||||
}
|
||||
|
||||
:host ::ng-deep .lineArea3 .ct-series-b .ct-point-circle {
|
||||
stroke-width: 2px;
|
||||
fill: #fff;
|
||||
stroke: #ff8d60;
|
||||
}
|
||||
|
||||
:host ::ng-deep .lineArea3 .ct-series-a .ct-point-circle {
|
||||
stroke-width: 2px;
|
||||
fill: #fff;
|
||||
stroke: #84cfd1;
|
||||
}
|
||||
:host ::ng-deep .lineChart2 .ct-series-a .ct-point-circle {
|
||||
stroke: #84cfd1;
|
||||
stroke-width: 2px;
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
:host ::ng-deep .lineChart2 .ct-series-b .ct-point-circle {
|
||||
stroke: #ff8d60;
|
||||
stroke-width: 2px;
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
:host ::ng-deep .bar-chart .ct-series-b .ct-bar {
|
||||
|
||||
stroke: #ff8d60;
|
||||
}
|
||||
|
||||
:host ::ng-deep .bar-chart .ct-series-a .ct-bar {
|
||||
|
||||
stroke: #009da0;
|
||||
}
|
||||
|
||||
:host ::ng-deep .distributed-bar-chart .ct-series-a .ct-bar {
|
||||
stroke: #009da0;
|
||||
}
|
||||
|
||||
:host ::ng-deep .distributed-bar-chart .ct-series-b .ct-bar {
|
||||
stroke: #ff8d60;
|
||||
}
|
||||
|
||||
:host ::ng-deep .distributed-bar-chart .ct-series-c .ct-bar {
|
||||
stroke: #ff586b;
|
||||
}
|
||||
|
||||
:host ::ng-deep .distributed-bar-chart .ct-series-d .ct-bar {
|
||||
stroke: #1cbcd8
|
||||
}
|
||||
|
||||
:host ::ng-deep .distributed-bar-chart .ct-series-e .ct-bar {
|
||||
stroke: #0cc27e;
|
||||
}
|
||||
|
||||
:host ::ng-deep .distributed-bar-chart .ct-series-f .ct-bar {
|
||||
stroke: #9c27b0;
|
||||
}
|
||||
|
||||
:host ::ng-deep .distributed-bar-chart .ct-series-f .ct-bar {
|
||||
stroke: #ffc107;
|
||||
;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-series-a .ct-slice-donut {
|
||||
stroke: #009da0;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-series-b .ct-slice-donut {
|
||||
stroke: #ff8d60;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-series-c .ct-slice-donut {
|
||||
stroke: #ff586b;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-series-d .ct-slice-donut {
|
||||
stroke: #1cbcd8;
|
||||
}
|
||||
|
||||
:host ::ng-deep .Bi-polar .ct-series-a .ct-area {
|
||||
fill: #84cfd1;
|
||||
fill-opacity: 0.6;
|
||||
}
|
||||
|
||||
:host ::ng-deep .Bi-polar .ct-series-b .ct-area {
|
||||
fill: #ff586b;
|
||||
fill-opacity: 0.6;
|
||||
}
|
||||
|
||||
:host ::ng-deep .Bi-polar .ct-series-c .ct-area {
|
||||
fill: #f0c5de;
|
||||
fill-opacity: 0.6;
|
||||
}
|
||||
|
||||
:host ::ng-deep .svg {
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
:host ::ng-deep .block-ui-wrapper {
|
||||
background: rgba(255, 249, 249, 0.5) !important;
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
<div class="app-content content">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
<app-breadcrumb class="col-12" [breadcrumb]="breadcrumb"></app-breadcrumb>
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<!-- chartist line charts section start -->
|
||||
<!--Line with Area Chart 1 Starts-->
|
||||
<div class="row text-left">
|
||||
<div class="col-sm-12" *blockUI="'lineWithAreaChartOne'; message: 'Loading'">
|
||||
<m-card [options]="options" (reloadFunction)="reloadLineWithAreaChartOne($event)">
|
||||
<ng-container mCardHeaderTitle>
|
||||
Line with Area Chart(Filled Holes in data)
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<div id="line-area1" class="height-300 lineArea1">
|
||||
<x-chartist *ngIf="lineArea1" [data]="lineArea1.data" [type]="lineArea1.type" [options]="lineArea1.options"
|
||||
[responsiveOptions]="lineArea1.responsiveOptions" [events]="lineArea1.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
<!--Line with Area Chart 1 Ends-->
|
||||
<!--Line with Area Chart 2 Starts-->
|
||||
<div class="row text-left">
|
||||
<div class="col-sm-12" *blockUI="'lineWithAreaChartTwo'; message: 'Loading'">
|
||||
<m-card [options]="options" (reloadFunction)="reloadLineWithAreaChartTwo($event)">
|
||||
<ng-container mCardHeaderTitle>
|
||||
Line with Area Chart(Holes in Data)
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<div id="line-area2" class="height-300 lineArea2">
|
||||
<x-chartist *ngIf="lineArea2" [data]="lineArea2.data" [type]="lineArea2.type" [options]="lineArea2.options"
|
||||
[responsiveOptions]="lineArea2.responsiveOptions" [events]="lineArea2.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
<!--Line with Area Chart 2 Ends-->
|
||||
<!--Line with Area Chart 3 Starts-->
|
||||
<div class="row text-left">
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Line with Area Chart(Holes in Data)</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-block">
|
||||
<div id="line-area3" class="height-300 lineArea3">
|
||||
<x-chartist *ngIf="lineArea3" [data]="lineArea3.data" [type]="lineArea3.type" [options]="lineArea3.options"
|
||||
[responsiveOptions]="lineArea3.responsiveOptions" [events]="lineArea3.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Line with Area Chart 3 Ends-->
|
||||
<!--Line with Area Chart 4 Starts-->
|
||||
<div class="row text-left">
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Simple Line with Area Chart</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-block">
|
||||
<div id="line-area4" class="height-300">
|
||||
<x-chartist *ngIf="lineArea4" [data]="lineArea4.data" [type]="lineArea4.type" [options]="lineArea4.options"
|
||||
[responsiveOptions]="lineArea4.responsiveOptions" [events]="lineArea4.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Line with Area Chart 4 Ends-->
|
||||
<!--Line Chart 1 Starts-->
|
||||
<div class="row text-left">
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Simple Line Chart </h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-block lineChart1">
|
||||
<div id="line-chart1" class="height-300 lineChart1 lineChart1Shadow">
|
||||
<x-chartist *ngIf="lineChart1" [data]="lineChart1.data" [type]="lineChart1.type" [options]="lineChart1.options"
|
||||
[responsiveOptions]="lineChart1.responsiveOptions" [events]="lineChart1.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Line Chart 1 Ends-->
|
||||
<!--Line Chart 2 Starts-->
|
||||
<div class="row text-left">
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Line Chart(Holes in data)</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-block">
|
||||
<div id="line-chart2" class="height-300 lineChart2">
|
||||
<x-chartist *ngIf="lineChart2" [data]="lineChart2.data" [type]="lineChart2.type" [options]="lineChart2.options"
|
||||
[responsiveOptions]="lineChart2.responsiveOptions" [events]="lineChart2.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Line Chart 2 Ends-->
|
||||
<!--Line Chart 3 Starts-->
|
||||
<div class="row text-left">
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Line Chart(Filled Holes in data)</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-block lineChart3">
|
||||
<div id="line-chart3" class="height-300">
|
||||
<x-chartist *ngIf="lineChart3" [data]="lineChart3.data" [type]="lineChart3.type" [options]="lineChart3.options"
|
||||
[responsiveOptions]="lineChart3.responsiveOptions" [events]="lineChart3.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Line Chart 3 Ends-->
|
||||
<!--Scatter Line Chart Starts-->
|
||||
<div class="row text-left">
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Scatter Line Chart</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-block">
|
||||
<div id="scatter -line-chart" class="height-300">
|
||||
<x-chartist *ngIf="scatterlineChart" [data]="scatterlineChart.data" [type]="scatterlineChart.type"
|
||||
[options]="scatterlineChart.options" [responsiveOptions]="scatterlineChart.responsiveOptions"
|
||||
[events]="scatterlineChart.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Scatter Line Chart Ends-->
|
||||
<!--Scatter Chart Starts-->
|
||||
<div class="row text-left">
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Scatter Chart</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-block">
|
||||
<div id="scatter-chart2" class="height-300">
|
||||
<x-chartist *ngIf="scatterChart" [data]="scatterChart.data" [type]="scatterChart.type" [options]="scatterChart.options"
|
||||
[responsiveOptions]="scatterChart.responsiveOptions" [events]="scatterChart.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Scatter Chart Ends-->
|
||||
<!--Bi-polar Line Chart Starts-->
|
||||
<div class="row text-left">
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Bi-polar Line Chart</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-block">
|
||||
<div id="bi-polar-chart" class="height-300 Bi-polar">
|
||||
<x-chartist *ngIf="biPolarLineChart" [data]="biPolarLineChart.data" [type]="biPolarLineChart.type"
|
||||
[options]="biPolarLineChart.options" [responsiveOptions]="biPolarLineChart.responsiveOptions"
|
||||
[events]="biPolarLineChart.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Bi-polar Line Chart Ends-->
|
||||
<!--Bar Chart Starts-->
|
||||
<div class="row text-left">
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Bar Chart</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-block">
|
||||
<div id="bar-chart" class="height-300 bar-chart">
|
||||
<x-chartist *ngIf="barChart" [data]="barChart.data" [type]="barChart.type" [options]="barChart.options"
|
||||
[responsiveOptions]="barChart.responsiveOptions" [events]="barChart.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Bar Chart Ends-->
|
||||
<!--Distributed Series Bar Chart Starts-->
|
||||
<div class="row text-left">
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Distributed Series Bar Chart</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-block">
|
||||
<div id="distributed-bar-chart" class="height-300 distributed-bar-chart">
|
||||
<x-chartist *ngIf="distributedSeriesBarChart" [data]="distributedSeriesBarChart.data" [type]="distributedSeriesBarChart.type"
|
||||
[options]="distributedSeriesBarChart.options"
|
||||
[responsiveOptions]="distributedSeriesBarChart.responsiveOptions"
|
||||
[events]="distributedSeriesBarChart.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Distributed Series Bar Chart Ends-->
|
||||
<!--Donut Chart 1 Starts-->
|
||||
<div class="row text-left">
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Donut Chart</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-block">
|
||||
<div id="donut-chart1" class="height-300">
|
||||
<x-chartist *ngIf="donutChart1" [data]="donutChart1.data" [type]="donutChart1.type" [options]="donutChart1.options"
|
||||
[responsiveOptions]="donutChart1.responsiveOptions" [events]="donutChart1.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Donut Chart 1 Ends-->
|
||||
<!--Donut Chart 2 Starts-->
|
||||
<div class="row text-left">
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Donut Chart</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-block">
|
||||
<div id="donut-chart2" class="height-400">
|
||||
<x-chartist *ngIf="donutChart2" [data]="donutChart2.data" [type]="donutChart2.type" [options]="donutChart2.options"
|
||||
[responsiveOptions]="donutChart2.responsiveOptions" [events]="donutChart2.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--Donut Chart 2 Ends-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ////////////////////////////////////////////////////////////////////////////-->
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { LinechartsComponent } from './linecharts.component';
|
||||
|
||||
describe('LinechartsComponent', () => {
|
||||
let component: LinechartsComponent;
|
||||
let fixture: ComponentFixture<LinechartsComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ LinechartsComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LinechartsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,575 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import * as Chartist from 'chartist';
|
||||
import { ChartEvent, ChartType } from 'ng-chartist';
|
||||
import { NgBlockUI, BlockUI } from 'ng-block-ui';
|
||||
import { ChartApiService } from '../../../../_services/chart.api';
|
||||
/**
|
||||
* Interface
|
||||
*/
|
||||
export interface Chart {
|
||||
type: ChartType;
|
||||
data: Chartist.IChartistData;
|
||||
options?: any;
|
||||
responsiveOptions?: any;
|
||||
events?: ChartEvent;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-linecharts',
|
||||
templateUrl: './linecharts.component.html',
|
||||
styleUrls: ['./linecharts.component.css']
|
||||
})
|
||||
export class LinechartsComponent implements OnInit {
|
||||
|
||||
@BlockUI('lineWithAreaChartOne') blockUILineWithAreaChartOne: NgBlockUI;
|
||||
@BlockUI('lineWithAreaChartTwo') blockUILineWithAreaChartTwo: NgBlockUI;
|
||||
public breadcrumb: any;
|
||||
data: any;
|
||||
loadDataURL: string;
|
||||
lineArea1: any;
|
||||
lineArea2: any;
|
||||
lineArea3: any;
|
||||
lineArea4: any;
|
||||
donutChart1: any;
|
||||
donutChart2: any;
|
||||
scatterChart: any;
|
||||
scatterlineChart: any;
|
||||
lineChart1: any;
|
||||
lineChart2: any;
|
||||
lineChart3: any;
|
||||
biPolarLineChart: any;
|
||||
barChart: any;
|
||||
distributedSeriesBarChart: any;
|
||||
options = {
|
||||
close: true,
|
||||
expand: true,
|
||||
minimize: true,
|
||||
reload: true
|
||||
};
|
||||
constructor(private chartApiservice: ChartApiService) {
|
||||
}
|
||||
/**
|
||||
* Get chart data
|
||||
*/
|
||||
getlineArea() {
|
||||
const Chartdata = this.data;
|
||||
// Line with Area Chart 1 Starts
|
||||
this.lineArea1 = {
|
||||
type: 'Line',
|
||||
data: Chartdata['lineArea1'],
|
||||
options: {
|
||||
height: '300px',
|
||||
low: 0,
|
||||
showArea: true,
|
||||
fullWidth: true,
|
||||
onlyInteger: true,
|
||||
axisY: {
|
||||
low: 0,
|
||||
scaleMinSpace: 50,
|
||||
},
|
||||
axisX: {
|
||||
showGrid: false
|
||||
},
|
||||
},
|
||||
responsiveOptions: [
|
||||
['screen and (max-width: 640px) and (min-width: 381px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}],
|
||||
['screen and (max-width: 380px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 3 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}]
|
||||
],
|
||||
events: {
|
||||
created(data: any): void {
|
||||
const defs = data.svg.elem('defs');
|
||||
defs.elem('linearGradient', {
|
||||
id: 'gradient',
|
||||
x1: 0,
|
||||
y1: 1,
|
||||
x2: 0,
|
||||
y2: 0
|
||||
}).elem('stop', {
|
||||
offset: 0,
|
||||
'stop-color': 'rgba(255, 255, 255, 1)'
|
||||
}).parent().elem('stop', {
|
||||
offset: 1,
|
||||
'stop-color': 'rgba(38, 198, 218, 1)'
|
||||
});
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
// Line with Area Chart 1 Ends
|
||||
|
||||
// Line with Area Chart 2 Starts
|
||||
this.lineArea2 = {
|
||||
type: 'Line',
|
||||
data: Chartdata['lineArea2'],
|
||||
options: {
|
||||
height: '300px',
|
||||
showArea: true,
|
||||
fullWidth: true,
|
||||
lineSmooth: Chartist.Interpolation.none(),
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
},
|
||||
axisY: {
|
||||
low: 0,
|
||||
scaleMinSpace: 50,
|
||||
},
|
||||
chartPadding: { top: 0, right: 25, bottom: 0, left: 0 },
|
||||
},
|
||||
responsiveOptions: [
|
||||
['screen and (max-width: 640px) and (min-width: 381px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}],
|
||||
['screen and (max-width: 380px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 3 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}]
|
||||
],
|
||||
events: {
|
||||
created(data: any): void {
|
||||
const defs = data.svg.elem('defs');
|
||||
defs.elem('linearGradient', {
|
||||
id: 'gradient1',
|
||||
x1: 0,
|
||||
y1: 1,
|
||||
x2: 0,
|
||||
y2: 0
|
||||
}).elem('stop', {
|
||||
offset: 0.2,
|
||||
'stop-color': 'rgba(255, 255, 255, 1)'
|
||||
}).parent().elem('stop', {
|
||||
offset: 1,
|
||||
'stop-color': 'rgba(38, 198, 218, 1)'
|
||||
});
|
||||
|
||||
defs.elem('linearGradient', {
|
||||
id: 'gradient2',
|
||||
x1: 0,
|
||||
y1: 1,
|
||||
x2: 0,
|
||||
y2: 0
|
||||
}).elem('stop', {
|
||||
offset: 0.5,
|
||||
'stop-color': 'rgba(255, 255, 255, 1)'
|
||||
}).parent().elem('stop', {
|
||||
offset: 1,
|
||||
'stop-color': 'rgba(255,141,96, 1)'
|
||||
});
|
||||
},
|
||||
draw(data: any): void {
|
||||
|
||||
const circleRadius = 6;
|
||||
if (data.type === 'point') {
|
||||
const circle = new Chartist.Svg('circle', {
|
||||
cx: data.x,
|
||||
cy: data.y,
|
||||
r: circleRadius,
|
||||
class: 'ct-point-circle'
|
||||
});
|
||||
data.element.replace(circle);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
// Line with Area Chart 2 Ends
|
||||
|
||||
// Line with Area Chart 3 Starts
|
||||
this.lineArea3 = {
|
||||
type: 'Line',
|
||||
data: Chartdata['lineArea3'],
|
||||
options: {
|
||||
height: '300px',
|
||||
low: 0,
|
||||
showArea: true,
|
||||
fullWidth: true,
|
||||
onlyInteger: true,
|
||||
axisY: {
|
||||
low: 0,
|
||||
scaleMinSpace: 50,
|
||||
}
|
||||
},
|
||||
responsiveOptions: [
|
||||
['screen and (max-width: 640px) and (min-width: 381px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}],
|
||||
['screen and (max-width: 380px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 3 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}]
|
||||
],
|
||||
events: {
|
||||
created(data: any): void {
|
||||
const defs = data.svg.elem('defs');
|
||||
defs.elem('linearGradient', {
|
||||
id: 'gradient',
|
||||
x1: 0,
|
||||
y1: 1,
|
||||
x2: 0,
|
||||
y2: 0
|
||||
}).elem('stop', {
|
||||
offset: 0,
|
||||
'stop-color': 'rgba(255, 255, 255, 1)'
|
||||
}).parent().elem('stop', {
|
||||
offset: 1,
|
||||
'stop-color': 'rgba(38, 198, 218, 1)'
|
||||
});
|
||||
},
|
||||
|
||||
draw(data: any): void {
|
||||
const circleRadius = 6;
|
||||
if (data.type === 'point') {
|
||||
const circle = new Chartist.Svg('circle', {
|
||||
cx: data.x,
|
||||
cy: data.y,
|
||||
r: circleRadius,
|
||||
class: 'ct-point-circle'
|
||||
});
|
||||
data.element.replace(circle);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
// Line with Area Chart 3 Ends
|
||||
|
||||
// Line with Area Chart 4 Starts
|
||||
this.lineArea4 = {
|
||||
type: 'Line',
|
||||
data: Chartdata['lineArea4'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
height: '300px',
|
||||
low: 0,
|
||||
showArea: true,
|
||||
fullWidth: true,
|
||||
},
|
||||
};
|
||||
// Line with Area Chart 4 Ends
|
||||
|
||||
// Line Chart 1 Starts
|
||||
this.lineChart1 = {
|
||||
type: 'Line',
|
||||
data: Chartdata['line1'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
height: '300px',
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
},
|
||||
axisY: {
|
||||
low: 0,
|
||||
scaleMinSpace: 50,
|
||||
},
|
||||
fullWidth: true,
|
||||
chartPadding: { top: 0, right: 25, bottom: 0, left: 0 }
|
||||
},
|
||||
};
|
||||
// Line Chart 1 Ends
|
||||
|
||||
// Line Chart 2 Starts
|
||||
this.lineChart2 = {
|
||||
type: 'Line',
|
||||
data: Chartdata['line2'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
height: '300px',
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
},
|
||||
axisY: {
|
||||
low: 0,
|
||||
scaleMinSpace: 50,
|
||||
},
|
||||
fullWidth: true,
|
||||
chartPadding: { top: 0, right: 25, bottom: 0, left: 0 },
|
||||
},
|
||||
responsiveOptions: [
|
||||
[{
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}],
|
||||
['screen and (max-width: 380px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 3 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}]
|
||||
],
|
||||
events: {
|
||||
draw(data: any): void {
|
||||
const circleRadius = 6;
|
||||
if (data.type === 'point') {
|
||||
const circle = new Chartist.Svg('circle', {
|
||||
cx: data.x,
|
||||
cy: data.y,
|
||||
r: circleRadius,
|
||||
class: 'ct-point-circle'
|
||||
});
|
||||
|
||||
data.element.replace(circle);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
// Line Chart 2 Ends
|
||||
|
||||
// Line Chart 3 Starts
|
||||
this.lineChart3 = {
|
||||
type: 'Line',
|
||||
data: Chartdata['Line3'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
height: '300px',
|
||||
axisX: { showGrid: false }, axisY: {
|
||||
scaleMinSpace: 30,
|
||||
}, fullWidth: true,
|
||||
chartPadding: { top: 0, right: 50, bottom: 0, left: 0 },
|
||||
},
|
||||
responsiveOptions: [
|
||||
['screen and (max-width: 640px) and (min-width: 381px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}],
|
||||
['screen and (max-width: 380px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 3 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}]
|
||||
],
|
||||
};
|
||||
// Line Chart 3 Ends
|
||||
|
||||
// Scatter Line Chart Starts
|
||||
this.scatterlineChart = {
|
||||
type: 'Line',
|
||||
data: Chartdata['ScatterLine'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
height: '300px',
|
||||
axisX: { showGrid: false }, axisY: {
|
||||
scaleMinSpace: 30,
|
||||
}, fullWidth: true,
|
||||
},
|
||||
responsiveOptions: [
|
||||
['screen and (max-width: 640px) and (min-width: 381px) and (min-hight: 300px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}],
|
||||
['screen and (max-width: 380px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 3 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}]
|
||||
],
|
||||
};
|
||||
// Scatter Line Chart Ends
|
||||
|
||||
// Scatter Chart Starts
|
||||
this.scatterChart = {
|
||||
type: 'Line',
|
||||
data: Chartdata['Scatter'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
height: '300px',
|
||||
showLine: false,
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value: number, index: number): string {
|
||||
return index % 13 === 0 ? `W${value}` : null;
|
||||
},
|
||||
showGrid: false
|
||||
},
|
||||
axisY: {
|
||||
scaleMinSpace: 30,
|
||||
}
|
||||
},
|
||||
responsiveOptions: [
|
||||
[
|
||||
'screen and (min-width: 640px)',
|
||||
{
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value: number, index: number): string {
|
||||
return index % 4 === 0 ? `W${value}` : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
};
|
||||
// Scatter Chart Ends
|
||||
|
||||
// Bi-polar Line Chart Starts
|
||||
this.biPolarLineChart = {
|
||||
type: 'Line',
|
||||
data: Chartdata['Bi-PolarLine'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
height: '350px',
|
||||
showArea: true,
|
||||
showLine: false,
|
||||
showPoint: false,
|
||||
fullWidth: true,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
offset: 100,
|
||||
labelInterpolationFnc: function (value: number, index: number): number {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
},
|
||||
axisY: {
|
||||
scaleMinSpace: 30,
|
||||
}
|
||||
}
|
||||
};
|
||||
// Bi-polar Line Chart Ends
|
||||
|
||||
// Bar Chart Starts
|
||||
this.barChart = {
|
||||
type: 'Bar',
|
||||
data: Chartdata['Bar'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
height: '350px',
|
||||
seriesBarDistance: 21,
|
||||
axisX: {
|
||||
showGrid: false, offset: 100
|
||||
},
|
||||
axisY: {
|
||||
scaleMinSpace: 30,
|
||||
}
|
||||
},
|
||||
};
|
||||
// Bar Chart Ends
|
||||
|
||||
// Distributed Series Bar Chart Starts
|
||||
this.distributedSeriesBarChart = {
|
||||
type: 'Bar',
|
||||
data: Chartdata['DistributedSeries'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
height: '300px',
|
||||
showGrid: false,
|
||||
distributeSeries: true,
|
||||
axisY: {
|
||||
scaleMinSpace: 30,
|
||||
}
|
||||
},
|
||||
};
|
||||
// Distributed Series Bar Chart Ends
|
||||
|
||||
// Donut Chart 1 Starts
|
||||
this.donutChart1 = {
|
||||
type: 'Pie',
|
||||
data: Chartdata['donut'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
height: '400px',
|
||||
donut: true,
|
||||
donutWidth: 60,
|
||||
startAngle: 270,
|
||||
total: 200,
|
||||
showLabel: true,
|
||||
},
|
||||
};
|
||||
// Donut Chart 1 Ends
|
||||
|
||||
// Donut Chart 2 Starts
|
||||
this.donutChart2 = {
|
||||
type: 'Pie',
|
||||
data: Chartdata['donut'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
height: '400px',
|
||||
donut: true,
|
||||
showLabel: true,
|
||||
labelDirection: 'implode',
|
||||
},
|
||||
};
|
||||
// Donut Chart 2 Ends
|
||||
}
|
||||
|
||||
/**
|
||||
* OnInit
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.breadcrumb = {
|
||||
'mainlabel': 'Chartist Charts',
|
||||
'links': [
|
||||
{
|
||||
'name': 'Home',
|
||||
'isLink': true,
|
||||
'link': '/dashboard/sales'
|
||||
},
|
||||
{
|
||||
'name': 'Chartist',
|
||||
'isLink': true,
|
||||
'link': '#'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.chartApiservice.getChartistData().subscribe(Response => {
|
||||
this.data = Response;
|
||||
this.getlineArea();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload card
|
||||
*/
|
||||
reloadLineWithAreaChartOne() {
|
||||
this.blockUILineWithAreaChartOne.start('Loading..');
|
||||
|
||||
setTimeout(() => {
|
||||
this.blockUILineWithAreaChartOne.stop();
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload card
|
||||
*/
|
||||
reloadLineWithAreaChartTwo() {
|
||||
this.blockUILineWithAreaChartTwo.start('Loading..');
|
||||
|
||||
setTimeout(() => {
|
||||
this.blockUILineWithAreaChartTwo.stop();
|
||||
}, 2500);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { NgchartistModule } from './ngchartist.module';
|
||||
|
||||
describe('NgchartistModule', () => {
|
||||
let ngchartistModule: NgchartistModule;
|
||||
|
||||
beforeEach(() => {
|
||||
ngchartistModule = new NgchartistModule();
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
expect(ngchartistModule).toBeTruthy();
|
||||
});
|
||||
});
|
||||
30
src/app/content/charts-maps/ngchartist/ngchartist.module.ts
Normal file
30
src/app/content/charts-maps/ngchartist/ngchartist.module.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CardModule } from '../../partials/general/card/card.module';
|
||||
import { ChartistModule } from 'ng-chartist';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { LinechartsComponent } from './linecharts/linecharts.component';
|
||||
import { BreadcrumbModule } from 'src/app/_layout/breadcrumb/breadcrumb.module';
|
||||
import { BlockTemplateComponent } from 'src/app/_layout/blockui/block-template.component';
|
||||
import { BlockUIModule } from 'ng-block-ui';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
CardModule,
|
||||
BreadcrumbModule,
|
||||
ChartistModule,
|
||||
BlockUIModule.forRoot({
|
||||
template: BlockTemplateComponent
|
||||
}),
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'linecharts',
|
||||
component: LinechartsComponent
|
||||
},
|
||||
]),
|
||||
],
|
||||
|
||||
declarations: [LinechartsComponent]
|
||||
})
|
||||
export class NgchartistModule { }
|
||||
13
src/app/content/dashboard/dashboard.module.spec.ts
Normal file
13
src/app/content/dashboard/dashboard.module.spec.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { DashboardModule } from './dashboard.module';
|
||||
|
||||
describe('DashboardModule', () => {
|
||||
let dashboardModule: DashboardModule;
|
||||
|
||||
beforeEach(() => {
|
||||
dashboardModule = new DashboardModule();
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
expect(dashboardModule).toBeTruthy();
|
||||
});
|
||||
});
|
||||
51
src/app/content/dashboard/dashboard.module.ts
Normal file
51
src/app/content/dashboard/dashboard.module.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { EcommerceComponent } from './ecommerce/ecommerce.component';
|
||||
import { ChartistModule } from 'ng-chartist';
|
||||
import { NgxDatatableModule } from '@swimlane/ngx-datatable';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { CardModule } from '../partials/general/card/card.module';
|
||||
import { NgChartsModule } from 'ng2-charts';
|
||||
import { SalesComponent } from './sales/sales.component';
|
||||
import { BlockUIModule } from 'ng-block-ui';
|
||||
import { BlockTemplateComponent } from '../../_layout/blockui/block-template.component';
|
||||
import { MatchHeightModule } from '../partials/general/match-height/match-height.module';
|
||||
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
|
||||
import { HospitalComponent } from './hospital/hospital.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
ChartistModule,
|
||||
FormsModule,
|
||||
NgChartsModule,
|
||||
CardModule,
|
||||
MatchHeightModule,
|
||||
NgxDatatableModule,
|
||||
PerfectScrollbarModule,
|
||||
NgbModule,
|
||||
BlockUIModule.forRoot({
|
||||
template: BlockTemplateComponent
|
||||
}),
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'ecommerce',
|
||||
component: EcommerceComponent
|
||||
},
|
||||
{
|
||||
path: 'sales',
|
||||
component: SalesComponent
|
||||
},
|
||||
{
|
||||
path: 'hospital',
|
||||
component: HospitalComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
declarations: [EcommerceComponent, SalesComponent, HospitalComponent],
|
||||
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class DashboardModule { }
|
||||
414
src/app/content/dashboard/ecommerce/ecommerce.component.css
Normal file
414
src/app/content/dashboard/ecommerce/ecommerce.component.css
Normal file
@@ -0,0 +1,414 @@
|
||||
.avatar-xs {
|
||||
width: 24px !important;
|
||||
margin-right: 5px !important;
|
||||
}
|
||||
|
||||
.btn_set_padding {
|
||||
padding: 0% !important;
|
||||
}
|
||||
|
||||
.chart_body_padding {
|
||||
padding: 2rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .scoreLineShadow {
|
||||
-webkit-filter: drop-shadow(0px 20px 11px rgba(0, 0, 0, 0.5)) !important;
|
||||
filter: drop-shadow(0px 20px 11px rgba(0, 0, 0, 0.5));
|
||||
}
|
||||
|
||||
:host ::ng-deep .ecommercesaleslineArea .ct-series-a .ct-point-circle {
|
||||
stroke-width: 5px;
|
||||
stroke: #ffffff;
|
||||
fill: #1e9ff2;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ecommercesaleslineArea .ct-series-b .ct-point-circle {
|
||||
stroke-width: 5px;
|
||||
stroke: #ffffff;
|
||||
fill: #58e0cd;
|
||||
;
|
||||
}
|
||||
|
||||
:host ::ng-deep .media {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
|
||||
:host ::ng-deep .position-relative {
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-series-b .ct-bar,
|
||||
.ct-series-b .ct-slice-donut {
|
||||
stroke: #beb6b6;
|
||||
}
|
||||
|
||||
:host ::ng-deep .progress:last-child {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .areaChartLegend .ct-series-a .ct-line {
|
||||
stroke: url(#gradient2);
|
||||
stroke-width: 5px;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
|
||||
:host ::ng-deep .areaChartLegend .ct-series-a .ct-area {
|
||||
fill: #ffffff;
|
||||
}
|
||||
|
||||
:host ::ng-deep .areaChartLegend .ct-series-a .ct-line {
|
||||
stroke: #3da2ea;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ecommercesaleslineArea .ct-series-a .ct-area {
|
||||
fill: #4105f9f5;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ecommercesaleslineArea .ct-series-b .ct-area {
|
||||
fill: #03f7b2fa;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ecommercesaleslineArea .ct-series-b .ct-line {
|
||||
stroke: #58e0cd;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ecommercesaleslineArea .ct-series-a .ct-line {
|
||||
stroke: #1e9ff2;
|
||||
}
|
||||
|
||||
:host ::ng-deep .barchart .ct-series-a .ct-bar {
|
||||
stroke: #ff394f !important;
|
||||
stroke-width: 7px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .pull-up {
|
||||
-webkit-transition: all 0.25s ease;
|
||||
-o-transition: all 0.25s ease;
|
||||
-moz-transition: all 0.25s ease;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
:host ::ng-deep .chart-info {
|
||||
margin-top: 73px !important;
|
||||
}
|
||||
|
||||
.mb-3,
|
||||
.my-3 {
|
||||
margin-bottom: -4rem !important;
|
||||
}
|
||||
|
||||
.mb-2,
|
||||
.my-2 {
|
||||
margin-bottom: -4.5rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut .ct-done .ct-slice-donut {
|
||||
stroke: #28d094;
|
||||
stroke-width: 24px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut .ct-progress .ct-slice-donut {
|
||||
stroke: #ff4558;
|
||||
stroke-width: 16px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut .ct-outstanding .ct-slice-donut {
|
||||
stroke: #ff7d4d;
|
||||
stroke-width: 8px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut .ct-started .ct-slice-donut {
|
||||
stroke: #666ECC;
|
||||
stroke-width: 32px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut .ct-label {
|
||||
text-anchor: middle;
|
||||
font-size: 20px;
|
||||
fill: #868e96;
|
||||
}
|
||||
|
||||
:host ::ng-deep .Barchart {
|
||||
display: block;
|
||||
margin-left: -100px;
|
||||
margin-bottom: -60px;
|
||||
margin-top: -45px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .Barchart .ct-label {
|
||||
font-size: 0.75rem;
|
||||
line-height: 15;
|
||||
}
|
||||
|
||||
.p {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: -1.5rem;
|
||||
font-size: large;
|
||||
color: #6c757d !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .text-center .p {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: -1.2rem;
|
||||
}
|
||||
|
||||
:host ::ng-deep .height-300 {
|
||||
height: 250px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .gradient-blackberry {
|
||||
background-image: linear-gradient(45deg, #b9e2fa, #b9e2fa) !important;
|
||||
margin-left: 48px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .gradient-mint {
|
||||
background-image: linear-gradient(45deg, #ff9ba6, #ff9ba6);
|
||||
margin-left: 48px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .gradient-info {
|
||||
background-image: linear-gradient(45deg, #6ef9d6, #6ef9d6);
|
||||
margin-left: 48px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .extraPadding7 {
|
||||
padding: 0.7rem;
|
||||
}
|
||||
|
||||
:host ::ng-deep .avatar-md {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .square {
|
||||
border-radius: 0% !important;
|
||||
height: auto;
|
||||
border: 2px solid #FFF !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ps--active-x>.ps__rail-x {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .border-top-0 {
|
||||
padding: 1.25rem 2rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .btn-danger {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .progress:last-child {
|
||||
margin-bottom: 0rem;
|
||||
}
|
||||
|
||||
|
||||
:host ::ng-deep .btn.active {
|
||||
outline: none;
|
||||
-webkit-box-shadow: none !important;
|
||||
box-shadow: none !important;
|
||||
background-color: #2196F3 !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.btn {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
.btn_dropdown {
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .text_color {
|
||||
color: #0c84d1;
|
||||
}
|
||||
|
||||
:host ::ng-deep .progress {
|
||||
box-shadow: 6px 6px 14px -1px rgba(62, 57, 107, .2);
|
||||
margin-top: 1rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .btn-group {
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
@media only screen and (max-width:767px) {
|
||||
.btn-group {
|
||||
position: relative !important;
|
||||
}
|
||||
}
|
||||
|
||||
:host ::ng-deep .text-muted {
|
||||
color: #6b6f82 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .mb-3,
|
||||
.my-3 {
|
||||
margin-bottom: 1.5rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .media {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
:host ::ng-deep .height-350 {
|
||||
height: 250px !important;
|
||||
margin-left: 18%;
|
||||
margin-bottom: 55px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .card-text:last-child {
|
||||
margin-bottom: 0;
|
||||
height: 430px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .mb-3 {
|
||||
margin-bottom: 1.1rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .chart-info .p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .order-tbl_change th,
|
||||
.order-tbl_change td {
|
||||
padding-right: 0.8rem;
|
||||
}
|
||||
|
||||
:host ::ng-deep svg.ct-chart-bar {
|
||||
width: 100% !important;
|
||||
padding-top: 5%;
|
||||
}
|
||||
|
||||
:host ::ng-deep #donut-dashboard-chart {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
:host ::ng-deep .pr_stats {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
:host ::ng-deep .height-300 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:host ::ng-deep .alert_basics_charrt {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:host ::ng-deep .card-header .heading-elements a.btn {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
|
||||
:host ::ng-deep .row_padding {
|
||||
padding: 1.25rem 2rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .border_bottom {
|
||||
margin-bottom: 0rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .top_space {
|
||||
padding-top: 5% !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .border_top {
|
||||
border-top: none !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .card-footer {
|
||||
padding: 2rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-chart-bar .ct-label.ct-horizontal.ct-end {
|
||||
text-anchor: middle;
|
||||
font-family: sans-serif;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-chart-bar .ct-label.ct-vertical.ct-start {
|
||||
text-anchor: middle;
|
||||
font-family: sans-serif;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
:host ::ng-deep .block-ui-wrapper {
|
||||
background: rgba(255, 249, 249, 0.5) !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .chartist-tooltip.bar_tooltip {
|
||||
border-radius: 10px;
|
||||
padding: 18px;
|
||||
color: rgb(29, 28, 28);
|
||||
height: 60px;
|
||||
width: 80px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border: solid 2px rgba(230, 230, 230, 0.9);
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
:host ::ng-deep .chartist-tooltip.donut_tooltip {
|
||||
border-radius: 10px;
|
||||
padding: 2px;
|
||||
color: rgb(29, 28, 28);
|
||||
height: 60px;
|
||||
width: 90px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border: solid 2px rgba(230, 230, 230, 0.9);
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
top: 16.906px;
|
||||
}
|
||||
|
||||
|
||||
:host ::ng-deep .chartist-tooltip.tooltip-show {
|
||||
opacity: 0.6 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .chartist-tooltip.bar_tooltip:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-left: -15px;
|
||||
border: 15px solid transparent;
|
||||
border-top-color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
:host ::ng-deep .chartist-tooltip.donut_tooltip:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-left: -15px;
|
||||
border: 15px solid transparent;
|
||||
border-top-color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
:host ::ng-deep .tab-content > .tab-pane,
|
||||
.pill-content > .pill-pane {
|
||||
display: block;
|
||||
height: 0;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
:host ::ng-deep .tab-content > .active,
|
||||
.pill-content > .active {
|
||||
height: auto;
|
||||
}
|
||||
510
src/app/content/dashboard/ecommerce/ecommerce.component.html
Normal file
510
src/app/content/dashboard/ecommerce/ecommerce.component.html
Normal file
@@ -0,0 +1,510 @@
|
||||
<div class="app-content content">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<!-- eCommerce statistic -->
|
||||
<div class="row">
|
||||
<div class="col-xl-3 col-lg-6 col-12">
|
||||
<div class="card pull-up">
|
||||
<div class="card-content">
|
||||
<div class="card-body card_padding">
|
||||
<div class="media d-flex">
|
||||
<div class="media-body text-left">
|
||||
<h3 class="info">850</h3>
|
||||
<h6>Products Sold</h6>
|
||||
</div>
|
||||
<div>
|
||||
<i class="icon-basket-loaded info font-large-2 float-right"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-0 mt-1">
|
||||
<ngb-progressbar height="7px" width="100%" type="gradient-x-info" [value]="80"></ngb-progressbar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-lg-6 col-12">
|
||||
<div class="card pull-up">
|
||||
<div class="card-content">
|
||||
<div class="card-body card_padding">
|
||||
<div class="media d-flex">
|
||||
<div class="media-body text-left">
|
||||
<h3 class="warning">$748</h3>
|
||||
<h6>Net Profit</h6>
|
||||
</div>
|
||||
<div>
|
||||
<i class="icon-pie-chart warning font-large-2 float-right"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-0 mt-1">
|
||||
<ngb-progressbar height="7px" width="100%" type="gradient-x-warning" [value]="65">
|
||||
</ngb-progressbar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xl-3 col-lg-6 col-12">
|
||||
<div class="card pull-up">
|
||||
<div class="card-content">
|
||||
<div class="card-body card_padding">
|
||||
<div class="media d-flex">
|
||||
<div class="media-body text-left">
|
||||
<h3 class="success">146</h3>
|
||||
<h6>New Customers</h6>
|
||||
</div>
|
||||
<div>
|
||||
<i class="icon-user-follow success font-large-2 float-right"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-0 mt-1">
|
||||
<ngb-progressbar height="7px" width="100%" type="gradient-x-success" [value]="75"></ngb-progressbar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-lg-6 col-12">
|
||||
<div class="card pull-up">
|
||||
<div class="card-content">
|
||||
<div class="card-body card_padding">
|
||||
<div class="media d-flex">
|
||||
<div class="media-body text-left">
|
||||
<h3 class="danger">99.89 %</h3>
|
||||
<h6>Customer Satisfaction</h6>
|
||||
</div>
|
||||
<div>
|
||||
<i class="icon-heart danger font-large-2 float-right"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-0 mt-1">
|
||||
<ngb-progressbar height="7px" width="100%" type="gradient-x-danger" [value]="85"></ngb-progressbar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--/ eCommerce statistic -->
|
||||
|
||||
<!-- Products sell and New Orders -->
|
||||
<div class="row">
|
||||
<div class="col-xl-8 col-12">
|
||||
<div class="card card-shadow">
|
||||
<div class="card-header card-header-transparent py-20">
|
||||
<div class="btn-group dropdown">
|
||||
<a [routerLink]="" ngbDropdown class="d-inline-block">
|
||||
<button class="btn btn_dropdown btn_set_padding btn-dropdown-toggle" id="dropdownBasic1"
|
||||
ngbDropdownToggle>PRODUCTS SALES</button>
|
||||
<div ngbDropdownMenu aria-labelledby="dropdownBasic1">
|
||||
<button class="dropdown-item">Sales</button>
|
||||
<button class="dropdown-item">Total Sales</button>
|
||||
<button class="dropdown-item">Profit</button>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<ul ngbNav #nav="ngbNav" class="justify-content-end nav nav-pills">
|
||||
<li [ngbNavItem]="1">
|
||||
<a ngbNavLink>Day</a>
|
||||
<ng-template ngbNavContent>
|
||||
<div class="areaChartLegend scoreLineShadow">
|
||||
<x-chartist *ngIf="lineAreaDay" [data]="lineAreaDay.data" [type]="lineAreaDay.type"
|
||||
[options]="lineAreaDay.options" [responsiveOptions]="lineAreaDay.responsiveOptions"
|
||||
[events]="lineAreaDay.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</ng-template>
|
||||
</li>
|
||||
<li [ngbNavItem]="2">
|
||||
<a ngbNavLink>Week</a>
|
||||
<ng-template ngbNavContent>
|
||||
<div class="areaChartLegend scoreLineShadow">
|
||||
<x-chartist *ngIf="lineAreaWeek" [data]="lineAreaWeek.data" [type]="lineAreaWeek.type"
|
||||
[options]="lineAreaWeek.options" [responsiveOptions]="lineAreaWeek.responsiveOptions"
|
||||
[events]="lineAreaWeek.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</ng-template>
|
||||
</li>
|
||||
<li [ngbNavItem]="3">
|
||||
<a ngbNavLink>Month</a>
|
||||
<ng-template ngbNavContent>
|
||||
<div class="areaChartLegend scoreLineShadow">
|
||||
<x-chartist *ngIf="lineAreaMonth" [data]="lineAreaMonth.data" [type]="lineAreaMonth.type"
|
||||
[options]="lineAreaMonth.options" [responsiveOptions]="lineAreaMonth.responsiveOptions"
|
||||
[events]="lineAreaMonth.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</ng-template>
|
||||
</li>
|
||||
</ul>
|
||||
<div [ngbNavOutlet]="nav"></div>
|
||||
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-lg-12" *blockUI="'newOrders'; message: 'Loading'">
|
||||
<m-card [options]="options" (reloadFunction)="reloadNewOrders($event)">
|
||||
<ng-container mCardHeaderTitle>
|
||||
New Orders
|
||||
</ng-container>
|
||||
<ng-container mCardContent>
|
||||
<div id="new-orders" class="media-list position-relative">
|
||||
<div class="table-responsive">
|
||||
<table id="new-orders-table" class="table table-hover table-xl mb-0 order-tbl_change">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="border-top-0">Product</th>
|
||||
<th class="border-top-0">Customers</th>
|
||||
<th class="border-top-0">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-truncate">iPhone X</td>
|
||||
<td class="text-truncate p-1">
|
||||
<ul class="list-unstyled users-list m-0">
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom" data-original-title="John Doe"
|
||||
class="avatar avatar-sm pull-up">
|
||||
<img class="media-object rounded-circle"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-19.png" alt="Avatar">
|
||||
</li>
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom"
|
||||
data-original-title="Katherine Nichols" class="avatar avatar-sm pull-up">
|
||||
<img class="media-object rounded-circle"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-18.png" alt="Avatar">
|
||||
</li>
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom" data-original-title="Joseph Weaver"
|
||||
class="avatar avatar-sm pull-up">
|
||||
<img class="media-object rounded-circle"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-17.png" alt="Avatar">
|
||||
</li>
|
||||
<li class="avatar avatar-sm">
|
||||
<span class="badge badge-info">+4 more</span>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td class="text-truncate">$8999</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-truncate">Pixel 2</td>
|
||||
<td class="text-truncate p-1">
|
||||
<ul class="list-unstyled users-list m-0">
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom" data-original-title="Alice Scott"
|
||||
class="avatar avatar-sm pull-up">
|
||||
<img class="media-object rounded-circle"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-16.png" alt="Avatar">
|
||||
</li>
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom" data-original-title="Charles Miller"
|
||||
class="avatar avatar-sm pull-up">
|
||||
<img class="media-object rounded-circle"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-15.png" alt="Avatar">
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td class="text-truncate">$5550</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-truncate">OnePlus</td>
|
||||
<td class="text-truncate p-1">
|
||||
<ul class="list-unstyled users-list m-0">
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom" data-original-title="Christine Ramos"
|
||||
class="avatar avatar-sm pull-up">
|
||||
<img class="media-object rounded-circle"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-11.png" alt="Avatar">
|
||||
</li>
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom" data-original-title="Thomas Brewer"
|
||||
class="avatar avatar-sm pull-up">
|
||||
<img class="media-object rounded-circle"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-10.png" alt="Avatar">
|
||||
</li>
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom" data-original-title="Alice Chapman"
|
||||
class="avatar avatar-sm pull-up">
|
||||
<img class="media-object rounded-circle"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-9.png" alt="Avatar">
|
||||
</li>
|
||||
<li class="avatar avatar-sm">
|
||||
<span class="badge badge-info">+3 more</span>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td class="text-truncate">$9000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-truncate">Galaxy</td>
|
||||
<td class="text-truncate p-1">
|
||||
<ul class="list-unstyled users-list m-0">
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom" data-original-title="Ryan Schneider"
|
||||
class="avatar avatar-sm pull-up">
|
||||
<img class="media-object rounded-circle"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-14.png" alt="Avatar">
|
||||
</li>
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom" data-original-title="Tiffany Oliver"
|
||||
class="avatar avatar-sm pull-up">
|
||||
<img class="media-object rounded-circle"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-13.png" alt="Avatar">
|
||||
</li>
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom" data-original-title="Joan Reid"
|
||||
class="avatar avatar-sm pull-up">
|
||||
<img class="media-object rounded-circle"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-12.png" alt="Avatar">
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td class="text-truncate">$7500</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-truncate">Moto Z2</td>
|
||||
<td class="text-truncate p-1">
|
||||
<ul class="list-unstyled users-list m-0">
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom" data-original-title="Kimberly Simmons"
|
||||
class="avatar avatar-sm pull-up">
|
||||
<img class="media-object rounded-circle"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-8.png" alt="Avatar">
|
||||
</li>
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom" data-original-title="Willie Torres"
|
||||
class="avatar avatar-sm pull-up">
|
||||
<img class="media-object rounded-circle"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-7.png" alt="Avatar">
|
||||
</li>
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom" data-original-title="Rebecca Jones"
|
||||
class="avatar avatar-sm pull-up">
|
||||
<img class="media-object rounded-circle"
|
||||
src="../../../../assets/images/portrait/small/avatar-s-6.png" alt="Avatar">
|
||||
</li>
|
||||
<li class="avatar avatar-sm">
|
||||
<span class="badge badge-info">+1 more</span>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td class="text-truncate">$8500</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
<!--/ Products sell and New Orders -->
|
||||
|
||||
<!-- Recent Transactions -->
|
||||
<div class="row match_height">
|
||||
<div id="recent-transactions" class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Recent Transactions</h4>
|
||||
|
||||
<div class="heading-elements invoice">
|
||||
<ul class="list-inline mb-0">
|
||||
<li><a [routerLink]="" class="btn btn-sm btn-danger box-shadow-2 round btn-min-width pull-right"
|
||||
(click)="rotueInvoice()">Invoice Summary</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="table-responsive" fxFlex="auto" [perfectScrollbar]="config">
|
||||
<table class="table table-hover table-xl border_bottom">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="border-top-0">Status</th>
|
||||
<th scope="col" class="border-top-0">Invoice#</th>
|
||||
<th scope="col" class="border-top-0">Customer Name</th>
|
||||
<th scope="col" class="border-top-0">Products</th>
|
||||
<th scope="col" class="border-top-0">Categories</th>
|
||||
<th scope="col" class="border-top-0">Shipping</th>
|
||||
<th scope="col" class="border-top-0">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let row of rows">
|
||||
<td class="text-truncate row_padding">
|
||||
<i class="la la-dot-circle-o {{row.statusSymbol}} font-medium-1 mr-1"></i>
|
||||
{{row.status}}
|
||||
</td>
|
||||
<td class="text-truncate row_padding">
|
||||
<a [routerLink]="">{{ row.invoice }}</a>
|
||||
</td>
|
||||
<td class="text-truncate row_padding">
|
||||
<span class="avatar avatar-xs"><img class="box-shadow-2 image-name-space"
|
||||
[src]="row.image"></span><span>{{row.name}}</span>
|
||||
</td>
|
||||
<td class="text-truncate row_padding">
|
||||
<span><img class="media-object avatar avatar-md avatar-online media-left pull-up square"
|
||||
[src]="row.categories"></span>
|
||||
</td>
|
||||
<td class="text-truncate row_padding">
|
||||
<span>
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-outline-{{row.type}} round">{{row.buttonname}}</button>
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-truncate row_padding">
|
||||
<ngb-progressbar height="7px" type="{{row.progressColor}}" [value]=row.value>
|
||||
</ngb-progressbar>
|
||||
</td>
|
||||
<td class="text-truncate row_padding">{{ row.amount }} </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--/ Recent Transactions -->
|
||||
|
||||
<!--Recent Orders & Monthly Sales -->
|
||||
<div class="row match_height">
|
||||
<div class="col-xl-12 col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-content top_space">
|
||||
<div id="cost-revenue" class="ecommercesaleslineArea position-relative">
|
||||
<x-chartist *ngIf="ecommercesaleslineArea" [data]="ecommercesaleslineArea.data"
|
||||
[type]="ecommercesaleslineArea.type" [options]="ecommercesaleslineArea.options"
|
||||
[responsiveOptions]="ecommercesaleslineArea.responsiveOptions"
|
||||
[events]="ecommercesaleslineArea.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer border_top">
|
||||
<div class="row mt-1">
|
||||
<div class="col-3 text-center">
|
||||
<h6 class="text-muted">Total Products</h6>
|
||||
<h2 class="block font-weight-normal">18.6 k</h2>
|
||||
<div class="TotalProducts">
|
||||
<ngb-progressbar height="7px" type="gradient-x-info" [value]="70"></ngb-progressbar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3 text-center">
|
||||
<h6 class="text-muted">Total Sales</h6>
|
||||
<h2 class="block font-weight-normal">64.5 M</h2>
|
||||
<div class="TotalSales">
|
||||
<ngb-progressbar height="7px" type="gradient-x-warning" [value]="60"></ngb-progressbar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3 text-center">
|
||||
<h6 class="text-muted">Total Cost</h6>
|
||||
<h2 class="block font-weight-normal">24.3 B</h2>
|
||||
<div class="TotalCost">
|
||||
<ngb-progressbar height="7px" type="gradient-x-danger" [value]="40"></ngb-progressbar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3 text-center">
|
||||
<h6 class="text-muted">Total Revenue</h6>
|
||||
<h2 class="block font-weight-normal">36.7 M</h2>
|
||||
<div class="TotalRevenue">
|
||||
<ngb-progressbar height="7px" type="gradient-x-success" [value]="90"></ngb-progressbar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--/Recent Orders & Monthly Sales -->
|
||||
<div class="row" matchHeight="card">
|
||||
<div class="col-xl-4 col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Basic Card</h4>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<img class="img-fluid" src="../../../../assets/images/carousel/05.jpg" alt="Card image cap">
|
||||
<div class="card-body">
|
||||
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the
|
||||
card's content.</p>
|
||||
<a [routerLink]="" class="card-link">Card link</a>
|
||||
<a [routerLink]="" class="card-link">Another link</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer border-top-blue-grey border-top-lighten-5 text-muted">
|
||||
<span class="float-left">3 hours ago</span>
|
||||
<span class="float-right">
|
||||
<a [routerLink]="" class="card-link">Read More <i class="fa fa-angle-right"></i></a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Project Stats</h4>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<p class="font-medium-2 text-muted text-center dountchartheader">Project Tasks</p>
|
||||
<div id="donut-dashboard-chart" class="donut">
|
||||
<x-chartist *ngIf="donutChart" class="pr_stats" [data]="donutChart.data" [type]="donutChart.type"
|
||||
[options]="donutChart.options" [responsiveOptions]="donutChart.responsiveOptions"
|
||||
[events]="donutChart.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<div class="col Started">
|
||||
<span class="mb-1 text-muted cardtext d-block">23% - Done</span>
|
||||
<div>
|
||||
<ngb-progressbar height="7px" type="success" [value]="23"></ngb-progressbar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col Progress">
|
||||
<span class="mb-1 text-muted cardtext d-block">14% - In Progress</span>
|
||||
<div>
|
||||
<ngb-progressbar height="7px" type="danger" [value]="14"></ngb-progressbar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col Remaining">
|
||||
<span class="mb-1 text-muted cardtext d-block">35% - Remaining</span>
|
||||
<div>
|
||||
<ngb-progressbar height="7px" type="warning" [value]="35"></ngb-progressbar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col Done">
|
||||
<span class="mb-1 text-muted cardtext d-block">28% - Started</span>
|
||||
<div>
|
||||
<ngb-progressbar height="7px" type="primary" [value]="28"></ngb-progressbar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card-body sales-growth-chart">
|
||||
<div id="monthly-sales" class=""></div>
|
||||
<div class="barchart">
|
||||
<x-chartist *ngIf="barChart" [data]="barChart.data" [type]="barChart.type"
|
||||
[options]="barChart.options" [responsiveOptions]="barChart.responsiveOptions"
|
||||
[events]="barChart.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<div class="chart-title mb-1 text-center">
|
||||
<h6>Total monthly Sales.</h6>
|
||||
</div>
|
||||
<div class="chart-stats text-center">
|
||||
<a [routerLink]="" class="btn btn-sm btn-danger box-shadow-2 mr-1">Statistics <i
|
||||
class="feather ft-bar-chart" (click)=" reLoad()"></i></a> <span class="text-muted">for the last
|
||||
year.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--/ Basic Horizontal Timeline -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ////////////////////////////////////////////////////////////////////////////-->
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { EcommerceComponent } from './ecommerce.component';
|
||||
|
||||
describe('EcommerceComponent', () => {
|
||||
let component: EcommerceComponent;
|
||||
let fixture: ComponentFixture<EcommerceComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ EcommerceComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(EcommerceComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
401
src/app/content/dashboard/ecommerce/ecommerce.component.ts
Normal file
401
src/app/content/dashboard/ecommerce/ecommerce.component.ts
Normal file
@@ -0,0 +1,401 @@
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import * as Chartist from 'chartist';
|
||||
import { DatatableComponent } from '@swimlane/ngx-datatable';
|
||||
import { ChartEvent, ChartType } from 'ng-chartist';
|
||||
import 'chartist-plugin-tooltips';
|
||||
import { BlockUI, NgBlockUI } from 'ng-block-ui';
|
||||
import { PerfectScrollbarDirective, PerfectScrollbarComponent, PerfectScrollbarConfigInterface } from 'ngx-perfect-scrollbar';
|
||||
import { ChartApiService } from '../../../_services/chart.api';
|
||||
import { TableApiService } from '../../../_services/table-api.service';
|
||||
import { Router } from '@angular/router';
|
||||
export interface Chart {
|
||||
type: ChartType;
|
||||
data: Chartist.IChartistData;
|
||||
options?: any;
|
||||
responsiveOptions?: any;
|
||||
events?: ChartEvent;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-ecommerce',
|
||||
templateUrl: './ecommerce.component.html',
|
||||
styleUrls: ['./ecommerce.component.css']
|
||||
})
|
||||
export class EcommerceComponent implements OnInit {
|
||||
|
||||
@BlockUI('newOrders') blockUINewOrders: NgBlockUI;
|
||||
public config: PerfectScrollbarConfigInterface = { wheelPropagation: true };
|
||||
|
||||
@ViewChild(PerfectScrollbarComponent) componentRef?: PerfectScrollbarComponent;
|
||||
@ViewChild(PerfectScrollbarDirective) directiveRef?: PerfectScrollbarDirective;
|
||||
|
||||
currentJustify = 'end';
|
||||
loadingIndicator = true;
|
||||
options = {
|
||||
close: false,
|
||||
expand: false,
|
||||
minimize: false,
|
||||
reload: true
|
||||
};
|
||||
ChartistData: any;
|
||||
datatableData: any;
|
||||
lineAreaDay: any;
|
||||
lineAreaWeek: any;
|
||||
lineAreaMonth: any;
|
||||
ecommercesaleslineArea: any;
|
||||
donutChart: any;
|
||||
barChart: any;
|
||||
rows: any;
|
||||
@ViewChild(DatatableComponent, { static: true }) table: DatatableComponent;
|
||||
Daygraph = true;
|
||||
Weekgraph = false;
|
||||
Monthgraph = false;
|
||||
|
||||
constructor(private chartApiservice: ChartApiService,
|
||||
private tableApiservice: TableApiService,
|
||||
private route: Router) { }
|
||||
getTabledata() {
|
||||
this.rows = this.datatableData.rows;
|
||||
}
|
||||
getlineArea() {
|
||||
const ChartData = this.ChartistData;
|
||||
this.lineAreaDay = {
|
||||
type: 'Line',
|
||||
data: ChartData['lineArea'],
|
||||
options: {
|
||||
lineSmooth: Chartist.Interpolation.simple({
|
||||
divisor: 1.8
|
||||
}),
|
||||
fullwidth: true,
|
||||
height: '320px',
|
||||
low: 0,
|
||||
showArea: true,
|
||||
fullWidth: true,
|
||||
showPoint: false,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
},
|
||||
axisY: {
|
||||
low: 0,
|
||||
offset: 16,
|
||||
scaleMinSpace: 40,
|
||||
labelInterpolationFnc: function (value) {
|
||||
return value + 'K';
|
||||
},
|
||||
},
|
||||
},
|
||||
responsiveOptions: [
|
||||
['screen and (max-width: 640px) and (min-width: 200px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}],
|
||||
['screen and (max-width: 380px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 3 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}]
|
||||
],
|
||||
events: {
|
||||
created(data: any): void {
|
||||
const defs = data.svg.elem('defs');
|
||||
defs.elem('linearGradient', {
|
||||
id: 'gradient2',
|
||||
x1: 1,
|
||||
y1: 1,
|
||||
x2: 1,
|
||||
y2: 1
|
||||
}).elem('stop', {
|
||||
offset: 0,
|
||||
'stop-color': 'rgba(22, 141, 238, 1)'
|
||||
}).parent().elem('stop', {
|
||||
offset: 1,
|
||||
'stop-color': 'rgba(98, 188, 270, 11)'
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
this.lineAreaWeek = {
|
||||
type: 'Line',
|
||||
data: ChartData['lineAreaWeek'],
|
||||
|
||||
options: {
|
||||
lineSmooth: Chartist.Interpolation.simple({
|
||||
divisor: 2
|
||||
}),
|
||||
fullwidth: true,
|
||||
height: '320px',
|
||||
low: 0,
|
||||
showArea: true,
|
||||
fullWidth: true,
|
||||
showPoint: false,
|
||||
chartPadding: {
|
||||
top: 33,
|
||||
},
|
||||
axisX: {
|
||||
showGrid: false
|
||||
},
|
||||
axisY: {
|
||||
low: 0,
|
||||
scaleMinSpace: 40,
|
||||
labelInterpolationFnc: function (value) {
|
||||
return value + 'K';
|
||||
},
|
||||
offset: 20,
|
||||
},
|
||||
},
|
||||
responsiveOptions: [
|
||||
['screen and (max-width: 640px) and (min-width: 200px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}],
|
||||
['screen and (max-width: 380px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 3 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}]
|
||||
],
|
||||
events: {
|
||||
created(data: any): void {
|
||||
const defs = data.svg.elem('defs');
|
||||
defs.elem('linearGradient', {
|
||||
id: 'gradient2',
|
||||
x1: 0,
|
||||
y1: 0,
|
||||
x2: 1,
|
||||
y2: 0
|
||||
}).elem('stop', {
|
||||
offset: 0,
|
||||
'stop-color': 'rgba(22, 141, 238, 1)'
|
||||
}).parent().elem('stop', {
|
||||
offset: 1,
|
||||
'stop-color': 'rgba(98, 188, 246, 1)'
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
this.lineAreaMonth = {
|
||||
type: 'Line',
|
||||
data: ChartData['lineAreaMonth'],
|
||||
options: {
|
||||
lineSmooth: Chartist.Interpolation.simple({
|
||||
divisor: 2
|
||||
}),
|
||||
// low: 650,
|
||||
fullwidth: true,
|
||||
height: '320px',
|
||||
low: 0,
|
||||
chartPadding: {
|
||||
top: 30,
|
||||
left: 0,
|
||||
right: 25
|
||||
},
|
||||
showArea: true,
|
||||
fullWidth: true,
|
||||
showPoint: false,
|
||||
axisX: {
|
||||
showGrid: false
|
||||
},
|
||||
axisY: {
|
||||
low: 0,
|
||||
scaleMinSpace: 60,
|
||||
labelInterpolationFnc: function (value) {
|
||||
return value + 'K';
|
||||
},
|
||||
}
|
||||
|
||||
},
|
||||
responsiveOptions: [
|
||||
['screen and (max-width: 640px) and (min-width: 200px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}],
|
||||
['screen and (max-width: 380px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 3 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}]
|
||||
],
|
||||
events: {
|
||||
created(data: any): void {
|
||||
const defs = data.svg.elem('defs');
|
||||
defs.elem('linearGradient', {
|
||||
id: 'gradient2',
|
||||
x1: 0,
|
||||
y1: 0,
|
||||
x2: 1,
|
||||
y2: 0
|
||||
}).elem('stop', {
|
||||
offset: 0,
|
||||
'stop-color': 'rgba(22, 141, 238, 1)'
|
||||
}).parent().elem('stop', {
|
||||
offset: 1,
|
||||
'stop-color': 'rgba(98, 188, 246, 1)'
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.ecommercesaleslineArea = {
|
||||
type: 'Line',
|
||||
data: ChartData['lineArea2'],
|
||||
options: {
|
||||
height: '300px',
|
||||
low: 0,
|
||||
showArea: true,
|
||||
fullWidth: true,
|
||||
onlyInteger: true,
|
||||
axisX: {
|
||||
showGrid: false
|
||||
},
|
||||
axisY: {
|
||||
low: 0,
|
||||
scaleMinSpace: 40,
|
||||
showGrid: false
|
||||
},
|
||||
},
|
||||
responsiveOptions: [
|
||||
['screen and (max-width: 640px) and (min-width: 381px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}],
|
||||
['screen and (max-width: 380px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 3 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}]
|
||||
],
|
||||
events: {
|
||||
|
||||
draw(data: any): void {
|
||||
const circleRadius = 6;
|
||||
if (data.type === 'point') {
|
||||
const circle = new Chartist.Svg('circle', {
|
||||
cx: data.x,
|
||||
cy: data.y,
|
||||
r: circleRadius,
|
||||
class: 'ct-point-circle'
|
||||
});
|
||||
data.element.replace(circle);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Doughnut
|
||||
this.donutChart = {
|
||||
type: 'Pie',
|
||||
data: ChartData.donutDashboard,
|
||||
options: {
|
||||
width: '100%',
|
||||
height: '290px',
|
||||
donut: true,
|
||||
startAngle: 0,
|
||||
low: 0,
|
||||
high: 8,
|
||||
fullWidth: true,
|
||||
plugins: [
|
||||
Chartist.plugins.tooltip({
|
||||
appendToBody: false,
|
||||
class: 'donut_tooltip',
|
||||
})
|
||||
],
|
||||
labelInterpolationFnc: function (value) {
|
||||
const total = ChartData.donutDashboard.series.reduce(function (prev, series) {
|
||||
return prev + series.value;
|
||||
}, 0);
|
||||
return total + '%';
|
||||
}
|
||||
},
|
||||
events: {
|
||||
draw(data: any): void {
|
||||
if (data.type === 'label') {
|
||||
if (data.index === 0) {
|
||||
data.element.attr({
|
||||
dx: data.element.root().width() / 2,
|
||||
dy: data.element.root().height() / 2
|
||||
});
|
||||
} else {
|
||||
data.element.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////// End doughnutchart////////////////
|
||||
///////////////////// Start barchart////////////////
|
||||
this.barChart = {
|
||||
type: 'Bar',
|
||||
data: ChartData['Bar'],
|
||||
options: {
|
||||
fullwidth: true,
|
||||
height: '380px',
|
||||
seriesBarDistance: 21,
|
||||
chartPadding: {
|
||||
top: 0,
|
||||
},
|
||||
plugins: [
|
||||
Chartist.plugins.tooltip({
|
||||
appendToBody: false,
|
||||
class: 'bar_tooltip',
|
||||
})
|
||||
],
|
||||
axisX: {
|
||||
showLable: true,
|
||||
showGrid: false,
|
||||
offset: 60,
|
||||
labelInterpolationFnc: function (value) {
|
||||
return value.slice(0, 3);
|
||||
}
|
||||
},
|
||||
|
||||
axisY: {
|
||||
scaleMinSpace: 40,
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
///////////////////// End barchart////////////////
|
||||
ngOnInit() {
|
||||
this.chartApiservice.getEcommerceData().subscribe(Response => {
|
||||
this.ChartistData = Response;
|
||||
this.getlineArea();
|
||||
});
|
||||
this.tableApiservice.getEcommerceTableData().subscribe(Response => {
|
||||
this.datatableData = Response;
|
||||
this.getTabledata();
|
||||
});
|
||||
}
|
||||
reloadNewOrders() {
|
||||
this.blockUINewOrders.start('Loading..');
|
||||
setTimeout(() => {
|
||||
this.blockUINewOrders.stop();
|
||||
}, 2500);
|
||||
}
|
||||
rotueInvoice() {
|
||||
this.route.navigate(['/invoice/invoice-summary']);
|
||||
}
|
||||
reLoad(){
|
||||
this.route.navigate(['/sale'])
|
||||
}
|
||||
}
|
||||
125
src/app/content/dashboard/hospital/data.ts
Normal file
125
src/app/content/dashboard/hospital/data.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
///////////////////// Start Barchart ///////////////
|
||||
export const barChartOptions: any = {
|
||||
responsive: true,
|
||||
scaleShowVerticalLines: false,
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
labels: {
|
||||
padding: 30
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
categoryPercentage: 0.36,
|
||||
barPercentage: 0.68
|
||||
}]
|
||||
}
|
||||
};
|
||||
export const barChartLabels: string[] = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'];
|
||||
export const barChartType = 'bar';
|
||||
export const barChartLegend = true;
|
||||
export const barChartData: any[] = [
|
||||
{ data: [70, 75, 90, 60, 80, 75, 65], label: 'Fulfilled',
|
||||
backgroundColor: '#00a5a8',
|
||||
borderColor: '#00a5a8',
|
||||
pointBackgroundColor: '#00a5a8',
|
||||
pointBorderColor: '#00a5a8',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: '#00a5a8',
|
||||
barPercentage: 0.5,
|
||||
categoryPercentage: 0.5 },
|
||||
{ data: [60, 65, 80, 63, 90, 80, 70], label: 'Booked',
|
||||
backgroundColor: '#ff4081',
|
||||
borderColor: '#ff4081',
|
||||
pointBackgroundColor: '#ff4081',
|
||||
pointBorderColor: '#ff4081',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: '#ff4081',
|
||||
barPercentage: 0.5,
|
||||
categoryPercentage: 0.5 },
|
||||
{ data: [42, 45, 65, 40, 42, 63, 35], label: 'Arrived',
|
||||
backgroundColor: '#626e82',
|
||||
borderColor: '#626e82',
|
||||
pointBackgroundColor: '#626e82',
|
||||
pointBorderColor: '#626e82',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: '#626e82',
|
||||
barPercentage: 0.5,
|
||||
categoryPercentage: 0.5 },
|
||||
{ data: [50, 55, 70, 40, 47, 65, 38], label: 'No show',
|
||||
backgroundColor: '#ff6e40',
|
||||
borderColor: '#ff6e40',
|
||||
pointBackgroundColor: '#ff6e40',
|
||||
pointBorderColor: '#ff6e40',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: '#ff6e40',
|
||||
barPercentage: 0.5,
|
||||
categoryPercentage: 0.5 },
|
||||
{ data: [40, 40, 45, 45, 45, 40, 45], label: 'reschedule',
|
||||
backgroundColor: '#7c4dff',
|
||||
borderColor: '#7c4dff',
|
||||
pointBackgroundColor: '#7c4dff',
|
||||
pointBorderColor: '#7c4dff',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: '#7c4dff',
|
||||
barPercentage: 0.5,
|
||||
categoryPercentage: 0.5 },
|
||||
{
|
||||
|
||||
type: 'line', // override the default type
|
||||
data: [40, 60, 80, 60, 75, 60, 70],
|
||||
label:'Appointment',
|
||||
backgroundColor: 'rgba(0,255,255,0)',
|
||||
borderColor: '#1e9ff2',
|
||||
fill: false,
|
||||
pointBorderColor: '#1e9ff2',
|
||||
pointBackgroundColor: '#FFF',
|
||||
pointBorderWidth: 2,
|
||||
pointHoverBorderWidth: 2,
|
||||
pointRadius: 4,
|
||||
lineTension: 0.4
|
||||
}
|
||||
];
|
||||
export const barChartColors: Array<any> = [
|
||||
{
|
||||
backgroundColor: '#00a5a8',
|
||||
borderColor: '#00a5a8',
|
||||
pointBackgroundColor: '#00a5a8',
|
||||
pointBorderColor: '#00a5a8',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: '#00a5a8',
|
||||
},
|
||||
{
|
||||
backgroundColor: '#ff4081',
|
||||
borderColor: '#ff4081',
|
||||
pointBackgroundColor: '#ff4081',
|
||||
pointBorderColor: '#ff4081',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: '#ff4081'
|
||||
},
|
||||
{
|
||||
backgroundColor: '#626e82',
|
||||
borderColor: '#626e82',
|
||||
pointBackgroundColor: '#626e82',
|
||||
pointBorderColor: '#626e82',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: '#626e82'
|
||||
},
|
||||
{
|
||||
backgroundColor: '#ff6e40',
|
||||
borderColor: '#ff6e40',
|
||||
pointBackgroundColor: '#ff6e40',
|
||||
pointBorderColor: '#ff6e40',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: '#ff6e40'
|
||||
},
|
||||
{
|
||||
backgroundColor: '#7c4dff',
|
||||
borderColor: '#7c4dff',
|
||||
pointBackgroundColor: '#7c4dff',
|
||||
pointBorderColor: '#7c4dff',
|
||||
pointHoverBackgroundColor: '#fff',
|
||||
pointHoverBorderColor: '#7c4dff'
|
||||
},
|
||||
];
|
||||
///////////////////// End barchart////////////////
|
||||
196
src/app/content/dashboard/hospital/hospital.component.html
Normal file
196
src/app/content/dashboard/hospital/hospital.component.html
Normal file
@@ -0,0 +1,196 @@
|
||||
<div class="app-content content">
|
||||
<div class="content-overlay"></div>
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row">
|
||||
</div>
|
||||
<div class="content-body"><!-- Hospital Info cards -->
|
||||
<div class="row">
|
||||
<div class="col-xl-3 col-lg-6 col-md-6 col-12">
|
||||
<div class="card pull-up">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="media d-flex">
|
||||
<div class="align-self-center">
|
||||
<i class="la la-user-md font-large-2 success"></i>
|
||||
</div>
|
||||
<div class="media-body text-right">
|
||||
<h5 class="text-muted text-bold-500">Doctors Available</h5>
|
||||
<h3 class="text-bold-600">122</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-lg-6 col-md-6 col-12">
|
||||
<div class="card pull-up">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="media d-flex">
|
||||
<div class="align-self-center">
|
||||
<i class="la la-stethoscope font-large-2 warning"></i>
|
||||
</div>
|
||||
<div class="media-body text-right">
|
||||
<h5 class="text-muted text-bold-500">Visiting Doctors</h5>
|
||||
<h3 class="text-bold-600">34</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-lg-6 col-md-6 col-12">
|
||||
<div class="card pull-up">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="media d-flex">
|
||||
<div class="align-self-center">
|
||||
<i class="la la-calendar-check-o font-large-2 info"></i>
|
||||
</div>
|
||||
<div class="media-body text-right">
|
||||
<h5 class="text-muted text-bold-500">Today's Inquiry</h5>
|
||||
<h3 class="text-bold-600">3.5K</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-lg-6 col-md-6 col-12">
|
||||
<div class="card pull-up">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="media d-flex">
|
||||
<div class="align-self-center">
|
||||
<i class="la la-bed font-large-2 danger"></i>
|
||||
</div>
|
||||
<div class="media-body text-right">
|
||||
<h5 class="text-muted text-bold-500">Rooms Available</h5>
|
||||
<h3 class="text-bold-600">179</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Hospital Info cards Ends -->
|
||||
|
||||
<!-- Appointment Bar Line Chart -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<section id="chartjs-bar-charts">
|
||||
<div class="row">
|
||||
<div class="col-12" *blockUI="'barCharts'; message: 'Loading'">
|
||||
<m-card [options]="options" (reloadFunction)="reloadBarCharts($event)">
|
||||
<ng-container mCardHeaderTitle>
|
||||
Appointment
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<div class="z">
|
||||
<canvas class="barchart" height="328" baseChart [datasets]="barChartData" [labels]="barChartLabels"
|
||||
[options]="barChartOptions" [legend]="barChartLegend"
|
||||
[chartType]="barChartType"></canvas>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Appointment Bar Line Chart Ends -->
|
||||
|
||||
<!-- Appointment Table -->
|
||||
<div class="row" matchHeight="card">
|
||||
<div class="col-12 col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Doctors Available</h4>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="table-responsive">
|
||||
<table id="recent-orders" class="table table-hover table-xl mb-0">
|
||||
<tbody>
|
||||
<tr *ngFor = "let doctor of doctors ">
|
||||
<td class="text-truncate p-1 border-top-0">
|
||||
<div class="avatar avatar-md">
|
||||
<img class="media-object rounded-circle" [src]= doctor.image
|
||||
alt="Avatar">
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-truncate pl-0 border-top-0">
|
||||
<div class="name">{{doctor.name}}</div>
|
||||
<div class="designation text-light font-small-2">Dentist</div>
|
||||
</td>
|
||||
<td class="text-right border-top-0">
|
||||
<a href="hospital-book-appointment.html" class="btn btn-sm btn-outline-success">Book Appointment</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="recent-appointments" class="col-12 col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Recent Appointments</h4>
|
||||
<a class="heading-elements-toggle"><i class="la la-ellipsis-v font-medium-3"></i></a>
|
||||
<div class="heading-elements">
|
||||
<ul class="list-inline mb-0">
|
||||
<li><a class="btn btn-sm btn-danger box-shadow-2 round btn-min-width pull-right" href="hospital-book-appointment.html"
|
||||
target="_blank">View all</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-content mt-1">
|
||||
<div class="table-responsive">
|
||||
<table id="recent-orders-doctors" class="table table-hover table-xl mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="border-top-0">Doctor</th>
|
||||
<th class="border-top-0">Patients</th>
|
||||
<th class="border-top-0">Specialities</th>
|
||||
<th class="border-top-0">Timings</th>
|
||||
<th class="border-top-0">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="pull-up" *ngFor="let doctor of doctorList">
|
||||
<td class="text-truncate">{{doctor.name}}</td>
|
||||
<td class="text-truncate p-1">
|
||||
<ul class="list-unstyled users-list m-0">
|
||||
<li data-toggle="tooltip" data-popup="tooltip-custom" data-original-title="Kimberly Simmons" class="avatar avatar-sm pull-up" *ngFor="let imageUrl of doctor.image">
|
||||
<img class="media-object rounded-circle" [src]="imageUrl" alt="Avatar">
|
||||
|
||||
</li>
|
||||
|
||||
<li class="avatar avatar-sm">
|
||||
<span class="badge badge-info">{{doctor.bagde}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-sm btn-outline-{{doctor.type}} round">{{doctor.designation}}</button>
|
||||
</td>
|
||||
<td class="text-truncate">{{doctor.time}}</td>
|
||||
<td class="text-truncate">{{doctor.amount}}</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Appointment Table Ends -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END: Content-->
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HospitalComponent } from './hospital.component';
|
||||
|
||||
describe('HospitalComponent', () => {
|
||||
let component: HospitalComponent;
|
||||
let fixture: ComponentFixture<HospitalComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ HospitalComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(HospitalComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
66
src/app/content/dashboard/hospital/hospital.component.ts
Normal file
66
src/app/content/dashboard/hospital/hospital.component.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { PerfectScrollbarComponent, PerfectScrollbarDirective, PerfectScrollbarConfigInterface } from 'ngx-perfect-scrollbar';
|
||||
import * as chartsData from './data';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-hospital',
|
||||
templateUrl: './hospital.component.html',
|
||||
styleUrls: ['./hospital.component.css']
|
||||
})
|
||||
export class HospitalComponent {
|
||||
public config: PerfectScrollbarConfigInterface = { suppressScrollY: true };
|
||||
@ViewChild(PerfectScrollbarComponent) componentRef?: PerfectScrollbarComponent;
|
||||
@ViewChild(PerfectScrollbarDirective, { static: true }) directiveRef?: PerfectScrollbarDirective;
|
||||
|
||||
constructor() { }
|
||||
|
||||
doctors = [
|
||||
{'name': 'Jane Andre','image':'../../../assets/images/portrait/small/avatar-s-4.png'},
|
||||
{'name': 'Kail Reack','image':'../../../assets/images/portrait/small/avatar-s-5.png'},
|
||||
{'name': 'Shail Black','image':'../../../assets/images/portrait/small/avatar-s-6.png'},
|
||||
{'name': 'Zena wall','image':'../../../assets/images/portrait/small/avatar-s-7.png'},
|
||||
{'name': 'Colin Welch','image':'../../../assets/images/portrait/small/avatar-s-8.png'}
|
||||
]
|
||||
|
||||
firstRow = ['../../../assets/images/portrait/small/avatar-s-4.png',
|
||||
'../../../assets/images/portrait/small/avatar-s-5.png',
|
||||
'../../../assets/images/portrait/small/avatar-s-6.png'];
|
||||
secondRow = ['../../../assets/images/portrait/small/avatar-s-7.png',
|
||||
'../../../assets/images/portrait/small/avatar-s-8.png'];
|
||||
thirdRow = ['../../../assets/images/portrait/small/avatar-s-1.png',
|
||||
'../../../assets/images/portrait/small/avatar-s-2.png',
|
||||
'../../../assets/images/portrait/small/avatar-s-3.png'];
|
||||
fourthRow = ['../../../assets/images/portrait/small/avatar-s-11.png',
|
||||
'../../../assets/images/portrait/small/avatar-s-12.png'];
|
||||
fifthRow = ['../../../assets/images/portrait/small/avatar-s-6.png',
|
||||
'../../../assets/images/portrait/small/avatar-s-4.png'];
|
||||
doctorList = [
|
||||
{
|
||||
'type': 'danger', 'designation': 'Dentist', 'name': 'Jane Andre',
|
||||
'image': this.firstRow, 'time': '8:00 A.M. - 12:00 P.M.', 'amount': '$ 1200.00', 'bagde': '+8 more'
|
||||
},
|
||||
{
|
||||
'type': 'success', 'designation': 'Dermatologist', 'name': 'Kail Reack',
|
||||
'image': this.secondRow, 'time': '10:00 A.M. - 1:00 P.M.', 'amount': '$ 1190.00', 'bagde': '+5 more'
|
||||
},
|
||||
{
|
||||
'type': 'danger', 'designation': 'Psychiatrist', 'name': 'Shail Black',
|
||||
'image': this.thirdRow, 'time': '11:00 A.M. - 2:00 P.M.', 'amount': '$ 999.00', 'bagde': '+3 more'
|
||||
},
|
||||
{
|
||||
'type': 'success', 'designation': 'Gastroenterologist', 'name': 'Zena wall',
|
||||
'image': this.fourthRow, 'time': '11:30 A.M. - 3:00 P.M.', 'amount': '$ 1150.00'
|
||||
},
|
||||
{
|
||||
'type': 'danger', 'designation': 'Pediatrician', 'name': 'Colin Welch',
|
||||
'image': this.fifthRow, 'time': '5:00 P.M. - 8:00 P.M.', 'amount': '$ 1180.00'
|
||||
}
|
||||
];
|
||||
public barChartOptions = chartsData.barChartOptions;
|
||||
public barChartLabels = chartsData.barChartLabels;
|
||||
public barChartType = chartsData.barChartType;
|
||||
public barChartLegend = chartsData.barChartLegend;
|
||||
public barChartData = chartsData.barChartData;
|
||||
public barChartColors = chartsData.barChartColors;
|
||||
}
|
||||
281
src/app/content/dashboard/sales/sales.component.css
Normal file
281
src/app/content/dashboard/sales/sales.component.css
Normal file
@@ -0,0 +1,281 @@
|
||||
:host ::ng-deep .chartist .ct-series-a .ct-line {
|
||||
|
||||
stroke: url(#gradient2);
|
||||
stroke-linecap: round;
|
||||
/* -webkit-filter: drop-shadow(0px 20px 11px rgba(0, 0, 0, 0.5)) !important; */
|
||||
}
|
||||
:host ::ng-deep .chartist {
|
||||
filter: drop-shadow(0px 20px 11px rgba(252, 198, 198, 0.8)) !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .chartist .ct-grid{
|
||||
stroke-dasharray: 0px;
|
||||
stroke: rgba(0, 0, 0, 0.4);
|
||||
stroke-width: 0.6px;
|
||||
}
|
||||
:host ::ng-deep .chartist .ct-series-b .ct-line {
|
||||
stroke: #c8c2c3;
|
||||
stroke-dasharray: 8px 3px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .chartist .ct-label.ct-vertical.ct-start {
|
||||
font-weight: 600;
|
||||
color: #636161;
|
||||
font-size: 12px;
|
||||
}
|
||||
:host ::ng-deep .earningchart .ct-series-a .ct-area {
|
||||
fill: rgba(255,117,136,1);
|
||||
}
|
||||
:host ::ng-deep .earningchart .ct-series-a .ct-point-circle {
|
||||
stroke-width: 3px;
|
||||
stroke: #FF4961;
|
||||
fill: #ffffff;
|
||||
}
|
||||
|
||||
:host ::ng-deep .earningchart .ct-series-a .ct-line {
|
||||
stroke: #FF4961;
|
||||
stroke-width: 3px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .avatar-xs {
|
||||
width: 32px !important;
|
||||
border: 2px solid #FFF;
|
||||
}
|
||||
:host ::ng-deep .donut-chart2{
|
||||
margin-bottom: -25px;
|
||||
margin-top: -17px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart2 .ct-series-a .ct-slice-donut {
|
||||
stroke: #28d094;
|
||||
stroke-width: 5.5px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart2 .ct-series-b .ct-slice-donut {
|
||||
stroke: #ff4961;
|
||||
stroke-width: 5.5px !important;
|
||||
}
|
||||
:host ::ng-deep .donut-chart2 {
|
||||
-webkit-filter: drop-shadow(0px 10px 11px rgba(187,187,187)) !important;
|
||||
filter: drop-shadow(0px 10px 11px rgba(187,187,187));
|
||||
}
|
||||
:host ::ng-deep .donut-chart1 {
|
||||
margin-bottom: -25px;
|
||||
margin-top: -17px;
|
||||
}
|
||||
:host ::ng-deep .donut-chart1 .ct-series-a .ct-slice-donut {
|
||||
stroke: #ff7889;
|
||||
stroke-width: 5.5px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart1 .ct-series-b .ct-slice-donut {
|
||||
stroke: #ffffff;
|
||||
stroke-width: 5.5px !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart1 .ct-label {
|
||||
fill: #ffffff;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
font-size: 1.75rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
:host ::ng-deep .donut-chart2 .ct-label {
|
||||
fill: #ff4b62;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
font-size: 1.75rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
:host ::ng-deep .position-relative {
|
||||
position: relative !important;
|
||||
margin-left: 0px;
|
||||
|
||||
}
|
||||
|
||||
:host ::ng-deep .pt-1,
|
||||
.py-1 {
|
||||
padding-top: 0rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .chartist .ct-label.ct-horizontal.ct-end {
|
||||
/* align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
text-align: left;
|
||||
text-anchor: start; */
|
||||
font-weight: 600;
|
||||
color: #636161;
|
||||
font-size: 12px;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
|
||||
:host ::ng-deep .container > .ct-chart .ct-series.ct-series-c .ct-line {
|
||||
stroke-width: 2px;
|
||||
stroke-dasharray: 20px 180px;
|
||||
stroke: #28d094;
|
||||
animation: draw 0.3s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes draw {
|
||||
from {
|
||||
stroke-dashoffset: 200
|
||||
}
|
||||
|
||||
to {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-series-c .ct-point,
|
||||
.ct-series-c .ct-line,
|
||||
.ct-series-c .ct-bar,
|
||||
.ct-series-c .ct-slice-donut {
|
||||
stroke: #28d094;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-chart .ct-series.ct-series-c .ct-line {
|
||||
stroke: #28d094;
|
||||
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-series-b .ct-point,
|
||||
.ct-series-b .ct-line,
|
||||
.ct-series-b .ct-bar,
|
||||
.ct-series-b .ct-slice-donut {
|
||||
stroke: #ff4961;
|
||||
}
|
||||
|
||||
:host ::ng-deep .container > .ct-chart .ct-series.ct-series-a .ct-line {
|
||||
stroke-dasharray: 5px;
|
||||
animation: dash 4s linear infinite;
|
||||
|
||||
}
|
||||
|
||||
@keyframes dash {
|
||||
to {
|
||||
stroke-dashoffset: 2000;
|
||||
}
|
||||
}
|
||||
|
||||
:host ::ng-deep .ct-chart .ct-point {
|
||||
stroke-width: 10px;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
|
||||
:host ::ng-deep .container > .ct-chart .ct-series.ct-series-b .ct-line {
|
||||
stroke-width: 10px;
|
||||
stroke-dasharray: 15px 5px;
|
||||
animation: draw 4s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes draw {
|
||||
from {
|
||||
stroke-dashoffset: 100
|
||||
}
|
||||
|
||||
to {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
:host ::ng-deep .container {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
:host ::ng-deep .btn.gradient-blackberry.active,
|
||||
.gradient-blackberry {
|
||||
background-color: #f05b4f;
|
||||
|
||||
}
|
||||
|
||||
:host ::ng-deep .Visit {
|
||||
|
||||
background-color: #28d094;
|
||||
|
||||
}
|
||||
|
||||
:host ::ng-deep .Sales {
|
||||
/* background-image: linear-gradient(45deg,#843cf7,#38b8f2)!important; */
|
||||
background-color: #d70206;
|
||||
|
||||
}
|
||||
|
||||
:host ::ng-deep .col-md-11 {
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .col-md-1 {
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .box-shadow-0 .ct-label.ct-vertical.ct-start {
|
||||
|
||||
font-weight: bold;
|
||||
color: #6e6e6e;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
:host ::ng-deep .box-shadow-0 .ct-label.ct-horizontal.ct-end {
|
||||
|
||||
font-weight: bold;
|
||||
color: #6e6e6e;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
|
||||
:host ::ng-deep .text-truncate {
|
||||
padding: 0.9rem 2rem;
|
||||
}
|
||||
|
||||
.mr-2 {
|
||||
margin-left: 1rem !important;
|
||||
margin-right: 0rem !important;
|
||||
}
|
||||
|
||||
.mt-2 {
|
||||
margin-top : 1.5rem !important;
|
||||
}
|
||||
|
||||
.ml-2 {
|
||||
margin-left : 2rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .my-custom-cell {
|
||||
padding-right: 6% !important;
|
||||
padding-top: 1.5% !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .border_bottom {
|
||||
margin-bottom: 0rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .border-top-0 {
|
||||
padding: 1.25rem 2rem !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .progress {
|
||||
box-shadow: 0 10px 18px 0 rgba(62, 57, 107, .2);
|
||||
margin-top: 1rem!important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .btn-danger {
|
||||
color: #FFF !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .users-list li + li {
|
||||
margin-left: -10px !important;
|
||||
}
|
||||
|
||||
|
||||
:host ::ng-deep .block-ui-wrapper {
|
||||
background: rgba(255, 249, 249, 0.5) !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .ps--active-x > .ps__rail-x {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep .progress {
|
||||
margin-bottom: 1rem !important;
|
||||
}
|
||||
269
src/app/content/dashboard/sales/sales.component.html
Normal file
269
src/app/content/dashboard/sales/sales.component.html
Normal file
@@ -0,0 +1,269 @@
|
||||
<div class="app-content content">
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header row mb-1">
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<!-- Revenue, Hit Rate & Deals -->
|
||||
<div class="row">
|
||||
<div class="col-xl-6 col-12">
|
||||
<div class="Revenue" *blockUI="'revenue'; message: 'Loading'">
|
||||
<m-card [options]="options" (reloadFunction)="reloadRevenue($event)">
|
||||
<ng-container mCardHeaderTitle>
|
||||
Revenue
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<div class="row mb-1">
|
||||
<div class="col-6 col-md-4">
|
||||
<h5>Current week</h5>
|
||||
<h2 class="danger">$82,124</h2>
|
||||
</div>
|
||||
<div class="col-6 col-md-4">
|
||||
<h5>Previous week</h5>
|
||||
<h2 class="text-muted">$52,502</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chartist">
|
||||
<x-chartist *ngIf="lineArea" [data]="lineArea.data" [type]="lineArea.type" [options]="lineArea.options"
|
||||
[responsiveOptions]="lineArea.responsiveOptions" [events]="lineArea.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-6 col-12">
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-12 ">
|
||||
<div class="HitRate" *blockUI="'hitrate'; message: 'Loading'">
|
||||
<m-card [options]="hitRateOptions" id="card" (reloadFunction)="reloadHitRate($event)">
|
||||
<ng-container mCardHeaderTitle>
|
||||
Hit Rate <span class="danger">-12%</span>
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<div id="donut-chart2" class="height-230 donut-chart2">
|
||||
<x-chartist *ngIf="donutChart2" [data]="donutChart2.data" [type]="donutChart2.type" [options]="donutChart2.options"
|
||||
[responsiveOptions]="donutChart2.responsiveOptions" [events]="donutChart2.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-12">
|
||||
<m-card [options]="dealsOptions">
|
||||
<ng-container mCardBody>
|
||||
<h4 class="card-title white">Deals <span class="white">-55%</span>
|
||||
<span class="float-right">
|
||||
<span class="white">152</span><span class="red lighten-4">/200</span>
|
||||
</span>
|
||||
</h4>
|
||||
<div id="donut-chart1" class="height-230 donut-chart1">
|
||||
<x-chartist *ngIf="donutChart1" [data]="donutChart1.data" [type]="donutChart1.type" [options]="donutChart1.options"
|
||||
[responsiveOptions]="donutChart1.responsiveOptions" [events]="donutChart1.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-12">
|
||||
<div class="card pull-up">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="media d-flex">
|
||||
<div class="media-body text-left">
|
||||
<h6 class="text-muted">Order Value </h6>
|
||||
<h3>$ 88,568</h3>
|
||||
</div>
|
||||
<div class="align-self-center">
|
||||
<i class="icon-trophy success font-large-2 float-right"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 col-12">
|
||||
<div class="card pull-up">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="media d-flex">
|
||||
<div class="media-body text-left">
|
||||
<h6 class="text-muted">Calls</h6>
|
||||
<h3>3,568</h3>
|
||||
</div>
|
||||
<div class="align-self-center">
|
||||
<i class="icon-call-in danger font-large-2 float-right"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--/ Revenue, Hit Rate & Deals -->
|
||||
|
||||
<!-- Emails Products & Avg Deals -->
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-3">
|
||||
<div class="EmailRate" *blockUI="'email'; message: 'Updating'">
|
||||
<m-card [options]="emailsOptions" (reloadFunction)="reloadEmail($event)">
|
||||
<ng-container mCardHeaderTitle>
|
||||
Emails
|
||||
</ng-container>
|
||||
<ng-container mCardBody>
|
||||
<p>Open rate <span class="float-right text-bold-600">89%</span></p>
|
||||
<ngb-progressbar height="7px" type="danger" [value]="89"></ngb-progressbar>
|
||||
<p class="pt-1">Sent <span class="float-right"><span class="text-bold-600">310</span>/500</span>
|
||||
</p>
|
||||
<ngb-progressbar height="7px" type="success" [value]="50"></ngb-progressbar>
|
||||
</ng-container>
|
||||
</m-card>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Top Products</h4>
|
||||
<div class="heading-elements">
|
||||
<ul class="list-inline mb-0">
|
||||
<li><a class="info">Show all</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-content collapse show">
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table mb-0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row" class="border-top-0">iPone X</th>
|
||||
<td class="border-top-0">2245</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">One Plus</th>
|
||||
<td>1850</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Samsung S7</th>
|
||||
<td>1550</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title text-center">Average Deal Size</h4>
|
||||
</div>
|
||||
<div class="card-content collapse show">
|
||||
<div class="card-body pt-0">
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-12 border-right-blue-grey border-right-lighten-5 text-center">
|
||||
<h6 class="danger text-bold-600">-30%</h6>
|
||||
<h4 class="font-large-2 text-bold-400">$12,536</h4>
|
||||
<p class="blue-grey lighten-2 mb-0">Per rep</p>
|
||||
</div>
|
||||
<div class="col-md-6 col-12 text-center">
|
||||
<h6 class="success text-bold-600">12%</h6>
|
||||
<h4 class="font-large-2 text-bold-400">$18,548</h4>
|
||||
<p class="blue-grey lighten-2 mb-0">Per team</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--/ Emails Products & Avg Deals -->
|
||||
|
||||
<!-- Total earning & Recent Sales -->
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="earning-chart position-relative">
|
||||
<div class="chart-title position-absolute mt-2 ml-2">
|
||||
<h1 class="display-4">$1,596</h1>
|
||||
<span class="text-muted">Total Earning</span>
|
||||
</div>
|
||||
<div id="cost-revenue" class="earningchart position-relative">
|
||||
<x-chartist *ngIf="earningchart" [data]="earningchart.data" [type]="earningchart.type" [options]="earningchart.options"
|
||||
[responsiveOptions]="earningchart.responsiveOptions" [events]="earningchart.events">
|
||||
</x-chartist>
|
||||
</div>
|
||||
<div class="chart-stats position-absolute position-bottom-0 position-right-0 mb-2 mr-3">
|
||||
<a [routerLink]="" class="btn round btn-danger mr-1 btn-glow">Statistics <i class="feather ft-bar-chart"></i></a>
|
||||
<span class="text-muted">for the <a [routerLink]="" class="danger darken-2">last year.</a></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="recent-sales" class="col-12 col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Recent Sales</h4>
|
||||
<div class="heading-elements">
|
||||
<ul class="list-inline mb-0">
|
||||
<li><a [routerLink]="" class="btn btn-sm btn-danger box-shadow-2 round btn-min-width pull-right" (click)="rotueInvoice()">View
|
||||
all</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-content mt-1">
|
||||
<div class="table-responsive" fxFlex="auto" [perfectScrollbar]="config">
|
||||
<table class="table border_bottom table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="border-top-0">Product</th>
|
||||
<th scope="col" class="border-top-0">Customers</th>
|
||||
<th scope="col" class="border-top-0">Categories</th>
|
||||
<th scope="col" class="border-top-0">Popularity</th>
|
||||
<th scope="col" class="border-top-0">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let row of rows">
|
||||
<td class="text-truncate">
|
||||
{{row.product}}
|
||||
</td>
|
||||
<td class="text-truncate p-1">
|
||||
<ul class="list-unstyled users-list m-0">
|
||||
<li class="avatar avatar-sm pull-up" *ngFor="let imageUrl of row.image">
|
||||
<img class="media-object rounded-circle" [src]="imageUrl" alt="Avatar">
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td class="text-truncate">
|
||||
<span>
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-outline-{{row.type}} round">{{row.buttonname}}</button>
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-truncate">
|
||||
<ngb-progressbar height="7px" type="{{row.type}}" [value]=row.value>
|
||||
</ngb-progressbar>
|
||||
</td>
|
||||
<td class="text-truncate">{{ row.amount }} </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--/ Total earning & Recent Sales -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ////////////////////////////////////////////////////////////////////////////-->
|
||||
25
src/app/content/dashboard/sales/sales.component.spec.ts
Normal file
25
src/app/content/dashboard/sales/sales.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { SalesComponent } from './sales.component';
|
||||
|
||||
describe('SalesComponent', () => {
|
||||
let component: SalesComponent;
|
||||
let fixture: ComponentFixture<SalesComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ SalesComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SalesComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
332
src/app/content/dashboard/sales/sales.component.ts
Normal file
332
src/app/content/dashboard/sales/sales.component.ts
Normal file
@@ -0,0 +1,332 @@
|
||||
import { Component, OnInit, ViewChild, Renderer2 } from '@angular/core';
|
||||
import * as Chartist from 'chartist';
|
||||
import { DatatableComponent } from '@swimlane/ngx-datatable';
|
||||
import { ChartEvent, ChartType } from 'ng-chartist';
|
||||
import { BlockUI, NgBlockUI } from 'ng-block-ui';
|
||||
import { PerfectScrollbarComponent, PerfectScrollbarDirective, PerfectScrollbarConfigInterface } from 'ngx-perfect-scrollbar';
|
||||
import { ChartApiService } from '../../../_services/chart.api';
|
||||
import { Router } from '@angular/router';
|
||||
export interface Chart {
|
||||
type: ChartType;
|
||||
data: Chartist.IChartistData;
|
||||
options?: any;
|
||||
responsiveOptions?: any;
|
||||
events?: ChartEvent;
|
||||
}
|
||||
@Component({
|
||||
selector: 'app-sales',
|
||||
templateUrl: './sales.component.html',
|
||||
styleUrls: ['./sales.component.css']
|
||||
})
|
||||
export class SalesComponent implements OnInit {
|
||||
|
||||
@BlockUI('revenue') blockUIRevenue: NgBlockUI;
|
||||
@BlockUI('hitrate') blockUIHitRate: NgBlockUI;
|
||||
@BlockUI('email') blockUIEmail: NgBlockUI;
|
||||
|
||||
public config: PerfectScrollbarConfigInterface = { suppressScrollY: true };
|
||||
@ViewChild(PerfectScrollbarComponent) componentRef?: PerfectScrollbarComponent;
|
||||
@ViewChild(PerfectScrollbarDirective, { static: true }) directiveRef?: PerfectScrollbarDirective;
|
||||
|
||||
salesData: any;
|
||||
lineArea: any;
|
||||
earningchart: any;
|
||||
donutChart2: any;
|
||||
donutChart1: any;
|
||||
options = {
|
||||
bodyClass: ['pt-0'],
|
||||
close: false,
|
||||
expand: false,
|
||||
minimize: false,
|
||||
reload: true
|
||||
};
|
||||
|
||||
hitRateOptions = {
|
||||
bodyClass: ['bg-hexagons', 'pt-0'],
|
||||
headerClass: ['bg-hexagons'],
|
||||
cardClass: ['pull-up'],
|
||||
close: false,
|
||||
expand: false,
|
||||
minimize: false,
|
||||
reload: true
|
||||
};
|
||||
|
||||
dealsOptions = {
|
||||
bodyClass: ['bg-hexagons-danger'],
|
||||
cardClass: ['pull-up'],
|
||||
contentClass: ['bg-gradient-directional-danger']
|
||||
};
|
||||
|
||||
emailsOptions = {
|
||||
bodyClass: ['pt-0'],
|
||||
close: false,
|
||||
expand: false,
|
||||
minimize: false,
|
||||
reload: true
|
||||
};
|
||||
loadingIndicator = true;
|
||||
|
||||
firstRow = ['../../../assets/images/portrait/small/avatar-s-4.png',
|
||||
'../../../assets/images/portrait/small/avatar-s-5.png',
|
||||
'../../../assets/images/portrait/small/avatar-s-6.png'];
|
||||
secondRow = ['../../../assets/images/portrait/small/avatar-s-7.png',
|
||||
'../../../assets/images/portrait/small/avatar-s-8.png'];
|
||||
thirdRow = ['../../../assets/images/portrait/small/avatar-s-1.png',
|
||||
'../../../assets/images/portrait/small/avatar-s-2.png',
|
||||
'../../../assets/images/portrait/small/avatar-s-3.png'];
|
||||
fourthRow = ['../../../assets/images/portrait/small/avatar-s-11.png',
|
||||
'../../../assets/images/portrait/small/avatar-s-12.png'];
|
||||
fifthRow = ['../../../assets/images/portrait/small/avatar-s-6.png',
|
||||
'../../../assets/images/portrait/small/avatar-s-4.png'];
|
||||
rows = [
|
||||
{
|
||||
'type': 'danger', 'value': 85, 'product': 'iPhone X',
|
||||
'image': this.firstRow, 'buttonname': 'Mobile', 'amount': '$ 1200.00', 'bagde': '+8 more'
|
||||
},
|
||||
{
|
||||
'type': 'success', 'value': 75, 'product': 'iPad',
|
||||
'image': this.secondRow, 'buttonname': 'Teblet', 'amount': '$ 1190.00', 'bagde': '+5 more'
|
||||
},
|
||||
{
|
||||
'type': 'danger', 'value': 65, 'product': 'OnePlus',
|
||||
'image': this.thirdRow, 'buttonname': 'Mobile', 'amount': '$ 999.00', 'bagde': '+3 more'
|
||||
},
|
||||
{
|
||||
'type': 'success', 'value': 55, 'product': 'ZenPad',
|
||||
'image': this.fourthRow, 'buttonname': 'Teblet', 'amount': '$ 1150.00'
|
||||
},
|
||||
{
|
||||
'type': 'danger', 'value': 45, 'product': 'Pixel 2',
|
||||
'image': this.fifthRow, 'buttonname': 'Mobile', 'amount': '$ 1180.00'
|
||||
}
|
||||
];
|
||||
|
||||
@ViewChild(DatatableComponent, { static: true }) table: DatatableComponent;
|
||||
Daygraph = true;
|
||||
Weekgraph = false;
|
||||
Monthgraph = false;
|
||||
ngOnInit() {
|
||||
this.chartApiservice.getSalesData().subscribe(Response => {
|
||||
this.salesData = Response;
|
||||
this.getChartdata();
|
||||
});
|
||||
}
|
||||
constructor(private _renderer: Renderer2, private route: Router,
|
||||
private chartApiservice: ChartApiService) { }
|
||||
reloadRevenue() {
|
||||
this.blockUIRevenue.start('Loading..');
|
||||
|
||||
setTimeout(() => {
|
||||
this.blockUIRevenue.stop();
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
reloadHitRate() {
|
||||
this.blockUIHitRate.start('Please Wait..');
|
||||
|
||||
setTimeout(() => {
|
||||
this.blockUIHitRate.stop();
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
reloadEmail() {
|
||||
this.blockUIEmail.start();
|
||||
|
||||
setTimeout(() => {
|
||||
this.blockUIEmail.stop();
|
||||
}, 2500);
|
||||
}
|
||||
rotueInvoice() {
|
||||
this.route.navigate(['/invoice/invoice-summary']);
|
||||
}
|
||||
getChartdata() {
|
||||
const Chartdata = this.salesData;
|
||||
this.lineArea = {
|
||||
type: 'Line',
|
||||
data: Chartdata['lineArea'],
|
||||
options: {
|
||||
lineSmooth: Chartist.Interpolation.simple({
|
||||
divisor: 2.8
|
||||
}),
|
||||
fullWidth: true,
|
||||
height: '270px',
|
||||
showArea: false,
|
||||
showPoint: false,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
showLabel: true,
|
||||
offset: 32
|
||||
},
|
||||
axisY: {
|
||||
showGrid: true,
|
||||
showLabel: true,
|
||||
scaleMinSpace: 28,
|
||||
offset: 44
|
||||
},
|
||||
},
|
||||
events: {
|
||||
created(data: any): void {
|
||||
const defs = data.svg.elem('defs');
|
||||
defs.elem('linearGradient', {
|
||||
id: 'gradient2',
|
||||
x1: 0,
|
||||
y1: 0,
|
||||
x2: 1,
|
||||
y2: 0
|
||||
}).elem('stop', {
|
||||
offset: 0,
|
||||
'stop-color': 'rgb(255,73,97)'
|
||||
}).parent().elem('stop', {
|
||||
offset: 1,
|
||||
'stop-color': 'rgb(255,73,97)'
|
||||
});
|
||||
},
|
||||
draw(data: any): void {
|
||||
const circleRadius = 4;
|
||||
if (data.type === 'point') {
|
||||
const circle = new Chartist.Svg('circle', {
|
||||
cx: data.x,
|
||||
cy: data.y,
|
||||
r: circleRadius,
|
||||
class: 'ct-point-circle'
|
||||
});
|
||||
data.element.replace(circle);
|
||||
} else if (data.type === 'label') {
|
||||
// adjust label position for rotation
|
||||
const dX = data.width / 2 + (26 - data.width);
|
||||
data.element.attr({ x: data.element.attr('x') - dX });
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
this.earningchart = {
|
||||
type: 'Line',
|
||||
data: Chartdata['earningchart'],
|
||||
options: {
|
||||
chartPadding: 0,
|
||||
height: '440px',
|
||||
low: 0,
|
||||
showArea: true,
|
||||
fullWidth: true,
|
||||
onlyInteger: true,
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
showLabel: false,
|
||||
offset: -1
|
||||
},
|
||||
axisY: {
|
||||
scaleMinSpace: 40,
|
||||
showGrid: false,
|
||||
showLabel: false,
|
||||
offset: -2
|
||||
},
|
||||
},
|
||||
responsiveOptions: [
|
||||
['screen and (max-width: 640px) and (min-width: 381px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 2 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}],
|
||||
['screen and (max-width: 380px)', {
|
||||
axisX: {
|
||||
labelInterpolationFnc: function (value, index) {
|
||||
return index % 3 === 0 ? value : null;
|
||||
}
|
||||
}
|
||||
}]
|
||||
],
|
||||
events: {
|
||||
created(data: any): void {
|
||||
const defs = data.svg.elem('defs');
|
||||
defs.elem('linearGradient', {
|
||||
id: 'gradient1',
|
||||
x1: 0,
|
||||
y1: 0,
|
||||
x2: 1,
|
||||
y2: 0
|
||||
}).elem('stop', {
|
||||
offset: 0,
|
||||
'stop-color': 'rgb(255,73,97)'
|
||||
}).parent().elem('stop', {
|
||||
offset: 1,
|
||||
'stop-color': 'rgb(255,73,97)'
|
||||
});
|
||||
},
|
||||
draw(data: any): void {
|
||||
const circleRadius = 6;
|
||||
if (data.type === 'point') {
|
||||
const circle = new Chartist.Svg('circle', {
|
||||
cx: data.x,
|
||||
cy: data.y,
|
||||
r: circleRadius,
|
||||
class: 'ct-point-circle'
|
||||
});
|
||||
data.element.replace(circle);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
// Doughnut
|
||||
this.donutChart2 = {
|
||||
type: 'Pie',
|
||||
data: Chartdata['donut1'],
|
||||
options: {
|
||||
chartPadding: 0,
|
||||
fullwidth: true,
|
||||
height: '273px',
|
||||
donut: true,
|
||||
showLabel: true,
|
||||
startAngle: 0,
|
||||
labelInterpolationFnc: function (value) {
|
||||
const total = 82;
|
||||
return total + '%';
|
||||
}
|
||||
},
|
||||
events: {
|
||||
draw(data: any): void {
|
||||
if (data.type === 'label') {
|
||||
if (data.index === 0) {
|
||||
data.element.attr({
|
||||
dx: data.element.root().width() / 2,
|
||||
dy: data.element.root().height() / 2
|
||||
});
|
||||
} else {
|
||||
data.element.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
this.donutChart1 = {
|
||||
type: 'Pie',
|
||||
data: Chartdata['donut2'],
|
||||
options: {
|
||||
chartPadding: 0,
|
||||
fullwidth: true,
|
||||
height: '273px',
|
||||
donut: true,
|
||||
showLabel: true,
|
||||
labelInterpolationFnc: function (value) {
|
||||
const total = 76;
|
||||
return total + '%';
|
||||
}
|
||||
},
|
||||
events: {
|
||||
draw(data: any): void {
|
||||
if (data.type === 'label') {
|
||||
if (data.index === 0) {
|
||||
data.element.attr({
|
||||
dx: data.element.root().width() / 2,
|
||||
dy: data.element.root().height() / 2
|
||||
});
|
||||
} else {
|
||||
data.element.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user