feat(dashboard): add contacts and room selector components
27
src/app/@core/data/data.module.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { UserService } from './users.service';
|
||||
|
||||
const SERVICES = [
|
||||
UserService,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
],
|
||||
providers: [
|
||||
...SERVICES,
|
||||
],
|
||||
})
|
||||
export class DataModule {
|
||||
static forRoot(): ModuleWithProviders {
|
||||
return <ModuleWithProviders>{
|
||||
ngModule: DataModule,
|
||||
providers: [
|
||||
...SERVICES,
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
35
src/app/@core/data/users.service.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
let counter = 0;
|
||||
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
|
||||
private users = {
|
||||
nick: { name: 'Nick Jones', picture: 'assets/images/nick.png' },
|
||||
eva: { name: 'Eva Moor', picture: 'assets/images/eva.png' },
|
||||
jack: { name: 'Jack Williams', picture: 'assets/images/jack.png' },
|
||||
lee: { name: 'Lee Wong', picture: 'assets/images/lee.png' },
|
||||
alan: { name: 'Alan Thompson', picture: 'assets/images/alan.png' },
|
||||
kate: { name: 'Kate Martinez', picture: 'assets/images/kate.png' },
|
||||
};
|
||||
|
||||
private userArray: any[];
|
||||
|
||||
constructor() {
|
||||
// this.userArray = Object.values(this.users);
|
||||
}
|
||||
|
||||
getUsers() {
|
||||
return this.users;
|
||||
}
|
||||
|
||||
getUserArray() {
|
||||
return this.userArray;
|
||||
}
|
||||
|
||||
getUser() {
|
||||
counter = (counter + 1) % this.userArray.length;
|
||||
return this.userArray[counter];
|
||||
}
|
||||
}
|
||||
13
src/app/pages/dashboard/contacts/contacts.component.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<nga-card size="xmedium">
|
||||
<nga-tabset fullWidth>
|
||||
<nga-tab tabTitle="Contacts">
|
||||
<div class="contact" *ngFor="let c of contacts">
|
||||
<nga-user [picture]="c.user.picture" [name]="c.user.name" [title]="c.type" size="xmedium"></nga-user>
|
||||
<i class="ion-ios-telephone-outline"></i>
|
||||
</div>
|
||||
</nga-tab>
|
||||
<nga-tab tabTitle="Recent">
|
||||
<span>Content #2</span>
|
||||
</nga-tab>
|
||||
</nga-tabset>
|
||||
</nga-card>
|
||||
44
src/app/pages/dashboard/contacts/contacts.component.scss
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
@import '../../../@theme/styles/variables';
|
||||
@import '~@nga/theme/styles/global/bootstrap/hero-buttons';
|
||||
|
||||
@include nga-install-component() {
|
||||
nga-tabset /deep/ ul {
|
||||
border-bottom: 1px solid nga-theme(separator);
|
||||
}
|
||||
|
||||
nga-tab {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.contact {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid nga-theme(separator);
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 2.5rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
nga-user /deep/ {
|
||||
.info-container {
|
||||
margin-left: 0.875rem;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 1.25rem;
|
||||
font-weight: nga-theme(font-weight-bolder);
|
||||
color: nga-theme(color-head);
|
||||
}
|
||||
|
||||
.user-title {
|
||||
font-size: 0.875rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
25
src/app/pages/dashboard/contacts/contacts.component.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
import { UserService } from '../../../@core/data/users.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-contacts',
|
||||
styleUrls: ['./contacts.component.scss'],
|
||||
templateUrl: './contacts.component.html',
|
||||
})
|
||||
export class ContactsComponent {
|
||||
contacts: any[];
|
||||
|
||||
constructor(private userService: UserService) {
|
||||
const users = this.userService.getUsers();
|
||||
|
||||
this.contacts = [
|
||||
{ user: users.nick, type: 'mobile' },
|
||||
{ user: users.eva, type: 'home' },
|
||||
{ user: users.jack, type: 'mobile' },
|
||||
{ user: users.lee, type: 'mobile' },
|
||||
{ user: users.alan, type: 'home' },
|
||||
{ user: users.kate, type: 'work' },
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -34,20 +34,12 @@
|
|||
Room Management
|
||||
</nga-card-header>
|
||||
<nga-card-body>
|
||||
<ngx-room-selector></ngx-room-selector>
|
||||
</nga-card-body>
|
||||
</nga-card>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<nga-card size="xmedium" class="contacts">
|
||||
<nga-tabset fullWidth>
|
||||
<nga-tab tabTitle="Contacts">
|
||||
<span>Content #1</span>
|
||||
</nga-tab>
|
||||
<nga-tab tabTitle="Recent">
|
||||
<span>Content #2</span>
|
||||
</nga-tab>
|
||||
</nga-tabset>
|
||||
</nga-card>
|
||||
<ngx-contacts></ngx-contacts>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,5 @@
|
|||
@import '../../@theme/styles/variables';
|
||||
@import '~@akveo/nga-theme/styles/global/bootstrap/hero-buttons';
|
||||
|
||||
@include nga-install-component() {
|
||||
nga-card-header {
|
||||
|
||||
}
|
||||
|
||||
nga-card.contacts nga-tabset /deep/ ul {
|
||||
border-bottom: 1px solid nga-theme(separator);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,25 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { NgaTabsetModule } from '@akveo/nga-theme';
|
||||
import { NgaTabsetModule, NgaUserModule } from '@akveo/nga-theme';
|
||||
|
||||
import { SharedModule } from '../../shared.module';
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
import { StatusCardsComponent } from './status-cards/status-cards.component';
|
||||
import { TemperatureDraggerComponent } from './temperature-dragger/temperature-dragger.component';
|
||||
import { ContactsComponent } from './contacts/contacts.component';
|
||||
import { RoomSelectorComponent } from './room-selector/room-selector.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
SharedModule,
|
||||
NgaTabsetModule,
|
||||
NgaUserModule,
|
||||
SharedModule,
|
||||
],
|
||||
declarations: [
|
||||
DashboardComponent,
|
||||
StatusCardsComponent,
|
||||
TemperatureDraggerComponent,
|
||||
ContactsComponent,
|
||||
RoomSelectorComponent,
|
||||
],
|
||||
})
|
||||
export class DashboardModule { }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" [attr.viewBox]="viewBox"
|
||||
preserveAspectRatio="xMidYMid">
|
||||
<defs>
|
||||
|
||||
<filter id="f2" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur result="blurOut" in="StrokePaint" stdDeviation="10" />
|
||||
</filter>
|
||||
|
||||
<pattern id="New_Pattern_Swatch_1" data-name="New Pattern Swatch 1" width="60" height="60"
|
||||
patternUnits="userSpaceOnUse" viewBox="0 0 60 60">
|
||||
<line class="stroke-pattern" x1="-113.26" y1="123.26" x2="3.26" y2="6.74"/>
|
||||
<line class="stroke-pattern" x1="-103.26" y1="133.26" x2="13.26" y2="16.74"/>
|
||||
<line class="stroke-pattern" x1="-93.26" y1="143.26" x2="23.26" y2="26.74"/>
|
||||
<line class="stroke-pattern" x1="-83.26" y1="153.26" x2="33.26" y2="36.74"/>
|
||||
<line class="stroke-pattern" x1="-73.26" y1="163.26" x2="43.26" y2="46.74"/>
|
||||
<line class="stroke-pattern" x1="-63.26" y1="173.26" x2="53.26" y2="56.74"/>
|
||||
<line class="stroke-pattern" x1="-53.26" y1="123.26" x2="63.26" y2="6.74"/>
|
||||
<line class="stroke-pattern" x1="-43.26" y1="133.26" x2="73.26" y2="16.74"/>
|
||||
<line class="stroke-pattern" x1="-33.26" y1="143.26" x2="83.26" y2="26.74"/>
|
||||
<line class="stroke-pattern" x1="-23.26" y1="153.26" x2="93.26" y2="36.74"/>
|
||||
<line class="stroke-pattern" x1="-13.26" y1="163.26" x2="103.26" y2="46.74"/>
|
||||
<line class="stroke-pattern" x1="-3.26" y1="173.26" x2="113.26" y2="56.74"/>
|
||||
<line class="stroke-pattern" x1="6.74" y1="123.26" x2="123.26" y2="6.74"/>
|
||||
<line class="stroke-pattern" x1="16.74" y1="133.26" x2="133.26" y2="16.74"/>
|
||||
<line class="stroke-pattern" x1="26.74" y1="143.26" x2="143.26" y2="26.74"/>
|
||||
<line class="stroke-pattern" x1="36.74" y1="153.26" x2="153.26" y2="36.74"/>
|
||||
<line class="stroke-pattern" x1="46.74" y1="163.26" x2="163.26" y2="46.74"/>
|
||||
<line class="stroke-pattern" x1="56.74" y1="173.26" x2="173.26" y2="56.74"/>
|
||||
<line class="stroke-pattern" x1="-113.26" y1="63.26" x2="3.26" y2="-53.26"/>
|
||||
<line class="stroke-pattern" x1="-103.26" y1="73.26" x2="13.26" y2="-43.26"/>
|
||||
<line class="stroke-pattern" x1="-93.26" y1="83.26" x2="23.26" y2="-33.26"/>
|
||||
<line class="stroke-pattern" x1="-83.26" y1="93.26" x2="33.26" y2="-23.26"/>
|
||||
<line class="stroke-pattern" x1="-73.26" y1="103.26" x2="43.26" y2="-13.26"/>
|
||||
<line class="stroke-pattern" x1="-63.26" y1="113.26" x2="53.26" y2="-3.26"/>
|
||||
<line class="stroke-pattern" x1="-53.26" y1="63.26" x2="63.26" y2="-53.26"/>
|
||||
<line class="stroke-pattern" x1="-43.26" y1="73.26" x2="73.26" y2="-43.26"/>
|
||||
<line class="stroke-pattern" x1="-33.26" y1="83.26" x2="83.26" y2="-33.26"/>
|
||||
<line class="stroke-pattern" x1="-23.26" y1="93.26" x2="93.26" y2="-23.26"/>
|
||||
<line class="stroke-pattern" x1="-13.26" y1="103.26" x2="103.26" y2="-13.26"/>
|
||||
<line class="stroke-pattern" x1="-3.26" y1="113.26" x2="113.26" y2="-3.26"/>
|
||||
<line class="stroke-pattern" x1="6.74" y1="63.26" x2="123.26" y2="-53.26"/>
|
||||
<line class="stroke-pattern" x1="16.74" y1="73.26" x2="133.26" y2="-43.26"/>
|
||||
<line class="stroke-pattern" x1="26.74" y1="83.26" x2="143.26" y2="-33.26"/>
|
||||
<line class="stroke-pattern" x1="36.74" y1="93.26" x2="153.26" y2="-23.26"/>
|
||||
<line class="stroke-pattern" x1="46.74" y1="103.26" x2="163.26" y2="-13.26"/>
|
||||
<line class="stroke-pattern" x1="56.74" y1="113.26" x2="173.26" y2="-3.26"/>
|
||||
<line class="stroke-pattern" x1="-113.26" y1="3.26" x2="3.26" y2="-113.26"/>
|
||||
<line class="stroke-pattern" x1="-103.26" y1="13.26" x2="13.26" y2="-103.26"/>
|
||||
<line class="stroke-pattern" x1="-93.26" y1="23.26" x2="23.26" y2="-93.26"/>
|
||||
<line class="stroke-pattern" x1="-83.26" y1="33.26" x2="33.26" y2="-83.26"/>
|
||||
<line class="stroke-pattern" x1="-73.26" y1="43.26" x2="43.26" y2="-73.26"/>
|
||||
<line class="stroke-pattern" x1="-63.26" y1="53.26" x2="53.26" y2="-63.26"/>
|
||||
<line class="stroke-pattern" x1="-53.26" y1="3.26" x2="63.26" y2="-113.26"/>
|
||||
<line class="stroke-pattern" x1="-43.26" y1="13.26" x2="73.26" y2="-103.26"/>
|
||||
<line class="stroke-pattern" x1="-33.26" y1="23.26" x2="83.26" y2="-93.26"/>
|
||||
<line class="stroke-pattern" x1="-23.26" y1="33.26" x2="93.26" y2="-83.26"/>
|
||||
<line class="stroke-pattern" x1="-13.26" y1="43.26" x2="103.26" y2="-73.26"/>
|
||||
<line class="stroke-pattern" x1="-3.26" y1="53.26" x2="113.26" y2="-63.26"/>
|
||||
<line class="stroke-pattern" x1="6.74" y1="3.26" x2="123.26" y2="-113.26"/>
|
||||
<line class="stroke-pattern" x1="16.74" y1="13.26" x2="133.26" y2="-103.26"/>
|
||||
<line class="stroke-pattern" x1="26.74" y1="23.26" x2="143.26" y2="-93.26"/>
|
||||
<line class="stroke-pattern" x1="36.74" y1="33.26" x2="153.26" y2="-83.26"/>
|
||||
<line class="stroke-pattern" x1="46.74" y1="43.26" x2="163.26" y2="-73.26"/>
|
||||
<line class="stroke-pattern" x1="56.74" y1="53.26" x2="173.26" y2="-63.26"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
|
||||
<g>
|
||||
<path class="room-border" [attr.d]="border.d" *ngFor="let border of roomSvg.borders" />
|
||||
</g>
|
||||
|
||||
<g>
|
||||
<path class="stroked-element" [attr.d]="strokedArea.d" *ngFor="let strokedArea of roomSvg.stokedAreas"/>
|
||||
</g>
|
||||
|
||||
<g [attr.id]="room.id" [class.selected-room]="selectedRoom == room.id" *ngFor="let room of sortedRooms">
|
||||
<path class="room-bg" (click)="roomSelected(room.id)" [attr.d]="room.area.d" />
|
||||
<path class="room-border" [attr.d]="room.border.d" />
|
||||
<text class="room-text" (click)="roomSelected(room.id)" text-anchor="middle"
|
||||
[attr.x]="room.name.x" [attr.y]="room.name.y">{{room.name.text}}</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.5 KiB |
|
|
@ -0,0 +1,59 @@
|
|||
:host {
|
||||
display: block;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
svg {
|
||||
display:block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.stroke-pattern {
|
||||
fill: none;
|
||||
stroke: #a1a1e5;
|
||||
stroke-miterlimit: 10;
|
||||
opacity: 0.1;
|
||||
stroke-width: 1px;
|
||||
}
|
||||
|
||||
.stroked-element {
|
||||
stroke-width: 4px;
|
||||
stroke: #a1a1e5;
|
||||
stroke-miterlimit: 10;
|
||||
fill: url('#New_Pattern_Swatch_1');
|
||||
}
|
||||
|
||||
.room-border {
|
||||
stroke-width: 4px;
|
||||
stroke: #a1a1e5;
|
||||
stroke-miterlimit: 10;
|
||||
fill: none;
|
||||
transition: stroke 0.4s ease-out;
|
||||
}
|
||||
|
||||
.room-bg {
|
||||
fill: transparent;
|
||||
stroke: transparent;
|
||||
cursor: pointer;
|
||||
transition: fill 0.4s ease-out;
|
||||
}
|
||||
|
||||
.room-text {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.selected-room {
|
||||
z-index: 40;
|
||||
.room-bg {
|
||||
stroke: rgba(0, 255, 170, 0.5);
|
||||
fill: rgba(0, 255, 170, 0.5);
|
||||
filter: url('#f2');
|
||||
}
|
||||
.room-border {
|
||||
stroke: #00f9a6;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-room-selector',
|
||||
templateUrl: './room-selector.component.html',
|
||||
styleUrls: ['./room-selector.component.scss'],
|
||||
})
|
||||
export class RoomSelectorComponent {
|
||||
selectedRoom: null;
|
||||
|
||||
sortedRooms = [];
|
||||
|
||||
viewBox = '-20 -20 608.88 407.99';
|
||||
|
||||
roomSvg = {
|
||||
borders: [{
|
||||
d: 'M186.21,130.05H216.37V160H186.21Z',
|
||||
}],
|
||||
stokedAreas: [
|
||||
{ d: 'M562.71,225V354h-290V319H418.37a6.09,6.09,0,0,0,6.09-6.09V225Z' },
|
||||
{ d: 'M8.09,130V347.91A6.09,6.09,0,0,0,14.18,354h54V130Z' },
|
||||
{ d: 'M216.37,49.82H358.8V92.5H216.37Z' },
|
||||
],
|
||||
rooms: [
|
||||
{
|
||||
id: '0',
|
||||
name: { text: 'Kitchen', x: 142, y: 240.8 },
|
||||
area: { d: 'M68.18,130V359.9A6.09,6.09,0,0,0,74.27,366h136a6.09,6.09,0,0,0,6.09-6.09V160H186.21V130Z' },
|
||||
border: { d: 'M96,130H68.18V359.9A6.09,6.09,0,0,0,74.27,366h136a6.09,6.09,0,0,0,6.09-6.09V225 M152.71,' +
|
||||
'130H186.21V160H216.21' },
|
||||
},
|
||||
{
|
||||
id: '1',
|
||||
name: { text: 'Bedroom', x: 109, y: 66 },
|
||||
area: { d: 'M152.71,130h63.66V8.09A6.09,6.09,0,0,0,210.27,2H8.09A6.09,6.09,0,0,0,2,8.09V123.95A6.09,' +
|
||||
'6.09,0,0,0,8.09,130H96Z' },
|
||||
border: { d: 'M152.71,130h63.66V8.09A6.09,6.09,0,0,0,210.27,2H8.09A6.09,6.09,0,0,0,2,8.09V123.95A6.09' +
|
||||
',6.09,0,0,0,8.09,130H96' },
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: { text: 'Living Room', x: 468, y: 134 },
|
||||
area: { d: 'M358.8,160V49.82a6.09,6.09,0,0,1,6.09-6.09H570.78a6.09,6.09,0,0,1,6.09,6.09V218.9a6.09' +
|
||||
',6.09,0,0,1-6.09,6.09h-212Z' },
|
||||
border: { d: 'M358.8,160V49.82a6.09,6.09,0,0,1,6.09-6.09H570.78a6.09,6.09,0,0,1,6.09,6.09V218.9a6.09' +
|
||||
',6.09,0,0,1-6.09,6.09h-212' },
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: { text: 'Hallway', x: 320, y: 273 },
|
||||
area: { d: 'M216.37,354V92.5H358.8V225H424.39V319H272.71V354Z' },
|
||||
border: { d: 'M216.37,225V354 M216.21,160V92.5H358.8V160 M358.8,225H424.39V312.91a6.09,' +
|
||||
'6.09,0,0,1,-6.09,6.09H272.71V354' },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
this.sortRooms();
|
||||
}
|
||||
|
||||
private sortRooms() {
|
||||
this.sortedRooms = this.roomSvg.rooms.slice(0).sort((a, b) => {
|
||||
if (a.id === this.selectedRoom) {
|
||||
return 1;
|
||||
}
|
||||
if (b.id === this.selectedRoom) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
roomSelected(roomNumber) {
|
||||
this.selectedRoom = roomNumber;
|
||||
this.sortRooms();
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import { PagesComponent } from './pages.component';
|
|||
import { DashboardModule } from './dashboard/dashboard.module';
|
||||
import { PagesRoutingModule } from './pages-routing.module';
|
||||
import { ThemeModule } from '../@theme/theme.module';
|
||||
import { DataModule } from '../@core/data/data.module';
|
||||
|
||||
const PAGES_COMPONENTS = [
|
||||
PagesComponent,
|
||||
|
|
@ -21,6 +22,7 @@ const PAGES_COMPONENTS = [
|
|||
NgaMenuModule.forRoot({ items: menuItems }),
|
||||
PagesRoutingModule,
|
||||
ThemeModule,
|
||||
DataModule.forRoot(),
|
||||
DashboardModule,
|
||||
],
|
||||
declarations: [
|
||||
|
|
|
|||
BIN
src/assets/images/alan.png
Normal file
|
After Width: | Height: | Size: 164 KiB |
BIN
src/assets/images/eva.png
Normal file
|
After Width: | Height: | Size: 149 KiB |
BIN
src/assets/images/jack.png
Normal file
|
After Width: | Height: | Size: 155 KiB |
BIN
src/assets/images/kate.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
src/assets/images/lee.png
Normal file
|
After Width: | Height: | Size: 146 KiB |
BIN
src/assets/images/nick.png
Normal file
|
After Width: | Height: | Size: 145 KiB |