| "version": 1, | "version": 1, | ||||
| "newProjectRoot": "projects", | "newProjectRoot": "projects", | ||||
| "projects": { | "projects": { | ||||
| "lot-web-ui": { | |||||
| "iot-web-ui": { | |||||
| "projectType": "application", | "projectType": "application", | ||||
| "schematics": { | "schematics": { | ||||
| "@schematics/angular:component": { | "@schematics/angular:component": { | ||||
| "build": { | "build": { | ||||
| "builder": "@angular-devkit/build-angular:browser", | "builder": "@angular-devkit/build-angular:browser", | ||||
| "options": { | "options": { | ||||
| "outputPath": "dist/lot-web-ui", | |||||
| "outputPath": "dist/iot-web-ui", | |||||
| "index": "src/index.html", | "index": "src/index.html", | ||||
| "main": "src/main.ts", | "main": "src/main.ts", | ||||
| "polyfills": [ | "polyfills": [ | ||||
| "src/assets" | "src/assets" | ||||
| ], | ], | ||||
| "styles": [ | "styles": [ | ||||
| "@angular/material/prebuilt-themes/indigo-pink.css", | |||||
| "src/styles.scss" | "src/styles.scss" | ||||
| ], | ], | ||||
| "scripts": [] | "scripts": [] | ||||
| "builder": "@angular-devkit/build-angular:dev-server", | "builder": "@angular-devkit/build-angular:dev-server", | ||||
| "configurations": { | "configurations": { | ||||
| "production": { | "production": { | ||||
| "browserTarget": "lot-web-ui:build:production" | |||||
| "browserTarget": "iot-web-ui:build:production" | |||||
| }, | }, | ||||
| "development": { | "development": { | ||||
| "browserTarget": "lot-web-ui:build:development" | |||||
| "browserTarget": "iot-web-ui:build:development" | |||||
| } | } | ||||
| }, | }, | ||||
| "defaultConfiguration": "development" | "defaultConfiguration": "development" | ||||
| "extract-i18n": { | "extract-i18n": { | ||||
| "builder": "@angular-devkit/build-angular:extract-i18n", | "builder": "@angular-devkit/build-angular:extract-i18n", | ||||
| "options": { | "options": { | ||||
| "browserTarget": "lot-web-ui:build" | |||||
| "browserTarget": "iot-web-ui:build" | |||||
| } | } | ||||
| }, | }, | ||||
| "test": { | "test": { | ||||
| "src/assets" | "src/assets" | ||||
| ], | ], | ||||
| "styles": [ | "styles": [ | ||||
| "@angular/material/prebuilt-themes/indigo-pink.css", | |||||
| "src/styles.scss" | "src/styles.scss" | ||||
| ], | ], | ||||
| "scripts": [] | "scripts": [] |
| import { NgModule } from '@angular/core'; | import { NgModule } from '@angular/core'; | ||||
| import { RouterModule, Routes } from '@angular/router'; | import { RouterModule, Routes } from '@angular/router'; | ||||
| const routes: Routes = []; | |||||
| const routes: Routes = [ | |||||
| { path: '', | |||||
| redirectTo: '/overview', | |||||
| pathMatch: 'full' | |||||
| }, | |||||
| { path: 'overview', | |||||
| loadChildren: () => import('./modules/overview/overview.module').then(m => m.OverviewModule) | |||||
| }, | |||||
| ]; | |||||
| @NgModule({ | @NgModule({ | ||||
| imports: [RouterModule.forRoot(routes)], | imports: [RouterModule.forRoot(routes)], |
| <app-map></app-map> | |||||
| <router-outlet></router-outlet> |
| expect(app).toBeTruthy(); | expect(app).toBeTruthy(); | ||||
| }); | }); | ||||
| it(`should have as title 'lot-web-ui'`, () => { | |||||
| it(`should have as title 'iot-web-ui'`, () => { | |||||
| const fixture = TestBed.createComponent(AppComponent); | const fixture = TestBed.createComponent(AppComponent); | ||||
| const app = fixture.componentInstance; | const app = fixture.componentInstance; | ||||
| expect(app.title).toEqual('lot-web-ui'); | |||||
| expect(app.title).toEqual('iot-web-ui'); | |||||
| }); | }); | ||||
| it('should render title', () => { | it('should render title', () => { | ||||
| const fixture = TestBed.createComponent(AppComponent); | const fixture = TestBed.createComponent(AppComponent); | ||||
| fixture.detectChanges(); | fixture.detectChanges(); | ||||
| const compiled = fixture.nativeElement as HTMLElement; | const compiled = fixture.nativeElement as HTMLElement; | ||||
| expect(compiled.querySelector('.content span')?.textContent).toContain('lot-web-ui app is running!'); | |||||
| expect(compiled.querySelector('.content span')?.textContent).toContain('iot-web-ui app is running!'); | |||||
| }); | }); | ||||
| }); | }); |
| #map { | #map { | ||||
| height: 100%; | height: 100%; | ||||
| } | } | ||||
| p { | |||||
| margin: 0 0 0 16px !important; | |||||
| } | |||||
| .box-custom { | |||||
| color: #F33152; | |||||
| padding: 3px 2px; | |||||
| background-color: rbg(243,49,82,0.1); | |||||
| } |
| tiles.addTo(this.map); | tiles.addTo(this.map); | ||||
| //add marker | //add marker | ||||
| let popupContent = `<div>Vinhome quận 9</div> | let popupContent = `<div>Vinhome quận 9</div> | ||||
| <a href="" target="_blank">Xem chi tiết</a>`; | |||||
| <a href="/overview/overall-ground" target="_blank">Xem chi tiết</a>`; | |||||
| let fireContent = `<div>Tọa độ: 10.8661° N, 106.8029° E</div> | |||||
| <div>Thời gian cảnh báo: 23:23:00</div> | |||||
| <a href="" target="_blank">Xem chi tiết</a>` | |||||
| let fireContent = `<div style="color: #F33152; | |||||
| padding: 2px 13px; | |||||
| background-color: rgba(243, 49, 82, 0.1); | |||||
| border-radius: 20px; | |||||
| text-align: center; | |||||
| width: 100px;"> | |||||
| Sự cố cháy | |||||
| </div> | |||||
| <div><strong>Địa điểm:</strong> 120 Xa Lộ Hà Nội, Thành Phố, Thủ Đức, Thành phố Hồ Chí Minh</div> | |||||
| <div><strong>Tọa độ:</strong> 10.8661° N, 106.8029° E</div> | |||||
| <div><strong>Thời gian:</strong> 01:54, 16/05/2022</div> | |||||
| <a href="/overview/overall-ground" target="_blank">Xem chi tiết</a>` | |||||
| L.marker([10.8356, 106.8300], {icon: this.houseIcon}) | L.marker([10.8356, 106.8300], {icon: this.houseIcon}) | ||||
| .addTo(this.map) | .addTo(this.map) | ||||
| .bindPopup(popupContent); | .bindPopup(popupContent); |
| <div class="p-3" | |||||
| fxLayout="row" fxLayoutAlign="space-around center" fxLayoutGap="20px"> | |||||
| <img src="assets/images/ground.png" fxFlex="70"> | |||||
| <div fxLayout="column" fxLayoutGap="50px"> | |||||
| <button mat-flat-button | |||||
| [ngClass]="{ 'red-bg': !isClicked, 'green-bg': isClicked }" | |||||
| (click)="toggleColor()">{{!isClicked ? 'ARM SYSTEM' : 'DISARM SYSTEM'}}</button> | |||||
| <button mat-flat-button color="primary">LIGHT ON</button> | |||||
| <button mat-flat-button color="primary">BELL ON</button> | |||||
| </div> | |||||
| </div> | |||||
| button { | |||||
| padding: 50px 30px !important; | |||||
| } | |||||
| .red-bg { | |||||
| background-color: red !important; | |||||
| color: white !important; | |||||
| } | |||||
| .green-bg { | |||||
| background-color: green !important; | |||||
| color: white !important; | |||||
| } |
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||||
| import { OverallGroundComponent } from './overall-ground.component'; | |||||
| describe('OverallGroundComponent', () => { | |||||
| let component: OverallGroundComponent; | |||||
| let fixture: ComponentFixture<OverallGroundComponent>; | |||||
| beforeEach(() => { | |||||
| TestBed.configureTestingModule({ | |||||
| declarations: [OverallGroundComponent] | |||||
| }); | |||||
| fixture = TestBed.createComponent(OverallGroundComponent); | |||||
| component = fixture.componentInstance; | |||||
| fixture.detectChanges(); | |||||
| }); | |||||
| it('should create', () => { | |||||
| expect(component).toBeTruthy(); | |||||
| }); | |||||
| }); |
| import { Component } from '@angular/core'; | |||||
| @Component({ | |||||
| selector: 'app-overall-ground', | |||||
| templateUrl: './overall-ground.component.html', | |||||
| styleUrls: ['./overall-ground.component.scss'] | |||||
| }) | |||||
| export class OverallGroundComponent { | |||||
| isClicked = false; | |||||
| toggleColor(): void { | |||||
| this.isClicked = !this.isClicked; | |||||
| } | |||||
| } |
| import { NgModule } from '@angular/core'; | |||||
| import { CommonModule } from '@angular/common'; | |||||
| import {OverallGroundComponent} from "./overall-ground/overall-ground.component"; | |||||
| import {RouterModule} from "@angular/router"; | |||||
| import {overviewRoutes} from "./overview.routing"; | |||||
| import {MapComponent} from "./map/map.component"; | |||||
| import {SharedMaterialModule} from "../../shared/shared-material.module"; | |||||
| import {MatIconModule} from "@angular/material/icon"; | |||||
| @NgModule({ | |||||
| declarations: [ | |||||
| OverallGroundComponent, | |||||
| MapComponent | |||||
| ], | |||||
| imports: [ | |||||
| CommonModule, | |||||
| RouterModule.forChild(overviewRoutes), | |||||
| SharedMaterialModule, | |||||
| MatIconModule | |||||
| ] | |||||
| }) | |||||
| export class OverviewModule { } |
| import {Routes} from "@angular/router"; | |||||
| import {MapComponent} from "./map/map.component"; | |||||
| import {OverallGroundComponent} from "./overall-ground/overall-ground.component"; | |||||
| export const overviewRoutes: Routes = [ | |||||
| { | |||||
| path: '', | |||||
| component: MapComponent, | |||||
| }, | |||||
| { | |||||
| path: 'overall-ground', | |||||
| component: OverallGroundComponent | |||||
| } | |||||
| ]; | |||||
| import {CommonModule} from "@angular/common"; | import {CommonModule} from "@angular/common"; | ||||
| import {SharedMaterialModule} from "../shared-material.module"; | import {SharedMaterialModule} from "../shared-material.module"; | ||||
| import {RouterModule} from "@angular/router"; | import {RouterModule} from "@angular/router"; | ||||
| import {MapComponent} from "./map/map.component"; | |||||
| const components = [ | const components = [ | ||||
| MapComponent, | |||||
| ]; | ]; | ||||
| @NgModule({ | @NgModule({ | ||||
| declarations: [ | declarations: [ | ||||
| ...components, | |||||
| // ...components, | |||||
| ], | ], | ||||
| imports: [ | imports: [ | ||||
| CommonModule, | CommonModule, | ||||
| RouterModule, | RouterModule, | ||||
| ], | ], | ||||
| exports: [ | exports: [ | ||||
| ...components, | |||||
| // ...components, | |||||
| ], | ], | ||||
| providers: [] | providers: [] |
| import { NgModule } from "@angular/core"; | import { NgModule } from "@angular/core"; | ||||
| import {MatIconModule} from "@angular/material/icon"; | |||||
| import {MatCardModule} from "@angular/material/card"; | |||||
| import {MatDividerModule} from "@angular/material/divider"; | |||||
| import {MatListModule} from "@angular/material/list"; | |||||
| import {MatExpansionModule} from "@angular/material/expansion"; | |||||
| import {MatInputModule} from "@angular/material/input"; | |||||
| import { FlexLayoutModule } from "@angular/flex-layout"; | |||||
| import {MatButtonModule} from "@angular/material/button"; | import {MatButtonModule} from "@angular/material/button"; | ||||
| import {MatSidenavModule} from "@angular/material/sidenav"; | |||||
| import {MatToolbarModule} from "@angular/material/toolbar"; | |||||
| import {MatTableModule} from "@angular/material/table"; | |||||
| import {MatPaginatorModule} from "@angular/material/paginator"; | |||||
| import {MatMenuModule} from "@angular/material/menu"; | |||||
| import {MatSortModule} from "@angular/material/sort"; | |||||
| import {MatSelectModule} from "@angular/material/select"; | |||||
| import {MatCheckboxModule} from "@angular/material/checkbox"; | |||||
| import {MatDialogModule} from "@angular/material/dialog"; | |||||
| import {MatNativeDateModule} from "@angular/material/core"; | |||||
| import {MatTooltipModule} from "@angular/material/tooltip"; | |||||
| import {FormsModule} from "@angular/forms"; | |||||
| import {MatDatepickerModule} from "@angular/material/datepicker"; | |||||
| import {MatBadgeModule} from "@angular/material/badge"; | |||||
| import {MatTreeModule} from "@angular/material/tree"; | |||||
| import {ClipboardModule} from "@angular/cdk/clipboard"; | |||||
| @NgModule({ | @NgModule({ | ||||
| exports: [ | exports: [ | ||||
| MatCardModule, | |||||
| MatIconModule, | |||||
| MatDividerModule, | |||||
| MatListModule, | |||||
| MatExpansionModule, | |||||
| MatInputModule, | |||||
| MatButtonModule, | MatButtonModule, | ||||
| MatSidenavModule, | |||||
| MatToolbarModule, | |||||
| MatTableModule, | |||||
| MatPaginatorModule, | |||||
| MatMenuModule, | |||||
| MatSortModule, | |||||
| MatDialogModule, | |||||
| FormsModule, | |||||
| MatSelectModule, | |||||
| MatDatepickerModule, | |||||
| MatNativeDateModule, | |||||
| MatCheckboxModule, | |||||
| MatTooltipModule, | |||||
| MatBadgeModule, | |||||
| MatTreeModule, | |||||
| ClipboardModule | |||||
| FlexLayoutModule | |||||
| ] | ] | ||||
| }) | }) | ||||
| export class SharedMaterialModule {} | export class SharedMaterialModule {} |
| @mixin mixPaddingMargin($i, $px) { | |||||
| // reusable code here | |||||
| .mt-#{$i} { | |||||
| margin-top: $px * 1px !important; | |||||
| } | |||||
| .mb-#{$i} { | |||||
| margin-bottom: $px * 1px !important; | |||||
| } | |||||
| .ms-#{$i} { | |||||
| margin-left: $px * 1px !important; | |||||
| } | |||||
| .me-#{$i} { | |||||
| margin-right: $px * 1px !important; | |||||
| } | |||||
| .mx-#{$i} { | |||||
| margin-left: $px * 1px !important; | |||||
| margin-right: $px * 1px !important; | |||||
| } | |||||
| .my-#{$i} { | |||||
| margin-top: $px * 1px !important; | |||||
| margin-bottom: $px * 1px !important; | |||||
| } | |||||
| .p-#{$i} { | |||||
| padding: $px * 1px !important; | |||||
| } | |||||
| .pt-#{$i} { | |||||
| padding-top: $px * 1px !important; | |||||
| } | |||||
| .pb-#{$i} { | |||||
| padding-bottom: $px * 1px !important; | |||||
| } | |||||
| .ps-#{$i} { | |||||
| padding-left: $px * 1px !important; | |||||
| } | |||||
| .pe-#{$i} { | |||||
| padding-right: $px * 1px !important; | |||||
| } | |||||
| .px-#{$i} { | |||||
| padding-left: $px * 1px !important; | |||||
| padding-right: $px * 1px !important; | |||||
| } | |||||
| .py-#{$i} { | |||||
| padding-top: $px * 1px !important; | |||||
| padding-bottom: $px * 1px !important; | |||||
| } | |||||
| .mt--#{$i} { | |||||
| margin-top: $px * -1px !important; | |||||
| } | |||||
| .mb--#{$i} { | |||||
| margin-bottom: $px * -1px !important; | |||||
| } | |||||
| .ms--#{$i} { | |||||
| margin-left: $px * -1px !important; | |||||
| } | |||||
| .me--#{$i} { | |||||
| margin-right: $px * -1px !important; | |||||
| } | |||||
| .mx--#{$i} { | |||||
| margin-left: $px * -1px !important; | |||||
| margin-right: $px * -1px !important; | |||||
| } | |||||
| .my--#{$i} { | |||||
| margin-top: $px * -1px !important; | |||||
| margin-bottom: $px * -1px !important; | |||||
| } | |||||
| } | |||||
| @mixin mixPosition($i, $px) { | |||||
| .top-#{$i} { | |||||
| top: $px * 1px !important; | |||||
| } | |||||
| .top--#{$i} { | |||||
| top: $px * -1px !important; | |||||
| } | |||||
| .right-#{$i} { | |||||
| right: $px * 1px !important; | |||||
| } | |||||
| .bottom-#{$i} { | |||||
| bottom: $px * 1px !important; | |||||
| } | |||||
| .bottom--#{$i} { | |||||
| bottom: $px * -1px !important; | |||||
| } | |||||
| .left-#{$i} { | |||||
| left: $px * 1px !important; | |||||
| } | |||||
| } | |||||
| $pxs: 0 0, 1 4, 2 8, 3 16, 4 24, 5 32, 6 48, 7 56, 8 62, 9 70, 10 78 ; | |||||
| @each $i, $px in $pxs { | |||||
| @include mixPaddingMargin($i, $px); | |||||
| @include mixPosition($i, $px); | |||||
| } | |||||
| @each $weight in 100, 200, 300, 400, 500, 600, 700, 800, 900 { | |||||
| [mat-weight='#{$weight}'] { | |||||
| font-weight: $weight !important; | |||||
| } | |||||
| } | |||||
| @mixin mixFontSize($i, $rem) { | |||||
| // reusable code here | |||||
| .fz-#{$i} { | |||||
| font-size: $rem * 1rem !important; | |||||
| } | |||||
| } | |||||
| $rems: 0 0.5, 1 0.75, 2 1, 3 1.25, 4 1.5, 5 1.75, 6 2, 7 2.25, 8 2.5, 9 2.75, 10 3; | |||||
| @each $i, $rem in $rems { | |||||
| @include mixFontSize($i, $rem); | |||||
| } |
| <html lang="en"> | <html lang="en"> | ||||
| <head> | <head> | ||||
| <meta charset="utf-8"> | <meta charset="utf-8"> | ||||
| <title>LotWebUi</title> | |||||
| <title>IotWebUi</title> | |||||
| <base href="/"> | <base href="/"> | ||||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||
| <link rel="icon" type="image/x-icon" href="favicon.ico"> | <link rel="icon" type="image/x-icon" href="favicon.ico"> |
| /* You can add global styles to this file, and also import other style files */ | /* You can add global styles to this file, and also import other style files */ | ||||
| @import "assets/style/scss/common"; | |||||
| html, body { height: 100%; } | |||||
| body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } |