committed by
khalil-bot
parent
ad911b7479
commit
781959240b
61
.github/workflows/README.md
vendored
Normal file
61
.github/workflows/README.md
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
# GitHub Actions Workflows
|
||||
|
||||
## Angular CI Pipeline
|
||||
|
||||
### Triggers
|
||||
- **Push**: Runs on all branches when changes are made to `ui/` folder
|
||||
- **Pull Request**: Runs when PR targets `main` branch
|
||||
|
||||
### Pipeline Stages
|
||||
|
||||
1. **Checkout** - Clone repository
|
||||
2. **Setup Node.js** - Install Node 20.x with npm cache
|
||||
3. **Install Dependencies** - Run `npm ci`
|
||||
4. **Type Check** - Run `npx tsc --noEmit`
|
||||
5. **Lint** - Run `npm run lint`
|
||||
6. **Format Check** - Run `npm run format:check`
|
||||
7. **Build Dev** - Build development configuration
|
||||
8. **Build Prod** - Build production configuration
|
||||
9. **Test** - Run unit tests with coverage
|
||||
10. **Upload Artifacts** - Save build outputs and coverage reports
|
||||
|
||||
|
||||
### Local Testing
|
||||
|
||||
Before pushing, run locally:
|
||||
```bash
|
||||
cd ui
|
||||
npm ci
|
||||
npx tsc --noEmit
|
||||
npm run lint
|
||||
npm run format:check
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
**Node version mismatch:**
|
||||
```bash
|
||||
# Use Node 20.x locally
|
||||
nvm use 20
|
||||
```
|
||||
|
||||
**Cache issues:**
|
||||
```bash
|
||||
# Clear npm cache
|
||||
npm cache clean --force
|
||||
rm -rf node_modules package-lock.json
|
||||
npm install
|
||||
```
|
||||
|
||||
**Lint errors:**
|
||||
```bash
|
||||
# Auto-fix
|
||||
npm run lint -- --fix
|
||||
```
|
||||
|
||||
**Format errors:**
|
||||
```bash
|
||||
# Auto-format
|
||||
npm run format
|
||||
```
|
||||
100
.github/workflows/angular-ci.yml
vendored
Normal file
100
.github/workflows/angular-ci.yml
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
name: Angular CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**' # Run on all branches
|
||||
paths:
|
||||
- 'ui/**'
|
||||
- '.github/workflows/angular-ci.yml'
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'ui/**'
|
||||
- '.github/workflows/angular-ci.yml'
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
name: Build and Test Angular App
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./ui
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [20.x]
|
||||
|
||||
steps:
|
||||
# Checkout code
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Setup Node.js
|
||||
- name: Setup Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: './ui/package-lock.json'
|
||||
|
||||
# Install dependencies
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
# Check TypeScript compilation
|
||||
- name: TypeScript compilation check
|
||||
run: npx tsc --noEmit
|
||||
|
||||
# Run linting
|
||||
- name: Run ESLint
|
||||
run: npm run lint
|
||||
continue-on-error: true # Don't fail build on lint warnings
|
||||
|
||||
# Check code formatting
|
||||
- name: Check Prettier formatting
|
||||
run: npm run format:check
|
||||
|
||||
# Build development
|
||||
- name: Build (Development)
|
||||
run: npm run build -- --configuration=development
|
||||
|
||||
# Build production
|
||||
- name: Build (Production)
|
||||
run: npm run build -- --configuration=production
|
||||
|
||||
# Run unit tests (when available)
|
||||
- name: Run unit tests
|
||||
run: npm run test -- --watch=false --browsers=ChromeHeadless --code-coverage
|
||||
continue-on-error: true # Don't fail yet (no tests implemented)
|
||||
|
||||
# Upload coverage (when tests exist)
|
||||
- name: Upload coverage reports
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: coverage-report
|
||||
path: ui/coverage/
|
||||
retention-days: 7
|
||||
continue-on-error: true
|
||||
|
||||
# Upload build artifacts
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: angular-build
|
||||
path: ui/dist/
|
||||
retention-days: 7
|
||||
|
||||
# Summary
|
||||
- name: Build summary
|
||||
if: success()
|
||||
run: |
|
||||
echo "Build successful!" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Build Details" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Node version: ${{ matrix.node-version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Angular version: 18.x" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Build time: $(date)" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"root": true,
|
||||
"ignorePatterns": ["projects/**/*"],
|
||||
"ignorePatterns": [
|
||||
"projects/**/*"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts"],
|
||||
"parserOptions": {
|
||||
"project": ["tsconfig.json"],
|
||||
"createDefaultProgram": true
|
||||
},
|
||||
"files": [
|
||||
"*.ts"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
@@ -30,15 +30,16 @@
|
||||
"prefix": "app",
|
||||
"style": "kebab-case"
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-explicit-any": "warn",
|
||||
"@typescript-eslint/explicit-function-return-type": "off"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.html"],
|
||||
"files": [
|
||||
"*.html"
|
||||
],
|
||||
"extends": [
|
||||
"plugin:@angular-eslint/template/recommended"
|
||||
"plugin:@angular-eslint/template/recommended",
|
||||
"plugin:@angular-eslint/template/accessibility"
|
||||
],
|
||||
"rules": {}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
"version": 1,
|
||||
"cli": {
|
||||
"packageManager": "npm",
|
||||
"analytics": false
|
||||
"analytics": false,
|
||||
"schematicCollections": [
|
||||
"@angular-eslint/schematics"
|
||||
]
|
||||
},
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
@@ -119,8 +122,17 @@
|
||||
],
|
||||
"scripts": []
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-eslint/builder:lint",
|
||||
"options": {
|
||||
"lintFilePatterns": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.html"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1614
ui/package-lock.json
generated
1614
ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,10 @@
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"test": "ng test"
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"format": "prettier --write \"src/**/*.{ts,html,scss,json}\"",
|
||||
"format:check": "prettier --check \"src/**/*.{ts,html,scss,json}\""
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
@@ -28,13 +31,18 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^18.0.2",
|
||||
"@angular-eslint/builder": "21.0.1",
|
||||
"@angular-eslint/eslint-plugin": "21.0.1",
|
||||
"@angular-eslint/eslint-plugin-template": "21.0.1",
|
||||
"@angular-eslint/schematics": "21.0.1",
|
||||
"@angular-eslint/template-parser": "21.0.1",
|
||||
"@angular/cli": "^18.0.2",
|
||||
"@angular/compiler-cli": "^18.0.0",
|
||||
"@types/chart.js": "^4.0.1",
|
||||
"@types/jasmine": "~5.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.57.2",
|
||||
"@typescript-eslint/parser": "^8.57.2",
|
||||
"eslint": "^10.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "7.11.0",
|
||||
"@typescript-eslint/parser": "7.11.0",
|
||||
"eslint": "8.57.1",
|
||||
"jasmine-core": "~5.1.0",
|
||||
"karma": "~6.4.0",
|
||||
"karma-chrome-launcher": "~3.2.0",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<app-header></app-header>
|
||||
<main>
|
||||
<router-outlet></router-outlet>
|
||||
</main>
|
||||
<app-header></app-header>
|
||||
<main>
|
||||
<router-outlet></router-outlet>
|
||||
</main>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
main {
|
||||
min-height: calc(100vh - 64px);
|
||||
background: #fafafa;
|
||||
}
|
||||
main {
|
||||
min-height: calc(100vh - 64px);
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { routes } from './app.routes';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AppComponent],
|
||||
providers: [provideRouter(routes)],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
@@ -14,16 +17,16 @@ describe('AppComponent', () => {
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should have the 'dashboard' title`, () => {
|
||||
it(`should have the 'PI_E2EEDA Dashboard' title`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('dashboard');
|
||||
expect(app.title).toEqual('PI_E2EEDA Dashboard');
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
it('should render header', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, dashboard');
|
||||
expect(compiled.querySelector('app-header')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,9 +7,8 @@ import { HeaderComponent } from './components/header/header.component';
|
||||
standalone: true,
|
||||
imports: [RouterOutlet, HeaderComponent],
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.scss'
|
||||
styleUrl: './app.component.scss',
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'PI_E2EEDA Dashboard';
|
||||
|
||||
title = 'PI_E2EEDA Dashboard';
|
||||
}
|
||||
|
||||
@@ -5,5 +5,9 @@ import { routes } from './app.routes';
|
||||
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideAnimationsAsync()]
|
||||
providers: [
|
||||
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||
provideRouter(routes),
|
||||
provideAnimationsAsync(),
|
||||
],
|
||||
};
|
||||
|
||||
@@ -4,22 +4,24 @@ export const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/dashboard',
|
||||
pathMatch: 'full'
|
||||
pathMatch: 'full',
|
||||
},
|
||||
{
|
||||
path: 'dashboard',
|
||||
loadComponent: () =>
|
||||
loadComponent: () =>
|
||||
import('./components/room-map/room-map.component').then(m => m.RoomMapComponent),
|
||||
title: 'Dashboard - PI_E2EEDA'
|
||||
title: 'Dashboard - PI_E2EEDA',
|
||||
},
|
||||
{
|
||||
path: 'room/:id',
|
||||
loadComponent: () =>
|
||||
import('./components/room-details-panel/room-details-panel.component').then(m => m.RoomDetailsPanelComponent),
|
||||
title: 'Room Details - PI_E2EEDA'
|
||||
loadComponent: () =>
|
||||
import('./components/room-details-panel/room-details-panel.component').then(
|
||||
m => m.RoomDetailsPanelComponent
|
||||
),
|
||||
title: 'Room Details - PI_E2EEDA',
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
redirectTo: '/dashboard'
|
||||
}
|
||||
redirectTo: '/dashboard',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<header>
|
||||
<div class="header-content">
|
||||
<h1 routerLink="/dashboard">🌡️ PI_E2EEDA</h1>
|
||||
<nav>
|
||||
<a routerLink="/dashboard" routerLinkActive="active">Dashboard</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<header>
|
||||
<div class="header-content">
|
||||
<h1 routerLink="/dashboard">🌡️ PI_E2EEDA</h1>
|
||||
<nav>
|
||||
<a routerLink="/dashboard" routerLinkActive="active">Dashboard</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
header {
|
||||
background: #00bcd4;
|
||||
color: white;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.header-content {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 16px 24px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
nav a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
margin-left: 24px;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
transition: background 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: rgba(255,255,255,0.2);
|
||||
}
|
||||
}
|
||||
header {
|
||||
background: #00bcd4;
|
||||
color: white;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header-content {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 16px 24px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
nav a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
margin-left: 24px;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
transition: background 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@ import { RouterModule } from '@angular/router';
|
||||
imports: [CommonModule, RouterModule],
|
||||
templateUrl: './header.component.html',
|
||||
styleUrl: './header.component.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class HeaderComponent {
|
||||
|
||||
}
|
||||
export class HeaderComponent {}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<div class="legend">
|
||||
<h3>Air Quality (CO2)</h3>
|
||||
<div class="legend-items">
|
||||
<div class="legend-item" *ngFor="let level of levels">
|
||||
<div class="color-box" [style.background-color]="level.color"></div>
|
||||
<span class="label">{{ level.label }}</span>
|
||||
<span class="range">{{ level.range }}</span>
|
||||
</div>
|
||||
<h3>Air Quality (CO2)</h3>
|
||||
<div class="legend-items">
|
||||
@for (level of levels; track level.label) {
|
||||
<div class="legend-item">
|
||||
<div class="color-box" [style.background-color]="level.color"></div>
|
||||
<span class="label">{{ level.label }}</span>
|
||||
<span class="range">{{ level.range }}</span>
|
||||
</div>
|
||||
</div>>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
.legend {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0 0 12px 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: rgba(0,0,0,0.87);
|
||||
}
|
||||
|
||||
.legend-items {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.color-box {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-weight: 500;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.range {
|
||||
color: rgba(0,0,0,0.6);
|
||||
}
|
||||
.legend {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0 0 12px 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
|
||||
.legend-items {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.color-box {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-weight: 500;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.range {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
|
||||
interface CO2Level {
|
||||
label: string;
|
||||
@@ -10,19 +10,18 @@ interface CO2Level {
|
||||
@Component({
|
||||
selector: 'app-legend',
|
||||
standalone: true,
|
||||
imports: [],
|
||||
imports: [CommonModule],
|
||||
templateUrl: './legend.component.html',
|
||||
styleUrl: './legend.component.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class LegendComponent {
|
||||
levels: CO2Level[] = [
|
||||
levels: CO2Level[] = [
|
||||
{ label: 'Excellent', range: '< 800 ppm', color: '#4caf50' },
|
||||
{ label: 'Good', range: '800-1000 ppm', color: '#8bc34a' },
|
||||
{ label: 'Moderate', range: '1000-1200 ppm', color: '#ffc107' },
|
||||
{ label: 'Poor', range: '1200-1500 ppm', color: '#ff9800' },
|
||||
{ label: 'Very Poor', range: '1500-2000 ppm', color: '#ff5722' },
|
||||
{ label: 'Critical', range: '> 2000 ppm', color: '#f44336' }
|
||||
{ label: 'Critical', range: '> 2000 ppm', color: '#f44336' },
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="room-details-container">
|
||||
<h1>Room Details - {{ roomId }}</h1>
|
||||
<p>Detailed room information coming soon.</p>
|
||||
<a routerLink="/dashboard">← Back to Dashboard</a>
|
||||
</div>
|
||||
<div class="room-details-container">
|
||||
<h1>Room Details - {{ roomId }}</h1>
|
||||
<p>Detailed room information coming soon.</p>
|
||||
<a routerLink="/dashboard">← Back to Dashboard</a>
|
||||
</div>
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
.room-details-container {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #00bcd4;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
.room-details-container {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #00bcd4;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ActivatedRoute, RouterModule } from '@angular/router';
|
||||
@Component({
|
||||
@@ -7,13 +7,9 @@ import { ActivatedRoute, RouterModule } from '@angular/router';
|
||||
imports: [CommonModule, RouterModule],
|
||||
templateUrl: './room-details-panel.component.html',
|
||||
styleUrl: './room-details-panel.component.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class RoomDetailsPanelComponent {
|
||||
roomId: string | null = null;
|
||||
|
||||
constructor(private route: ActivatedRoute) {
|
||||
this.roomId = this.route.snapshot.paramMap.get('id');
|
||||
}
|
||||
|
||||
private route = inject(ActivatedRoute);
|
||||
roomId: string | null = this.route.snapshot.paramMap.get('id');
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="room-map-container">
|
||||
<h1>Room Map</h1>
|
||||
<p>Interactive 2D SVG map will be displayed here.</p>
|
||||
</div>
|
||||
<div class="room-map-container">
|
||||
<h1>Room Map</h1>
|
||||
<p>Interactive 2D SVG map will be displayed here.</p>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
.room-map-container {
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #00bcd4;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #00bcd4;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
imports: [CommonModule],
|
||||
templateUrl: './room-map.component.html',
|
||||
styleUrl: './room-map.component.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class RoomMapComponent {
|
||||
|
||||
}
|
||||
export class RoomMapComponent {}
|
||||
|
||||
@@ -7,5 +7,5 @@ export const environment = {
|
||||
apiUrl: 'https://YOUR_DOMAIN/api',
|
||||
wsUrl: 'wss://YOUR_DOMAIN/ws',
|
||||
influxUrl: '',
|
||||
logLevel: 'error'
|
||||
logLevel: 'error',
|
||||
};
|
||||
|
||||
@@ -3,5 +3,5 @@ export const environment = {
|
||||
apiUrl: 'http://localhost:8080',
|
||||
wsUrl: 'ws://localhost:8080',
|
||||
influxUrl: '',
|
||||
logLevel: 'debug'
|
||||
logLevel: 'debug',
|
||||
};
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Dashboard</title>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
</head>
|
||||
<body class="mat-typography">
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Dashboard</title>
|
||||
<base href="/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
||||
</head>
|
||||
<body class="mat-typography">
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -2,5 +2,4 @@ import { bootstrapApplication } from '@angular/platform-browser';
|
||||
import { appConfig } from './app/app.config';
|
||||
import { AppComponent } from './app/app.component';
|
||||
|
||||
bootstrapApplication(AppComponent, appConfig)
|
||||
.catch((err) => console.error(err));
|
||||
bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err));
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
/* You can add global styles to this file, and also import other style files */
|
||||
|
||||
html, body { height: 100%; }
|
||||
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Roboto, 'Helvetica Neue', sans-serif;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user