Merge pull request #32 from Pear-Trading/finn/storytrail
story markers and package updates
This commit is contained in:
commit
52551e3f6e
31 changed files with 1832 additions and 2294 deletions
|
@ -2,6 +2,12 @@
|
|||
|
||||
# Next Release
|
||||
|
||||
* Info window on map replaced with modals
|
||||
* Loading modals added to maps
|
||||
* Lancaster Independent Story markers added
|
||||
* Code dependencies updated
|
||||
* Angular code updated to Angular 5 and made fixes to account for it
|
||||
|
||||
# v0.0.3
|
||||
|
||||
* Customer Leaderboards added
|
||||
|
|
3624
package-lock.json
generated
3624
package-lock.json
generated
File diff suppressed because it is too large
Load diff
66
package.json
66
package.json
|
@ -18,51 +18,49 @@
|
|||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@agm/core": "^1.0.0-beta.1",
|
||||
"@agm/js-marker-clusterer": "^1.0.0-beta.2",
|
||||
"@angular/common": "4.0.3",
|
||||
"@angular/compiler": "4.0.3",
|
||||
"@angular/core": "4.0.3",
|
||||
"@angular/forms": "4.0.3",
|
||||
"@angular/http": "4.0.3",
|
||||
"@angular/platform-browser": "4.0.3",
|
||||
"@angular/platform-browser-dynamic": "4.0.3",
|
||||
"@angular/router": "4.0.3",
|
||||
"@angular/upgrade": "4.0.3",
|
||||
"@types/moment": "^2.13.0",
|
||||
"angular-in-memory-web-api": "^0.3.1",
|
||||
"chart.js": "2.5.0",
|
||||
"core-js": "2.4.1",
|
||||
"js-marker-clusterer": "^1.0.0",
|
||||
"moment": "^2.18.1",
|
||||
"@agm/core": "1.0.0-beta.2",
|
||||
"@agm/js-marker-clusterer": "1.0.0-beta.2",
|
||||
"@angular/common": "5.0.1",
|
||||
"@angular/compiler": "5.0.1",
|
||||
"@angular/core": "5.0.1",
|
||||
"@angular/forms": "5.0.1",
|
||||
"@angular/platform-browser": "5.0.1",
|
||||
"@angular/platform-browser-dynamic": "5.0.1",
|
||||
"@angular/router": "5.0.1",
|
||||
"@angular/upgrade": "5.0.1",
|
||||
"@types/moment": "2.13.0",
|
||||
"chart.js": "2.7.1",
|
||||
"core-js": "2.5.1",
|
||||
"js-marker-clusterer": "1.0.0",
|
||||
"moment": "^2.19.2",
|
||||
"ng2-charts": "1.6.0",
|
||||
"ng2-validation-manager": "^0.3.1",
|
||||
"ngx-bootstrap": "1.6.6",
|
||||
"ngx-pagination": "^3.0.1",
|
||||
"rxjs": "5.4.2",
|
||||
"ng2-validation-manager": "0.5.3",
|
||||
"ngx-bootstrap": "2.0.0-beta.8",
|
||||
"ngx-pagination": "3.0.3",
|
||||
"rxjs": "5.5.2",
|
||||
"ts-helpers": "1.1.2",
|
||||
"webpack": "3.5.4",
|
||||
"webpack-dev-server": "2.7.1",
|
||||
"zone.js": "0.8.9"
|
||||
"webpack": "3.8.1",
|
||||
"webpack-dev-server": "2.9.4",
|
||||
"zone.js": "0.8.18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/cli": "1.3.0",
|
||||
"@angular/compiler-cli": "4.0.3",
|
||||
"@types/jasmine": "2.5.54",
|
||||
"@types/jasminewd2": "2.0.2",
|
||||
"@types/node": "8.0.24",
|
||||
"codelyzer": "2.1.1",
|
||||
"jasmine-core": "2.7.0",
|
||||
"@angular/cli": "1.5.0",
|
||||
"@angular/compiler-cli": "5.0.1",
|
||||
"@types/jasmine": "2.8.2",
|
||||
"@types/jasminewd2": "2.0.3",
|
||||
"@types/node": "8.0.52",
|
||||
"codelyzer": "4.0.1",
|
||||
"jasmine-core": "2.8.0",
|
||||
"jasmine-spec-reporter": "4.2.1",
|
||||
"karma": "1.7.0",
|
||||
"karma": "1.7.1",
|
||||
"karma-chrome-launcher": "2.2.0",
|
||||
"karma-cli": "1.0.1",
|
||||
"karma-coverage-istanbul-reporter": "1.3.0",
|
||||
"karma-jasmine": "1.1.0",
|
||||
"karma-jasmine-html-reporter": "0.2.2",
|
||||
"protractor": "5.1.2",
|
||||
"protractor": "5.2.0",
|
||||
"ts-node": "3.3.0",
|
||||
"tslint": "4.5.1",
|
||||
"tslint": "5.8.0",
|
||||
"typescript": "2.4.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { LocationStrategy, HashLocationStrategy } from '@angular/common';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
||||
|
@ -38,7 +38,7 @@ import { DashboardModule } from './dashboard/dashboard.module';
|
|||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
HttpModule,
|
||||
HttpClientModule,
|
||||
NgxPaginationModule,
|
||||
BsDropdownModule.forRoot(),
|
||||
TabsModule.forRoot(),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
@ -15,7 +14,6 @@ export class LoginComponent implements OnInit {
|
|||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private http: Http,
|
||||
private formBuilder: FormBuilder,
|
||||
private router: Router,
|
||||
private api: ApiService
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { ValidationManager } from 'ng2-validation-manager';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import {Router } from '@angular/router';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
@ -19,7 +18,6 @@ export class RegisterComponent {
|
|||
registerStatusError = 'Error received, please try again.';
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private formBuilder: FormBuilder,
|
||||
private router: Router,
|
||||
private api: ApiService,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
|
@ -17,7 +16,6 @@ export class AccountEditComponent implements OnInit {
|
|||
submitStatusError = 'Error received, please try again.';
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private formBuilder: FormBuilder,
|
||||
private api: ApiService,
|
||||
) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import { OrgTableComponent } from '../shared/org-table.component';
|
||||
import * as moment from 'moment';
|
||||
|
@ -40,7 +39,6 @@ export class AddDataComponent implements OnInit {
|
|||
minDate: any;
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private formBuilder: FormBuilder,
|
||||
private api: ApiService,
|
||||
) {
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
<ul>
|
||||
<li>
|
||||
<div class="text-muted">My Total Spend</div>
|
||||
<strong>{{ basicStats.user_sum | currency:'GBP':true:'1.2-2' }}</strong>
|
||||
<strong>{{ basicStats.user_sum | currency:'GBP':'symbol':'1.2-2' }}</strong>
|
||||
</li>
|
||||
<li>
|
||||
<div class="text-muted">Value to Local Economy</div>
|
||||
<strong>{{ basicStats.user_sum * 2.3 | currency:'GBP':true:'1.2-2' }}</strong>
|
||||
<strong>{{ basicStats.user_sum * 2.3 | currency:'GBP':'symbol':'1.2-2' }}</strong>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -34,7 +34,7 @@
|
|||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.today_sum | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div class="h4 mb-0">{{ basicStats.today_sum | currency:'GBP':'symbol':'1.2-2' }}</div>
|
||||
<div>Total Today</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
|
@ -46,7 +46,7 @@
|
|||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.today_sum / (basicStats.today_count ? basicStats.today_count : 1) | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div class="h4 mb-0">{{ basicStats.today_sum / (basicStats.today_count ? basicStats.today_count : 1) | currency:'GBP':'symbol':'1.2-2' }}</div>
|
||||
<div>Avg. Spend Today</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
|
@ -58,7 +58,7 @@
|
|||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.week_sum | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div class="h4 mb-0">{{ basicStats.week_sum | currency:'GBP':'symbol':'1.2-2' }}</div>
|
||||
<div>Last Week Total</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
|
@ -70,7 +70,7 @@
|
|||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.week_sum / (basicStats.week_count ? basicStats.week_count : 1) | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div class="h4 mb-0">{{ basicStats.week_sum / (basicStats.week_count ? basicStats.week_count : 1) | currency:'GBP':'symbol':'1.2-2' }}</div>
|
||||
<div>Last Week Avg. Spend</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
|
@ -82,7 +82,7 @@
|
|||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.month_sum | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div class="h4 mb-0">{{ basicStats.month_sum | currency:'GBP':'symbol':'1.2-2' }}</div>
|
||||
<div>Last Month Total</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
|
@ -94,7 +94,7 @@
|
|||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.month_sum / (basicStats.month_count ? basicStats.month_count : 1) | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div class="h4 mb-0">{{ basicStats.month_sum / (basicStats.month_count ? basicStats.month_count : 1) | currency:'GBP':'symbol':'1.2-2' }}</div>
|
||||
<div>Last Month Avg. Spend</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
|
@ -106,7 +106,7 @@
|
|||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.user_sum | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div class="h4 mb-0">{{ basicStats.user_sum | currency:'GBP':'symbol':'1.2-2' }}</div>
|
||||
<div>User Total</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
|
@ -118,7 +118,7 @@
|
|||
<div class="col-sm-6 col-lg-3">
|
||||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block">
|
||||
<div class="h4 mb-0">{{ basicStats.user_sum / (basicStats.user_count ? basicStats.user_count : 1) | currency:'GBP':true:'1.2-2' }}</div>
|
||||
<div class="h4 mb-0">{{ basicStats.user_sum / (basicStats.user_count ? basicStats.user_count : 1) | currency:'GBP':'symbol':'1.2-2' }}</div>
|
||||
<div>User Avg. Spend</div>
|
||||
<!-- <div class="progress progress-white progress-xs mt-3">
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%" attr.aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { Directive, Component, OnInit } from '@angular/core';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import { Router } from '@angular/router';
|
||||
import { GraphWidget } from '../widgets/graph-widget.component';
|
||||
|
@ -36,7 +35,6 @@ export class DashboardCustomerComponent implements OnInit {
|
|||
};
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private api: ApiService,
|
||||
) {
|
||||
this.api.basicStats().subscribe(
|
||||
|
|
|
@ -6,6 +6,7 @@ import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
|||
import { NgxPaginationModule } from 'ngx-pagination';
|
||||
import { AgmCoreModule, GoogleMapsAPIWrapper } from '@agm/core';
|
||||
import { AgmJsMarkerClustererModule } from '@agm/js-marker-clusterer';
|
||||
import { ModalModule } from 'ngx-bootstrap/modal';
|
||||
|
||||
import { CurrencyPipe } from '@angular/common';
|
||||
|
||||
|
@ -18,6 +19,7 @@ import { TransactionLogComponent } from './transaction-log.component';
|
|||
import { PayrollLogComponent } from './payroll-log.component';
|
||||
import { LeaderboardComponent } from './leaderboard.component';
|
||||
import { MapComponent } from './map.component';
|
||||
import { TrailMapComponent } from './trail-map.component';
|
||||
|
||||
import { GraphWidget } from '../widgets/graph-widget.component';
|
||||
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
||||
|
@ -47,6 +49,7 @@ import { environment } from '../../environments/environment';
|
|||
BsDropdownModule,
|
||||
NgxPaginationModule,
|
||||
DashboardRoutingModule,
|
||||
ModalModule.forRoot(),
|
||||
],
|
||||
declarations: [
|
||||
DashboardComponent,
|
||||
|
@ -62,6 +65,7 @@ import { environment } from '../../environments/environment';
|
|||
LeaderboardComponent,
|
||||
LeaderboardResultComponent,
|
||||
MapComponent,
|
||||
TrailMapComponent,
|
||||
FeedbackComponent,
|
||||
GraphWidget,
|
||||
OrgBarSnippetComponent,
|
||||
|
|
|
@ -15,6 +15,7 @@ import { TransactionLogComponent } from './transaction-log.component';
|
|||
import { PayrollLogComponent } from './payroll-log.component';
|
||||
import { LeaderboardComponent } from './leaderboard.component';
|
||||
import { MapComponent } from './map.component';
|
||||
import { TrailMapComponent } from './trail-map.component';
|
||||
|
||||
// Using child path to allow for FullLayout theming
|
||||
const routes: Routes = [
|
||||
|
@ -62,6 +63,11 @@ const routes: Routes = [
|
|||
component: MapComponent,
|
||||
data: { title: 'Purchase Map' },
|
||||
},
|
||||
{
|
||||
path: 'story-trail',
|
||||
component: TrailMapComponent,
|
||||
data: { title: 'Story Trail' },
|
||||
},
|
||||
{
|
||||
path: 'payroll-log',
|
||||
component: PayrollLogComponent,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
|
@ -16,7 +15,6 @@ export class FeedbackComponent implements OnInit {
|
|||
feedbackFormStatusError = 'Error received, please try again.';
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private formBuilder: FormBuilder,
|
||||
private api: ApiService,
|
||||
) {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
// import { PaginatePipe } from 'ngx-pagination';
|
||||
import {PaginationInstance} from 'ngx-pagination';
|
||||
|
@ -29,7 +28,6 @@ export class LeaderboardComponent implements OnInit {
|
|||
};
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private api: ApiService,
|
||||
) { }
|
||||
|
||||
|
|
|
@ -6,37 +6,66 @@
|
|||
<strong>Purchase Map</strong>
|
||||
<small>Required Data marked in <strong>bold</strong>.</small>
|
||||
</div>
|
||||
<div [ngSwitch]="dataReceived">
|
||||
<div *ngSwitchCase="'no'"class="card-block">
|
||||
<div class="alert alert-danger" role="alert">
|
||||
No map data received, check your connection.
|
||||
<div class="modal fade" bsModal #statusModal="bs-modal" [config]="{backdrop: false, animated: false}"
|
||||
tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-sm h-100 d-flex flex-column justify-content-center my-0">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title pull-left">Status</h4>
|
||||
<button type="button" class="close pull-right" aria-label="Close" (click)="statusModal.hide()">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div [ngSwitch]="dataReceived">
|
||||
<div *ngSwitchCase="'no'">
|
||||
<div class="alert alert-danger" role="alert">
|
||||
No map data received, check your connection.
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'loading'">
|
||||
<div class="alert alert-warning" role="alert">
|
||||
Map loading, please wait.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'yes'">
|
||||
<!-- this creates a google map on the page with the given lat/lng from -->
|
||||
<!-- the component as the initial center of the map: -->
|
||||
<agm-map
|
||||
(mapReady)="onMapReady($event)"
|
||||
[latitude]="lat"
|
||||
[longitude]="lng"
|
||||
[zoom]="zoom"
|
||||
[scaleControl]="true"
|
||||
(idle)="viewBoundsChanged($event)">
|
||||
<agm-marker-cluster maxZoom="13" imagePath="https://raw.githubusercontent.com/googlemaps/v3-utility-library/master/markerclustererplus/images/m">
|
||||
<agm-marker
|
||||
*ngFor="let m of markers"
|
||||
[latitude]="m.latitude"
|
||||
[longitude]="m.longitude"
|
||||
[label]="m.name[0]">
|
||||
|
||||
<agm-info-window>
|
||||
<strong>{{m.name}}</strong>
|
||||
</agm-info-window>
|
||||
</agm-marker>
|
||||
</agm-marker-cluster>
|
||||
</agm-map>
|
||||
</div>
|
||||
</div>
|
||||
<!-- this creates a google map on the page with the given lat/lng from -->
|
||||
<!-- the component as the initial center of the map: -->
|
||||
<agm-map (mapReady)="onMapReady($event)"
|
||||
[latitude]="lat"
|
||||
[longitude]="lng"
|
||||
[zoom]="zoom"
|
||||
[scaleControl]="true"
|
||||
(idle)="viewBoundsChanged($event)">
|
||||
<agm-marker-cluster maxZoom="13" imagePath="https://raw.githubusercontent.com/googlemaps/v3-utility-library/master/markerclustererplus/images/m">
|
||||
<agm-marker
|
||||
*ngFor="let m of markers"
|
||||
[latitude]="m.latitude"
|
||||
[longitude]="m.longitude"
|
||||
[label]="m.name[0]"
|
||||
[openInfoWindow]="false"
|
||||
(markerClick)="onMarkerClick(m, template)">
|
||||
</agm-marker>
|
||||
</agm-marker-cluster>
|
||||
</agm-map>
|
||||
<ng-template #template>
|
||||
<div class="modal-header d-flex justify-content-between">
|
||||
<img src="assets/img/lis_logo.png" class="w-15" alt="lis logo"><h4 class="modal-title">{{clickedMarker.name}}</h4>
|
||||
<button type="button" class="close pull-right" aria-label="Close" (click)="modalRef.hide()">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body text-right">
|
||||
<h5>Located at:</h5>
|
||||
<h6>{{clickedMarker.street_name}}</h6>
|
||||
<h6>{{clickedMarker.town}}</h6>
|
||||
<h6>{{clickedMarker.postcode}}</h6>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.row-->
|
||||
|
|
|
@ -1,35 +1,52 @@
|
|||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { Component, OnInit, AfterViewInit, Input, Output, EventEmitter, ViewChild, TemplateRef } from '@angular/core';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import { AgmCoreModule } from '@agm/core';
|
||||
import { BsModalService, ModalDirective } from 'ngx-bootstrap/modal';
|
||||
import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'map.component.html',
|
||||
})
|
||||
export class MapComponent implements OnInit {
|
||||
|
||||
export class MapComponent implements OnInit, AfterViewInit {
|
||||
@ViewChild('statusModal') myStatusModal: ModalDirective;
|
||||
lat: number = 54.0466;
|
||||
lng: number = -2.8007;
|
||||
zoom: number = 12;
|
||||
public modalRef: BsModalRef;
|
||||
clickedMarker: any;
|
||||
|
||||
dataReceived: string = 'yes';
|
||||
dataReceived: string = 'loading';
|
||||
|
||||
markers: Array<{latitude: number, longitude: number, name: string}>;
|
||||
|
||||
map: any;
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private api: ApiService,
|
||||
private modalService: BsModalService,
|
||||
) { }
|
||||
|
||||
ngOnInit(): void { }
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.myStatusModal.show();
|
||||
}
|
||||
|
||||
public onMapReady(map: any) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
openModal(template: TemplateRef<any>) {
|
||||
this.modalRef = this.modalService.show(template);
|
||||
}
|
||||
|
||||
public onMarkerClick(clickedMarker, template: TemplateRef<any>) {
|
||||
console.log(clickedMarker);
|
||||
this.clickedMarker = clickedMarker;
|
||||
this.openModal(template);
|
||||
}
|
||||
|
||||
public viewBoundsChanged() {
|
||||
console.log("finding bounds");
|
||||
const resp = this.map.getBounds();
|
||||
|
@ -50,11 +67,11 @@ export class MapComponent implements OnInit {
|
|||
}
|
||||
this.api.getMapData(mapData).subscribe(
|
||||
result => {
|
||||
this.dataReceived = 'yes';
|
||||
this.myStatusModal.hide();
|
||||
this.markers = result.suppliers;
|
||||
},
|
||||
error => {
|
||||
// this.dataReceived = 'no';
|
||||
this.dataReceived = 'no';
|
||||
console.log('Retrieval Error');
|
||||
console.log( error._body );
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
// import { PaginatePipe } from 'ngx-pagination';
|
||||
import {PaginationInstance} from 'ngx-pagination';
|
||||
|
@ -27,7 +26,6 @@ export class PayrollLogComponent implements OnInit {
|
|||
};
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private api: ApiService,
|
||||
) {
|
||||
this.myDate = moment().format('YYYY-MM-DD[T]HH:mm');
|
||||
|
|
73
src/app/dashboard/trail-map.component.html
Normal file
73
src/app/dashboard/trail-map.component.html
Normal file
|
@ -0,0 +1,73 @@
|
|||
<div class="animated fadeIn">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<strong>Purchase Map</strong>
|
||||
<small>Required Data marked in <strong>bold</strong>.</small>
|
||||
</div>
|
||||
<div class="modal fade" bsModal #statusModal="bs-modal" [config]="{backdrop: false, animated: false}"
|
||||
tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-sm h-100 d-flex flex-column justify-content-center my-0">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title pull-left">Status</h4>
|
||||
<button type="button" class="close pull-right" aria-label="Close" (click)="statusModal.hide()">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div [ngSwitch]="dataReceived">
|
||||
<div *ngSwitchCase="'no'">
|
||||
<div class="alert alert-danger" role="alert">
|
||||
No map data received, check your connection.
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'loading'">
|
||||
<div class="alert alert-warning" role="alert">
|
||||
Map loading, please wait.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- this creates a google map on the page with the given lat/lng from -->
|
||||
<!-- the component as the initial center of the map: -->
|
||||
<agm-map
|
||||
(mapReady)="onMapReady($event)"
|
||||
[latitude]="lat"
|
||||
[longitude]="lng"
|
||||
[zoom]="zoom"
|
||||
[scaleControl]="true"
|
||||
(idle)="viewBoundsChanged($event)">
|
||||
<agm-marker-cluster maxZoom="13" imagePath="https://raw.githubusercontent.com/googlemaps/v3-utility-library/master/markerclustererplus/images/m">
|
||||
<agm-marker
|
||||
*ngFor="let m of markers"
|
||||
[iconUrl]="'/assets/img/map-pin-lis.png'"
|
||||
[latitude]="m.latitude"
|
||||
[longitude]="m.longitude"
|
||||
[openInfoWindow]="false"
|
||||
(markerClick)="onMarkerClick(m, template)">
|
||||
</agm-marker>
|
||||
</agm-marker-cluster>
|
||||
</agm-map>
|
||||
<ng-template #template>
|
||||
<div class="modal-header d-flex justify-content-between">
|
||||
<img src="assets/img/lis_logo.png" class="w-15" alt="lis logo"><h4 class="modal-title">{{clickedMarker.name}}</h4>
|
||||
<button type="button" class="close pull-right" aria-label="Close" (click)="modalRef.hide()">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body text-right">
|
||||
<h5>Located at:</h5>
|
||||
<h6>{{clickedMarker.street_name}}</h6>
|
||||
<h6>{{clickedMarker.town}}</h6>
|
||||
<h6>{{clickedMarker.postcode}}</h6>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.row-->
|
||||
</div>
|
83
src/app/dashboard/trail-map.component.ts
Normal file
83
src/app/dashboard/trail-map.component.ts
Normal file
|
@ -0,0 +1,83 @@
|
|||
import { Component, OnInit, AfterViewInit, Input, Output, EventEmitter, ViewChild, TemplateRef } from '@angular/core';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import { AgmCoreModule } from '@agm/core';
|
||||
import { BsModalService, ModalDirective } from 'ngx-bootstrap/modal';
|
||||
import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'trail-map.component.html',
|
||||
})
|
||||
export class TrailMapComponent implements OnInit, AfterViewInit {
|
||||
@ViewChild('statusModal') myStatusModal: ModalDirective;
|
||||
lat: number = 54.0466;
|
||||
lng: number = -2.8007;
|
||||
zoom: number = 12;
|
||||
public modalRef: BsModalRef;
|
||||
clickedMarker: any;
|
||||
|
||||
dataReceived: string = 'loading';
|
||||
|
||||
markers: Array<{latitude: number, longitude: number, name: string}>;
|
||||
|
||||
map: any;
|
||||
|
||||
constructor(
|
||||
private api: ApiService,
|
||||
private modalService: BsModalService,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void { }
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.myStatusModal.show();
|
||||
}
|
||||
|
||||
public onMapReady(map: any) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
openModal(template: TemplateRef<any>) {
|
||||
this.modalRef = this.modalService.show(template);
|
||||
}
|
||||
|
||||
public onMarkerClick(clickedMarker, template: TemplateRef<any>) {
|
||||
console.log(clickedMarker);
|
||||
this.clickedMarker = clickedMarker;
|
||||
this.openModal(template);
|
||||
}
|
||||
|
||||
public viewBoundsChanged() {
|
||||
console.log("finding bounds");
|
||||
const resp = this.map.getBounds();
|
||||
console.log("found bounds");
|
||||
console.log(resp.getNorthEast().lat());
|
||||
console.log(resp.getNorthEast().lng());
|
||||
console.log(resp.getSouthWest().lat());
|
||||
console.log(resp.getSouthWest().lng());
|
||||
const mapData = {
|
||||
north_east: {
|
||||
latitude: resp.getNorthEast().lat(),
|
||||
longitude: resp.getNorthEast().lng()
|
||||
},
|
||||
south_west: {
|
||||
latitude: resp.getSouthWest().lat(),
|
||||
longitude: resp.getSouthWest().lng()
|
||||
},
|
||||
}
|
||||
this.api.getLisData(mapData).subscribe(
|
||||
result => {
|
||||
this.myStatusModal.hide();
|
||||
this.markers = result.locations;
|
||||
},
|
||||
error => {
|
||||
this.dataReceived = 'no';
|
||||
console.log('Retrieval Error');
|
||||
console.log( error._body );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { Http, Response } from '@angular/http';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
// import { PaginatePipe } from 'ngx-pagination';
|
||||
import {PaginationInstance} from 'ngx-pagination';
|
||||
|
@ -28,7 +27,6 @@ export class TransactionLogComponent implements OnInit {
|
|||
};
|
||||
|
||||
constructor(
|
||||
private http: Http,
|
||||
private api: ApiService,
|
||||
) {
|
||||
this.myDate = moment().format('YYYY-MM-DD[T]HH:mm');
|
||||
|
|
|
@ -45,6 +45,11 @@
|
|||
<i class="icon-map"></i> Purchase Map
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/story-trail']">
|
||||
<i class="icon-map"></i> Story Trail
|
||||
</a>
|
||||
</li>
|
||||
<li *ngIf="accountType == 'customer'" class="nav-item">
|
||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/leaderboard']">
|
||||
<i class="icon-basket"></i> Leaderboard
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { environment } from '../../environments/environment';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
@ -11,7 +11,7 @@ export class ApiService {
|
|||
private apiUrl = environment.apiUrl;
|
||||
private sessionKey: string = null;
|
||||
constructor(
|
||||
private http: Http,
|
||||
private http: HttpClient,
|
||||
) {
|
||||
if (localStorage.getItem('sessionKey') ) {
|
||||
this.sessionKey = localStorage.getItem('sessionKey');
|
||||
|
@ -20,10 +20,10 @@ export class ApiService {
|
|||
|
||||
public post(url: string, data: any = {}) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + url,
|
||||
data
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
|
||||
// Login API
|
||||
|
@ -46,21 +46,21 @@ export class ApiService {
|
|||
}
|
||||
|
||||
public register(data) {
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/register',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
|
||||
public login(data) {
|
||||
return this.http
|
||||
.post(
|
||||
.post<any>(
|
||||
this.apiUrl + '/login',
|
||||
data
|
||||
)
|
||||
.map(
|
||||
result => {
|
||||
const json = result.json();
|
||||
const json = result;
|
||||
this.setSessionKey(json.session_key);
|
||||
this.setUserInfo(
|
||||
json.email,
|
||||
|
@ -76,7 +76,7 @@ export class ApiService {
|
|||
console.log(this.sessionKey);
|
||||
const key = this.sessionKey;
|
||||
return this.http
|
||||
.post(
|
||||
.post<any>(
|
||||
this.apiUrl + '/logout',
|
||||
{ session_key : key },
|
||||
)
|
||||
|
@ -84,7 +84,7 @@ export class ApiService {
|
|||
response => {
|
||||
localStorage.clear();
|
||||
this.sessionKey = null;
|
||||
return response.json();
|
||||
return response;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -97,82 +97,82 @@ export class ApiService {
|
|||
data.version_code = 'dev';
|
||||
data.version_number = 'dev';
|
||||
console.log(data);
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/feedback',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
|
||||
// gets transaction list for log
|
||||
|
||||
public transList(data) {
|
||||
const key = this.sessionKey;
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/outgoing-transactions',
|
||||
{
|
||||
session_key : key,
|
||||
page : data
|
||||
}
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
|
||||
// Searches organisations used for transaction submission
|
||||
|
||||
public search(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/search',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
|
||||
// Uploads a transaction
|
||||
|
||||
public upload(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/upload',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
|
||||
// gets payroll list for log
|
||||
|
||||
public payrollList(data) {
|
||||
const key = this.sessionKey;
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/v1/organisation/payroll',
|
||||
{
|
||||
session_key : key,
|
||||
page : data
|
||||
}
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
|
||||
// handles Org data added
|
||||
|
||||
public orgPayroll(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/v1/organisation/payroll/add',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
|
||||
public orgSupplier(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/v1/organisation/supplier/add',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
|
||||
public orgEmployee(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/v1/organisation/employee/add',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
|
||||
// Handles user data interaction
|
||||
|
@ -204,18 +204,18 @@ export class ApiService {
|
|||
|
||||
public accountFullLoad() {
|
||||
const key = this.sessionKey;
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/user',
|
||||
{ session_key : key },
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
|
||||
public accountEditUpdate(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/user/account',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
|
||||
// Deletes account details on logout
|
||||
|
@ -257,33 +257,42 @@ export class ApiService {
|
|||
type: string,
|
||||
page: number) {
|
||||
const key = this.sessionKey;
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/stats/leaderboard/paged',
|
||||
{
|
||||
session_key : key,
|
||||
type : type,
|
||||
page: page,
|
||||
}
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
|
||||
// Initial Map Data
|
||||
public getMapData(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/v1/supplier/location',
|
||||
data
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
|
||||
// Load LIS Data
|
||||
public getLisData(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/v1/supplier/location/lis',
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
// Basic Customer User stats API
|
||||
public basicStats() {
|
||||
const key = this.sessionKey;
|
||||
return this.http.post(
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/stats',
|
||||
{
|
||||
session_key : key,
|
||||
}
|
||||
).map( response => response.json() );
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<td>{{ leaderboard.position }}</td>
|
||||
<td class="text-truncate">{{ leaderboard.display_name }}</td>
|
||||
<td>{{ listType.includes('total') ? (leaderboard.value | currency:'GBP':true:'1.2-2') : (leaderboard.value | number:'1.0-0') }}</td>
|
||||
<td>{{ listType.includes('total') ? (leaderboard.value | currency:'GBP':'symbol':'1.2-2') : (leaderboard.value | number:'1.0-0') }}</td>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<td>{{payrollDate}}</td>
|
||||
<td>{{payroll.gross_payroll | currency:'GBP':true:'1.2-2' }}</td>
|
||||
<td>{{payroll.gross_payroll | currency:'GBP':'symbol':'1.2-2' }}</td>
|
||||
<td>{{payroll.employee_amount}}</td>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<td>{{transaction.seller}}</td>
|
||||
<td>{{transaction.value | currency:'GBP':true:'1.2-2' }}</td>
|
||||
<td>{{transaction.value | currency:'GBP':'symbol':'1.2-2' }}</td>
|
||||
<td>{{transactionDate}}</td>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</li>
|
||||
<li class="hidden-sm-down">
|
||||
<div class="text-muted">Money Spent This Month</div>
|
||||
<strong>{{ thisMonthPurchasesTotal | currency:'GBP':true:'1.2-2'}}</strong>
|
||||
<strong>{{ thisMonthPurchasesTotal | currency:'GBP':'symbol':'1.2-2'}}</strong>
|
||||
</li>
|
||||
<li class="hidden-sm-down">
|
||||
<div class="text-muted">Customers Today</div>
|
||||
|
@ -15,7 +15,7 @@
|
|||
</li>
|
||||
<li class="hidden-sm-down">
|
||||
<div class="text-muted">Average Transaction Today</div>
|
||||
<strong>{{ ( todaySalesTotal / todaySalesCount ) || 0 | currency:'GBP':true:'1.2-2'}}</strong>
|
||||
<strong>{{ ( todaySalesTotal / todaySalesCount ) || 0 | currency:'GBP':'symbol':'1.2-2'}}</strong>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<i [ngClass]="graphIcon"></i>
|
||||
</button>
|
||||
<h4 *ngIf="dataType == availableDataTypes.number" class="mb-0">{{ graphSum }}</h4>
|
||||
<h4 *ngIf="dataType == availableDataTypes.currency" class="mb-0">{{ graphSum | currency:'GBP':true:'1.2-2' }}</h4>
|
||||
<h4 *ngIf="dataType == availableDataTypes.currency" class="mb-0">{{ graphSum | currency:'GBP':'symbol':'1.2-2' }}</h4>
|
||||
<p>{{ graphTitle }}</p>
|
||||
</div>
|
||||
<div class="chart-wrapper px-3" style="height:70px;">
|
||||
|
|
|
@ -137,7 +137,7 @@ export class GraphWidget implements OnInit {
|
|||
private tooltipLabelCallback(tooltipItem: any, data: any) {
|
||||
const value = tooltipItem.yLabel;
|
||||
if ( this.dataType === DataType.currency ) {
|
||||
return this.currencyPipe.transform(value, 'GBP', true, '1.2-2');
|
||||
return this.currencyPipe.transform(value, 'GBP', 'symbol', '1.2-2');
|
||||
}
|
||||
return value || '0';
|
||||
}
|
||||
|
|
BIN
src/assets/img/lis_logo.png
Normal file
BIN
src/assets/img/lis_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 260 KiB |
BIN
src/assets/img/map-pin-lis.png
Normal file
BIN
src/assets/img/map-pin-lis.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
|
@ -20,6 +20,10 @@ agm-map {
|
|||
height: 75vh;
|
||||
}
|
||||
|
||||
.w-15 {
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
// white title font variant on type-2 as defined in _widgets.css
|
||||
.horizontal-bars {
|
||||
padding: 0;
|
||||
|
|
Reference in a new issue