You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@trafficcontrol.apache.org by GitBox <gi...@apache.org> on 2022/04/13 21:05:09 UTC
[GitHub] [trafficcontrol] shamrickus opened a new pull request, #6753: Add Theming to TPv2
shamrickus opened a new pull request, #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753
<!--
Thank you for contributing! Please be sure to read our contribution guidelines: https://github.com/apache/trafficcontrol/blob/master/CONTRIBUTING.md
If this closes or relates to an existing issue, please reference it using one of the following:
Closes: #ISSUE
Related: #ISSUE
If this PR fixes a security vulnerability, DO NOT submit! Instead, contact
the Apache Traffic Control Security Team at security@trafficcontrol.apache.org and follow the
guidelines at https://apache.org/security regarding vulnerability disclosure.
-->
This PR introduces theming to TPv2, in doing so it refactors several components to use material inputs.
The TP header has been moved up to the `app.comp.html` and a service has been introduced to manage the header from any page.
<!-- **^ Add meaningful description above** --><hr/>
## Which Traffic Control components are affected by this PR?
<!-- Please delete all components from this list that are NOT affected by this PR.
Feel free to add the name of a tool or script that is affected but not on the list.
-->
- Traffic Portal 2
## What is the best way to verify this PR?
Verify:
```
* User able to change theme in profile
* Theme is remembered across sessions
* Dark theme is not loaded unless it is needed
* Server details page works
* All pages are properly themed
```
<!-- Please include here ALL the steps necessary to test your PR.
If your PR has tests (and most should), provide the steps needed to run the tests.
If not, please provide step-by-step instructions to test the PR manually and explain why your PR does not need tests. -->
## PR submission checklist
- [x] This PR has tests <!-- If not, please delete this text and explain why this PR does not need tests. -->
- [x] This PR has documentation <!-- If not, please delete this text and explain why this PR does not need documentation. -->
- [ ] This PR has a CHANGELOG.md entry <!-- A fix for a bug from an ATC release, an improvement, or a new feature should have a changelog entry. -->
- [x] This PR **DOES NOT FIX A SERIOUS SECURITY VULNERABILITY** (see [the Apache Software Foundation's security guidelines](https://apache.org/security) for details)
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] ocket8888 merged pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
ocket8888 merged PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] ocket8888 commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
ocket8888 commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r876246508
##########
experimental/traffic-portal/src/app/shared/tp-header/tp-header.service.ts:
##########
@@ -22,15 +21,31 @@ import {TpHeaderComponent} from "src/app/shared/tp-header/tp-header.component";
providedIn: "root"
})
export class TpHeaderService {
- private header?: TpHeaderComponent;
+ private readonly headerTitle: ReplaySubject<string>;
+ private readonly headerHidden: ReplaySubject<boolean>;
+
+ constructor() {
+ this.headerTitle = new ReplaySubject(1);
+ this.headerHidden = new ReplaySubject(1);
+ this.headerHidden.next(true);
+ }
+
+ /**
+ * Gets the header title.
+ *
+ * @returns Subject containing the header title.
+ */
+ public getTitle(): ReplaySubject<string> {
+ return this.headerTitle;
+ }
Review Comment:
why not just make the property `public` instead of adding an identity function wrapper?
##########
experimental/traffic-portal/src/app/shared/tp-header/tp-header.service.ts:
##########
@@ -22,15 +21,31 @@ import {TpHeaderComponent} from "src/app/shared/tp-header/tp-header.component";
providedIn: "root"
})
export class TpHeaderService {
- private header?: TpHeaderComponent;
+ private readonly headerTitle: ReplaySubject<string>;
+ private readonly headerHidden: ReplaySubject<boolean>;
+
+ constructor() {
+ this.headerTitle = new ReplaySubject(1);
+ this.headerHidden = new ReplaySubject(1);
+ this.headerHidden.next(true);
+ }
+
+ /**
+ * Gets the header title.
+ *
+ * @returns Subject containing the header title.
+ */
+ public getTitle(): ReplaySubject<string> {
+ return this.headerTitle;
+ }
Review Comment:
also applies to `getHidden`, obviously.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] ocket8888 commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
ocket8888 commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r878446081
##########
experimental/traffic-portal/src/app/shared/tp-header/tp-header.component.html:
##########
@@ -11,30 +11,39 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<mat-toolbar color="primary">
- <img src="/assets/logo.svg" alt="Apache Traffic Control logo"/>
+<mat-toolbar color="primary" *ngIf="!hidden">
+ <img src="/assets/logo.svg" alt="Apache Traffic Control logo" routerLink="/core/"/>
<h1>{{title ? title : 'Welcome to Traffic Portal!'}}</h1>
<div></div>
<nav id="expanded">
<ul>
- <li><a routerLink="/core/">Home</a></li>
- <li *ngIf="hasPermission('USER:READ')"><a routerLink="/core/users">Users</a></li>
- <li *ngIf="hasPermission('SERVER:READ')"><a routerLink="/core/servers">Servers</a></li>
- <li><button class="menubutton" type="button" (click)="logout()">Logout</button></li>
- <li><a routerLink="/core/me"><svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 16 16"><g id="surface1"><path d="M 8 2 C 6.347656 2 5 3.347656 5 5 C 5 6.652344 6.347656 8 8 8 C 9.652344 8 11 6.652344 11 5 C 11 3.347656 9.652344 2 8 2 Z M 8 8 C 5.246094 8 3 10.246094 3 13 L 4 13 C 4 10.785156 5.785156 9 8 9 C 10.214844 9 12 10.785156 12 13 L 13 13 C 13 10.246094 10.753906 8 8 8 Z M 8 3 C 9.109375 3 10 3.890625 10 5 C 10 6.109375 9.109375 7 8 7 C 6.890625 7 6 6.109375 6 5 C 6 3.890625 6.890625 3 8 3 Z "></path></g></svg>
- </a></li>
+ <li><button mat-button routerLink="/core/">Home</button></li>
+ <li *ngIf="hasPermission('USER:READ')"><button mat-button routerLink="/core/users">Users</button></li>
+ <li *ngIf="hasPermission('SERVER:READ')"><button mat-button routerLink="/core/servers">Servers</button></li>
+ <li>
+ <button mat-icon-button [matMenuTriggerFor]="expandedMenu">
+ <mat-icon>manage_accounts</mat-icon>
+ </button>
+ <mat-menu #expandedMenu="matMenu">
+ <button mat-menu-item routerLink="/core/me">Profile</button>
+ <button mat-menu-item (click)="logout()">Logout</button>
+ <button mat-menu-item [matMenuTriggerFor]="themeMenu">Theme</button>
+ </mat-menu>
+ </li>
</ul>
</nav>
<nav id="collapsed">
- <input type="checkbox" hidden id="collapsed-menu"/>
- <label for="collapsed-menu"></label>
- <ul>
- <li><a routerLink="/core/">Home</a></li>
- <li *ngIf="hasPermission('USER:READ')"><a routerLink="/core/users">Users</a></li>
- <li *ngIf="hasPermission('SERVER:READ')"><a routerLink="/core/servers">Servers</a></li>
- <li><a href="#">Tools</a></li>
- <li><a href="/core/me">Profile</a></li>
- <li><button type="button" class="menubutton" (click)="logout()">Logout</button></li>
- </ul>
+ <button mat-icon-button [matMenuTriggerFor]="collapsedMenu"><mat-icon>menu</mat-icon></button>
+ <mat-menu #collapsedMenu="matMenu">
+ <button mat-menu-item routerLink="/core/">Home</button>
+ <button *ngIf="hasPermission('USER:READ')" mat-menu-item routerLink="/core/users">Users</button>
+ <button *ngIf="hasPermission('SERVER:READ')" mat-menu-item routerLink="/core/servers">Servers</button>
+ <button mat-menu-item href="/core/me">Profile</button>
Review Comment:
also those of these buttons that should be buttons, should have their `type` set to `button`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] ocket8888 commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
ocket8888 commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r878634838
##########
experimental/traffic-portal/src/app/core/servers/update-status/update-status.component.html:
##########
@@ -11,22 +11,20 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<dialog open>
- <h2>Change status for {{serverName}}</h2>
- <hr/>
- <!-- method=dialog doesn't work in Firefox - even with the dialog element enabled in about:config-->
- <!-- So we need to preventDefault on this event anyway -->
- <form ngNativeValidate (ngSubmit)="submit($event)" method="dialog">
- <label for="status">New Status</label>
- <select id="status" name="status" [formControl]="statusControl" required>
- <option *ngFor="let status of statuses" [ngValue]="status" [disabled]="status.id === currentStatus">{{status.name}}</option>
- </select>
- <label *ngIf="isOffline" for="offlineReason">Offline Reason</label>
- <input [formControl]="offlineReasonControl" id="offlineReason" name="offlineReason" *ngIf="isOffline" required maxlength="100"/>
- <div>
- <button mat-raised-button color="warn" type="button" (click)="cancel()">Cancel</button>
- <button mat-raised-button>Submit</button>
- </div>
- </form>
-</dialog>
-<div class="backdrop"></div>
+<h2 mat-dialog-title>Change status for {{serverName}}</h2>
+<div mat-dialog-content>
+ <mat-form-field appearance="fill">
+ <mat-label for="status">New Status</mat-label>
+ <mat-select id="status" name="status" [(ngModel)]="status" required>
+ <mat-option *ngFor="let status of statuses" [value]="status" [disabled]="status.id === currentStatus">{{status.name}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ <mat-form-field *ngIf="isOffline" appearance="fill">
+ <mat-label for="offlineReason">Offline Reason</mat-label>
+ <input matInput [(ngModel)]="offlineReason" id="offlineReason" name="offlineReason" required maxlength="100"/>
+ </mat-form-field>
+</div>
+<div mat-dialog-actions>
+ <button mat-raised-button disabled="{{status === null || isOffline && offlineReason === ''}}" (click)="submit()">Submit</button>
+ <button mat-raised-button color="warn" type="button" (click)="cancel()">Cancel</button>
+</div>
Review Comment:
I hadn't thought of that. That's a bit tricky. I would've thought Material would use a hidden input laid underneath the material select that reports custom validity messages that mirror the select's validity, to fully implement that. But then, Angular has a general disdain for native form validation in general.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] shamrickus commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
shamrickus commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r878592466
##########
experimental/traffic-portal/src/app/core/servers/update-status/update-status.component.html:
##########
@@ -11,22 +11,20 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<dialog open>
- <h2>Change status for {{serverName}}</h2>
- <hr/>
- <!-- method=dialog doesn't work in Firefox - even with the dialog element enabled in about:config-->
- <!-- So we need to preventDefault on this event anyway -->
- <form ngNativeValidate (ngSubmit)="submit($event)" method="dialog">
- <label for="status">New Status</label>
- <select id="status" name="status" [formControl]="statusControl" required>
- <option *ngFor="let status of statuses" [ngValue]="status" [disabled]="status.id === currentStatus">{{status.name}}</option>
- </select>
- <label *ngIf="isOffline" for="offlineReason">Offline Reason</label>
- <input [formControl]="offlineReasonControl" id="offlineReason" name="offlineReason" *ngIf="isOffline" required maxlength="100"/>
- <div>
- <button mat-raised-button color="warn" type="button" (click)="cancel()">Cancel</button>
- <button mat-raised-button>Submit</button>
- </div>
- </form>
-</dialog>
-<div class="backdrop"></div>
+<h2 mat-dialog-title>Change status for {{serverName}}</h2>
+<div mat-dialog-content>
+ <mat-form-field appearance="fill">
+ <mat-label for="status">New Status</mat-label>
+ <mat-select id="status" name="status" [(ngModel)]="status" required>
+ <mat-option *ngFor="let status of statuses" [value]="status" [disabled]="status.id === currentStatus">{{status.name}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ <mat-form-field *ngIf="isOffline" appearance="fill">
+ <mat-label for="offlineReason">Offline Reason</mat-label>
+ <input matInput [(ngModel)]="offlineReason" id="offlineReason" name="offlineReason" required maxlength="100"/>
+ </mat-form-field>
+</div>
+<div mat-dialog-actions>
+ <button mat-raised-button disabled="{{status === null || isOffline && offlineReason === ''}}" (click)="submit()">Submit</button>
+ <button mat-raised-button color="warn" type="button" (click)="cancel()">Cancel</button>
+</div>
Review Comment:
I added it, however had to switch the status dropdown to the native select instead of `mat-select` since it's not backed by a `select` so native validation wouldn't apply.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] ocket8888 commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
ocket8888 commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r864211210
##########
experimental/traffic-portal/src/app/app.component.ts:
##########
@@ -26,14 +28,15 @@ import { CurrentUserService } from "src/app/shared/currentUser/current-user.serv
styleUrls: ["./app.component.scss"],
templateUrl: "./app.component.html",
})
-export class AppComponent implements OnInit {
+export class AppComponent implements OnInit, AfterViewInit {
+ @ViewChild("header") private readonly headerRef!: TpHeaderComponent;
Review Comment:
I kinda hate `ViewChild` because it'll compile fine if the child doesn't actually exist and then break at runtime.
I know this is a major change to the PR, but what if instead we had a `ThemeService` or something that exposes a `BehaviorSubject` and the header just subscribes to it. Then you wouldn't need to register it either.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] ocket8888 commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
ocket8888 commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r864211210
##########
experimental/traffic-portal/src/app/app.component.ts:
##########
@@ -26,14 +28,15 @@ import { CurrentUserService } from "src/app/shared/currentUser/current-user.serv
styleUrls: ["./app.component.scss"],
templateUrl: "./app.component.html",
})
-export class AppComponent implements OnInit {
+export class AppComponent implements OnInit, AfterViewInit {
+ @ViewChild("header") private readonly headerRef!: TpHeaderComponent;
Review Comment:
I kinda hate `ViewChild` because it'll compile fine if the child doesn't actually exist.
I know this is a major change to the PR, but what if instead we had a `ThemeService` or something that exposes a `BehaviorSubject` and the header just subscribes to it. Then you wouldn't need to register it either.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] ocket8888 commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
ocket8888 commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r878634596
##########
experimental/traffic-portal/src/app/shared/tp-header/tp-header.component.scss:
##########
@@ -53,6 +57,10 @@ nav {
}
}
+a.mat-menu-item {
+ text-transform: uppercase;
Review Comment:
doesn't `mat-button` handle this for you?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] shamrickus commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
shamrickus commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r879446495
##########
experimental/traffic-portal/src/app/shared/tp-header/tp-header.component.scss:
##########
@@ -53,6 +57,10 @@ nav {
}
}
+a.mat-menu-item {
+ text-transform: uppercase;
Review Comment:
`mat-menu-item` and `mat-button` are mutually exclusive directives
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] shamrickus commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
shamrickus commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r878566184
##########
experimental/traffic-portal/src/app/core/currentuser/currentuser.component.html:
##########
@@ -11,67 +11,71 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<tp-header [title]="currentUser ? currentUser.username : ''"></tp-header>
+<mat-card>
+ <main *ngIf="currentUser && !editMode">
+ <h1><span *ngIf=currentUser.fullName>{{currentUser.fullName}}, </span>{{currentUser.roleName}} user</h1>
+ <address>
+ <p *ngIf="currentUser.email || currentUser.phoneNumber"><a *ngIf=currentUser.email href="mailto:{{currentUser.email}}">{{currentUser.email}}</a><span *ngIf="currentUser.email && currentUser.phoneNumber">, </span><a *ngIf="currentUser.phoneNumber" href="tel:{{currentUser.phoneNumber}}">{{currentUser.phoneNumber}}</a></p>
+ <p *ngIf=currentUser.addressLine1>{{currentUser.addressLine1}}</p>
+ <p *ngIf=currentUser.addressLine2>{{currentUser.addressLine2}}</p>
+ <p *ngIf=currentUser.company>{{currentUser.company}}</p>
+ <p *ngIf="currentUser.city || currentUser.country || currentUser.stateOrProvince || currentUser.postalCode"><span *ngIf="currentUser.city">{{currentUser.city}}<span *ngIf="currentUser.country || currentUser.stateOrProvince || currentUser.postalCode"> </span></span><span *ngIf="currentUser.stateOrProvince">{{currentUser.stateOrProvince}}<span *ngIf="currentUser.country || currentUser.postalCode">, </span></span><span *ngIf="currentUser.country">{{currentUser.country}}<span *ngIf="currentUser.postalCode">, </span></span><span *ngIf=currentUser.postalCode>{{currentUser.postalCode}}</span></p>
+ </address>
+ <div>
+ <h2>User Theme</h2>
+ <button mat-button (click)="themeSvc.loadTheme(theme)" *ngFor="let theme of themeSvc.themes">{{theme.name}}</button>
+ </div>
+ </main>
-<main *ngIf="currentUser && !editMode">
-<h1><span *ngIf=currentUser.fullName>{{currentUser.fullName}}, </span>{{currentUser.roleName}} user</h1>
-<address>
- <p *ngIf="currentUser.email || currentUser.phoneNumber"><a *ngIf=currentUser.email href="mailto:{{currentUser.email}}">{{currentUser.email}}</a><span *ngIf="currentUser.email && currentUser.phoneNumber">, </span><a *ngIf="currentUser.phoneNumber" href="tel:{{currentUser.phoneNumber}}">{{currentUser.phoneNumber}}</a></p>
- <p *ngIf=currentUser.addressLine1>{{currentUser.addressLine1}}</p>
- <p *ngIf=currentUser.addressLine2>{{currentUser.addressLine2}}</p>
- <p *ngIf=currentUser.company>{{currentUser.company}}</p>
- <p *ngIf="currentUser.city || currentUser.country || currentUser.stateOrProvince || currentUser.postalCode"><span *ngIf="currentUser.city">{{currentUser.city}}<span *ngIf="currentUser.country || currentUser.stateOrProvince || currentUser.postalCode"> </span></span><span *ngIf="currentUser.stateOrProvince">{{currentUser.stateOrProvince}}<span *ngIf="currentUser.country || currentUser.postalCode">, </span></span><span *ngIf="currentUser.country">{{currentUser.country}}<span *ngIf="currentUser.postalCode">, </span></span><span *ngIf=currentUser.postalCode>{{currentUser.postalCode}}</span></p>
-</address>
-</main>
-
-<form *ngIf="editMode && editUser" ngNativeValidate (submit)="submitEdit($event)">
- <mat-form-field style="grid-area: a-start;">
- <mat-label>Username</mat-label>
- <input matInput [(ngModel)]="editUser.username" name="username" type="text" required/>
- </mat-form-field>
- <mat-form-field style="grid-area: z;">
- <mat-label>Full Name</mat-label>
- <input matInput [(ngModel)]="editUser.fullName" name="fullName" type="text" required/>
- </mat-form-field>
- <mat-form-field style="grid-area: b;">
- <mat-label>Email</mat-label>
- <input matInput [(ngModel)]="editUser.email" name="email" type="email"/>
- </mat-form-field>
- <mat-form-field style="grid-area: c;">
- <mat-label>Telephone</mat-label>
- <input matInput [(ngModel)]="editUser.phoneNumber" name="phoneNumber" type="tel"/>
- </mat-form-field>
- <mat-form-field style="grid-area: d;">
- <mat-label>Address Line 1</mat-label>
- <input matInput [(ngModel)]="editUser.addressLine1" name="addressLine1" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: e;">
- <mat-label>Address Line 2</mat-label>
- <input matInput [(ngModel)]="editUser.addressLine2" name="addressLine2" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: f;">
- <mat-label>Company</mat-label>
- <input matInput [(ngModel)]="editUser.company" name="company" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: g;">
- <mat-label>City</mat-label>
- <input matInput [(ngModel)]="editUser.city" name="city" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: h;">
- <mat-label>State or Province</mat-label>
- <input matInput [(ngModel)]="editUser.stateOrProvince" name="stateOrProvince" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: i;">
- <mat-label>Country</mat-label>
- <input matInput [(ngModel)]="editUser.country" name="country" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: j;">
- <mat-label>Postal Code</mat-label>
- <input matInput [(ngModel)]="editUser.postalCode" name="postalCode" type="text"/>
- </mat-form-field>
- <button mat-raised-button style="grid-area: k;">Submit</button>
- <button mat-raised-button color="accent" style="grid-area: l;" type="button" (click)="updatePassword()">Update Password</button>
- <button type="button" mat-raised-button color="warn" (click)="cancelEdit()" style="grid-area: m;">Cancel</button>
-</form>
+ <form *ngIf="editMode && editUser" ngNativeValidate (submit)="submitEdit($event)">
+ <mat-form-field style="grid-area: a-start;">
+ <mat-label>Username</mat-label>
+ <input matInput [(ngModel)]="editUser.username" name="username" type="text" required/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: z;">
+ <mat-label>Full Name</mat-label>
+ <input matInput [(ngModel)]="editUser.fullName" name="fullName" type="text" required/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: b;">
+ <mat-label>Email</mat-label>
+ <input matInput [(ngModel)]="editUser.email" name="email" type="email"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: c;">
+ <mat-label>Telephone</mat-label>
+ <input matInput [(ngModel)]="editUser.phoneNumber" name="phoneNumber" type="tel"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: d;">
+ <mat-label>Address Line 1</mat-label>
+ <input matInput [(ngModel)]="editUser.addressLine1" name="addressLine1" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: e;">
+ <mat-label>Address Line 2</mat-label>
+ <input matInput [(ngModel)]="editUser.addressLine2" name="addressLine2" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: f;">
+ <mat-label>Company</mat-label>
+ <input matInput [(ngModel)]="editUser.company" name="company" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: g;">
+ <mat-label>City</mat-label>
+ <input matInput [(ngModel)]="editUser.city" name="city" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: h;">
+ <mat-label>State or Province</mat-label>
+ <input matInput [(ngModel)]="editUser.stateOrProvince" name="stateOrProvince" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: i;">
+ <mat-label>Country</mat-label>
+ <input matInput [(ngModel)]="editUser.country" name="country" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: j;">
+ <mat-label>Postal Code</mat-label>
+ <input matInput [(ngModel)]="editUser.postalCode" name="postalCode" type="text"/>
+ </mat-form-field>
+ <button mat-raised-button style="grid-area: k;">Submit</button>
+ <button mat-raised-button color="accent" style="grid-area: l;" type="button" (click)="updatePassword()">Update Password</button>
+ <button type="button" mat-raised-button color="warn" (click)="cancelEdit()" style="grid-area: m;">Cancel</button>
Review Comment:
I don't think so, at least not without restructuring the whole form due to the fact adding `mat-card-actions` really messes with the grid layout
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] shamrickus commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
shamrickus commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r878468626
##########
experimental/traffic-portal/src/app/shared/theme-manager/theme-manager.service.ts:
##########
@@ -0,0 +1,154 @@
+/*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import {EventEmitter, Injectable} from "@angular/core";
+
+/**
+ * Defines a theme. If fileName is null, it is the default theme
+ */
+export interface Theme {
+ fileName?: string;
+ name: string;
+}
+
+/**
+ *
+ */
+@Injectable({
+ providedIn: "root"
+})
+export class ThemeManagerService {
+ private static readonly STORAGE_KEY = "current-theme-name";
+ private static readonly LINK_KEY = "themer";
+
+ public themeChanged = new EventEmitter<Theme>();
+
+ /**
+ * Initialize the theme service
+ */
+ public initTheme(): void {
+ const themeName = ThemeManagerService.loadStoredTheme();
+ if(themeName) {
+ this.loadTheme(themeName);
+ }
+ }
+
+ public readonly themes: Array<Theme> = [{
+ name: "Default"
+ },
+ {
+ fileName: "dark-default-theme.css",
+ name: "Dark"
+ }
+ ];
+
+ /**
+ * Given a themes bundle name, load the theme and cache the value
+ *
+ * @param theme Theme to load
+ */
+ public loadTheme(theme: Theme): void {
+ if(theme.fileName === undefined) {
+ this.clearTheme();
+ return;
+ }
+ ThemeManagerService.getThemeLinkElement().setAttribute("href", theme.fileName);
+ ThemeManagerService.storeTheme(theme);
+ this.themeChanged.emit(theme);
+ }
+
+ /**
+ * Revert to the default theme
+ */
+ public clearTheme(): void {
+ const linkEl = ThemeManagerService.getExistingThemeLinkElement();
+ if(linkEl) {
+ document.head.removeChild(linkEl);
+ ThemeManagerService.clearStoredTheme();
+ this.themeChanged.emit(this.themes[0]);
+ }
+ }
+
+ /**
+ * Stores theme in localStorage
+ *
+ * @param theme Theme to be stored
+ * @private
Review Comment:
My IDE must've generated them, they don't appear to serve any purpose
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] shamrickus commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
shamrickus commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r876132620
##########
experimental/traffic-portal/src/app/app.component.ts:
##########
@@ -26,14 +28,15 @@ import { CurrentUserService } from "src/app/shared/currentUser/current-user.serv
styleUrls: ["./app.component.scss"],
templateUrl: "./app.component.html",
})
-export class AppComponent implements OnInit {
+export class AppComponent implements OnInit, AfterViewInit {
+ @ViewChild("header") private readonly headerRef!: TpHeaderComponent;
Review Comment:
The Header service now uses `ReplaySubject` instead of managing the component itself.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] ocket8888 commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
ocket8888 commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r878326227
##########
experimental/traffic-portal/src/app/shared/tp-header/tp-header.component.html:
##########
@@ -11,30 +11,39 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<mat-toolbar color="primary">
- <img src="/assets/logo.svg" alt="Apache Traffic Control logo"/>
+<mat-toolbar color="primary" *ngIf="!hidden">
+ <img src="/assets/logo.svg" alt="Apache Traffic Control logo" routerLink="/core/"/>
Review Comment:
[Image links](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img#image_link) should be wrapped in an Anchor element that does the navigation, rather than relying on Javascript bindings. Also in that case the "alt" text should be changed to a description of the navigation being performed rather than a description of the image.
##########
experimental/traffic-portal/src/app/shared/theme-manager/theme-manager.service.ts:
##########
@@ -0,0 +1,154 @@
+/*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import {EventEmitter, Injectable} from "@angular/core";
+
+/**
+ * Defines a theme. If fileName is null, it is the default theme
+ */
+export interface Theme {
+ fileName?: string;
+ name: string;
+}
+
+/**
+ *
+ */
+@Injectable({
+ providedIn: "root"
+})
+export class ThemeManagerService {
+ private static readonly STORAGE_KEY = "current-theme-name";
+ private static readonly LINK_KEY = "themer";
+
+ public themeChanged = new EventEmitter<Theme>();
+
+ /**
+ * Initialize the theme service
+ */
+ public initTheme(): void {
+ const themeName = ThemeManagerService.loadStoredTheme();
+ if(themeName) {
+ this.loadTheme(themeName);
+ }
+ }
+
+ public readonly themes: Array<Theme> = [{
+ name: "Default"
+ },
+ {
+ fileName: "dark-default-theme.css",
+ name: "Dark"
+ }
+ ];
+
+ /**
+ * Given a themes bundle name, load the theme and cache the value
+ *
+ * @param theme Theme to load
+ */
+ public loadTheme(theme: Theme): void {
+ if(theme.fileName === undefined) {
+ this.clearTheme();
+ return;
+ }
+ ThemeManagerService.getThemeLinkElement().setAttribute("href", theme.fileName);
+ ThemeManagerService.storeTheme(theme);
+ this.themeChanged.emit(theme);
+ }
+
+ /**
+ * Revert to the default theme
+ */
+ public clearTheme(): void {
+ const linkEl = ThemeManagerService.getExistingThemeLinkElement();
+ if(linkEl) {
+ document.head.removeChild(linkEl);
+ ThemeManagerService.clearStoredTheme();
+ this.themeChanged.emit(this.themes[0]);
+ }
+ }
+
+ /**
+ * Stores theme in localStorage
+ *
+ * @param theme Theme to be stored
+ * @private
Review Comment:
I don't think you need to tag things as `@private` when they're already `private` - unless this is catching some edge case of private statics I don't know about?
##########
experimental/traffic-portal/src/app/shared/tp-header/tp-header.component.html:
##########
@@ -11,30 +11,39 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<mat-toolbar color="primary">
- <img src="/assets/logo.svg" alt="Apache Traffic Control logo"/>
+<mat-toolbar color="primary" *ngIf="!hidden">
+ <img src="/assets/logo.svg" alt="Apache Traffic Control logo" routerLink="/core/"/>
<h1>{{title ? title : 'Welcome to Traffic Portal!'}}</h1>
<div></div>
<nav id="expanded">
<ul>
- <li><a routerLink="/core/">Home</a></li>
- <li *ngIf="hasPermission('USER:READ')"><a routerLink="/core/users">Users</a></li>
- <li *ngIf="hasPermission('SERVER:READ')"><a routerLink="/core/servers">Servers</a></li>
- <li><button class="menubutton" type="button" (click)="logout()">Logout</button></li>
- <li><a routerLink="/core/me"><svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 16 16"><g id="surface1"><path d="M 8 2 C 6.347656 2 5 3.347656 5 5 C 5 6.652344 6.347656 8 8 8 C 9.652344 8 11 6.652344 11 5 C 11 3.347656 9.652344 2 8 2 Z M 8 8 C 5.246094 8 3 10.246094 3 13 L 4 13 C 4 10.785156 5.785156 9 8 9 C 10.214844 9 12 10.785156 12 13 L 13 13 C 13 10.246094 10.753906 8 8 8 Z M 8 3 C 9.109375 3 10 3.890625 10 5 C 10 6.109375 9.109375 7 8 7 C 6.890625 7 6 6.109375 6 5 C 6 3.890625 6.890625 3 8 3 Z "></path></g></svg>
- </a></li>
+ <li><button mat-button routerLink="/core/">Home</button></li>
+ <li *ngIf="hasPermission('USER:READ')"><button mat-button routerLink="/core/users">Users</button></li>
+ <li *ngIf="hasPermission('SERVER:READ')"><button mat-button routerLink="/core/servers">Servers</button></li>
+ <li>
+ <button mat-icon-button [matMenuTriggerFor]="expandedMenu">
+ <mat-icon>manage_accounts</mat-icon>
+ </button>
+ <mat-menu #expandedMenu="matMenu">
+ <button mat-menu-item routerLink="/core/me">Profile</button>
+ <button mat-menu-item (click)="logout()">Logout</button>
+ <button mat-menu-item [matMenuTriggerFor]="themeMenu">Theme</button>
+ </mat-menu>
+ </li>
</ul>
</nav>
<nav id="collapsed">
- <input type="checkbox" hidden id="collapsed-menu"/>
- <label for="collapsed-menu"></label>
- <ul>
- <li><a routerLink="/core/">Home</a></li>
- <li *ngIf="hasPermission('USER:READ')"><a routerLink="/core/users">Users</a></li>
- <li *ngIf="hasPermission('SERVER:READ')"><a routerLink="/core/servers">Servers</a></li>
- <li><a href="#">Tools</a></li>
- <li><a href="/core/me">Profile</a></li>
- <li><button type="button" class="menubutton" (click)="logout()">Logout</button></li>
- </ul>
+ <button mat-icon-button [matMenuTriggerFor]="collapsedMenu"><mat-icon>menu</mat-icon></button>
+ <mat-menu #collapsedMenu="matMenu">
+ <button mat-menu-item routerLink="/core/">Home</button>
+ <button *ngIf="hasPermission('USER:READ')" mat-menu-item routerLink="/core/users">Users</button>
+ <button *ngIf="hasPermission('SERVER:READ')" mat-menu-item routerLink="/core/servers">Servers</button>
+ <button mat-menu-item href="/core/me">Profile</button>
Review Comment:
Navigation should use Anchor elements, not buttons.
##########
experimental/traffic-portal/src/app/shared/generic-table/generic-table.component.scss:
##########
@@ -44,9 +44,6 @@ ag-grid-angular {
}
button {
- border-style: solid solid none solid;
- border-radius: 0;
- padding: 0 1em;
}
Review Comment:
don't use empty rulesets - this whole block should just be removed, looks like.
##########
experimental/traffic-portal/src/app/shared/generic-table/generic-table.component.ts:
##########
@@ -435,6 +436,7 @@ export class GenericTableComponent<T> implements OnInit, OnDestroy {
const visible = column.isVisible();
this.columnAPI.setColumnVisible(col, !visible);
}
+ $event.stopPropagation();
Review Comment:
This method can return before it gets to this point - should it stop propagation immediately? Or is propagation only desirable in the case that visibility setting fails?
##########
experimental/traffic-portal/src/app/shared/tp-header/tp-header.component.html:
##########
@@ -11,30 +11,39 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<mat-toolbar color="primary">
- <img src="/assets/logo.svg" alt="Apache Traffic Control logo"/>
+<mat-toolbar color="primary" *ngIf="!hidden">
+ <img src="/assets/logo.svg" alt="Apache Traffic Control logo" routerLink="/core/"/>
<h1>{{title ? title : 'Welcome to Traffic Portal!'}}</h1>
<div></div>
<nav id="expanded">
<ul>
- <li><a routerLink="/core/">Home</a></li>
- <li *ngIf="hasPermission('USER:READ')"><a routerLink="/core/users">Users</a></li>
- <li *ngIf="hasPermission('SERVER:READ')"><a routerLink="/core/servers">Servers</a></li>
- <li><button class="menubutton" type="button" (click)="logout()">Logout</button></li>
- <li><a routerLink="/core/me"><svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 16 16"><g id="surface1"><path d="M 8 2 C 6.347656 2 5 3.347656 5 5 C 5 6.652344 6.347656 8 8 8 C 9.652344 8 11 6.652344 11 5 C 11 3.347656 9.652344 2 8 2 Z M 8 8 C 5.246094 8 3 10.246094 3 13 L 4 13 C 4 10.785156 5.785156 9 8 9 C 10.214844 9 12 10.785156 12 13 L 13 13 C 13 10.246094 10.753906 8 8 8 Z M 8 3 C 9.109375 3 10 3.890625 10 5 C 10 6.109375 9.109375 7 8 7 C 6.890625 7 6 6.109375 6 5 C 6 3.890625 6.890625 3 8 3 Z "></path></g></svg>
- </a></li>
+ <li><button mat-button routerLink="/core/">Home</button></li>
+ <li *ngIf="hasPermission('USER:READ')"><button mat-button routerLink="/core/users">Users</button></li>
+ <li *ngIf="hasPermission('SERVER:READ')"><button mat-button routerLink="/core/servers">Servers</button></li>
+ <li>
+ <button mat-icon-button [matMenuTriggerFor]="expandedMenu">
+ <mat-icon>manage_accounts</mat-icon>
+ </button>
+ <mat-menu #expandedMenu="matMenu">
+ <button mat-menu-item routerLink="/core/me">Profile</button>
Review Comment:
navigation should use Anchor elements, not buttons
##########
experimental/traffic-portal/src/app/core/servers/servers-table/servers-table.component.html:
##########
@@ -11,19 +11,22 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<tp-header [title]="'Servers'"></tp-header>
<main>
- <div>
- <input type="search" name="fuzzControl" aria-label="Fuzzy Search Servers" autofocus inputmode="search" role="search" accesskey="/" placeholder="Fuzzy Search" [formControl]="fuzzControl" (input)="updateURL()"/>
- </div>
- <tp-generic-table
- [data]="servers | async"
- [cols]="columnDefs"
- [fuzzySearch]="fuzzySubject"
- context="servers"
- [contextMenuItems]="contextMenuItems"
- (contextMenuAction)="handleContextMenu($event)">
- </tp-generic-table>
+ <mat-card>
+ <div>
+ <input type="search" name="fuzzControl" aria-label="Fuzzy Search Servers" autofocus inputmode="search" role="search" accesskey="/" placeholder="Fuzzy Search" [formControl]="fuzzControl" (input)="updateURL()"/>
+ </div>
+ <tp-generic-table
+ [data]="servers | async"
+ [cols]="columnDefs"
+ [fuzzySearch]="fuzzySubject"
+ context="servers"
+ [contextMenuItems]="contextMenuItems"
+ (contextMenuAction)="handleContextMenu($event)">
+ </tp-generic-table>
+ </mat-card>
</main>
+<!--
<tp-update-status *ngIf="changeStatusOpen" [servers]="changeStatusServers" (done)="statusUpdated($event)"></tp-update-status>
+-->
Review Comment:
This should be removed instead of just commented out
##########
experimental/traffic-portal/src/app/login/login.component.html:
##########
@@ -11,15 +11,29 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<header>
- <img src="assets/logo.svg" alt="Apache Traffic Control logo"/><h1>Traffic Portal</h1>
-</header>
-<form name="login" (ngSubmit)="submitLogin()" ngNativeValidate>
- <label for="u">Username</label><input required autocomplete="username" autofocus type="text" [formControl]="u" name="u" id="u"/>
- <label for="p">Password</label><input required autocomplete="current-password" type="password" [formControl]="p" name="p" id="p"/>
- <div>
- <button name="login" mat-raised-button>Login</button>
- <button name="reset" mat-button color="accent" type="button" (click)="resetPassword()">Forgot Password</button>
- <button name="clear" mat-raised-button color="warn" type="reset">Clear</button>
- </div>
-</form>
+<mat-card>
+ <mat-card-header>
+ <img src="assets/logo.svg" alt="Apache Traffic Control logo"/>
+ <h1>Traffic Portal</h1>
+ </mat-card-header>
+ <mat-card-content>
+ <form name="login" (ngSubmit)="submitLogin()" ngNativeValidate>
+ <mat-form-field appearance="fill">
+ <mat-label>Username</mat-label>
+ <input matInput required autofocus type="text" [formControl]="u" id="u"/>
+ </mat-form-field>
+ <mat-form-field appearance="fill">
+ <mat-label>Password</mat-label>
+ <input matInput required [type]="hide ? 'password' : 'text'" [formControl]="p" id="p"/>
+ <button mat-icon-button matSuffix (click)="hide = !hide">
Review Comment:
especially inside a form, a button that doesn't submit the form must have the `type` attribute set to "button". Currently, clicking on this twice submits the form. Frankly idk why it's only every other time it's clicked instead of every time.
##########
experimental/traffic-portal/src/app/core/servers/update-status/update-status.component.html:
##########
@@ -11,22 +11,20 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<dialog open>
- <h2>Change status for {{serverName}}</h2>
- <hr/>
- <!-- method=dialog doesn't work in Firefox - even with the dialog element enabled in about:config-->
- <!-- So we need to preventDefault on this event anyway -->
- <form ngNativeValidate (ngSubmit)="submit($event)" method="dialog">
- <label for="status">New Status</label>
- <select id="status" name="status" [formControl]="statusControl" required>
- <option *ngFor="let status of statuses" [ngValue]="status" [disabled]="status.id === currentStatus">{{status.name}}</option>
- </select>
- <label *ngIf="isOffline" for="offlineReason">Offline Reason</label>
- <input [formControl]="offlineReasonControl" id="offlineReason" name="offlineReason" *ngIf="isOffline" required maxlength="100"/>
- <div>
- <button mat-raised-button color="warn" type="button" (click)="cancel()">Cancel</button>
- <button mat-raised-button>Submit</button>
- </div>
- </form>
-</dialog>
-<div class="backdrop"></div>
+<h2 mat-dialog-title>Change status for {{serverName}}</h2>
+<div mat-dialog-content>
+ <mat-form-field appearance="fill">
+ <mat-label for="status">New Status</mat-label>
+ <mat-select id="status" name="status" [(ngModel)]="status" required>
+ <mat-option *ngFor="let status of statuses" [value]="status" [disabled]="status.id === currentStatus">{{status.name}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ <mat-form-field *ngIf="isOffline" appearance="fill">
+ <mat-label for="offlineReason">Offline Reason</mat-label>
+ <input matInput [(ngModel)]="offlineReason" id="offlineReason" name="offlineReason" required maxlength="100"/>
+ </mat-form-field>
+</div>
+<div mat-dialog-actions>
+ <button mat-raised-button disabled="{{status === null || isOffline && offlineReason === ''}}" (click)="submit()">Submit</button>
+ <button mat-raised-button color="warn" type="button" (click)="cancel()">Cancel</button>
+</div>
Review Comment:
The behavior here is now changed. Whether or not you can submit the form is no longer directly tied to the validity of any form. In fact, there is no longer a form at all, so assistive technologies can't tell the user what information is being submitted or what inputs on the page are tied to the submit button. The submit button has implicitly `type=submit` but has no linked form that it submits. Validation messages aren't displayed; I can see that the button is unavailable, but there is no information as to why in the accessibility details of the page.
Compare to this simple document:
```html
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
</head>
<body>
<form>
<label>Something<input type="text" name="something" required minlength="10" maxlength="100"/></label>
<button>Submit</button>
</form>
</html>
```
You can see in the accessibility details links between the form's validity and the validity of its inputs. This tells the user not only *that* the form cannot be submitted, but also *why*. If you try to submit it anyway, a validation error is displayed to the user - no such message is possible in this mat-dialog as-is.
Furthermore, if in the future we decided, for example, that offline reasons should be at least 10 characters long, or that they can't consist of only whitespace it would have been as simple as adding `minlength=10` or `pattern=".*\S.*"` to the input, respectively. Now I have to add that to the input *and* the boolean expression that disables the submit button, which gets progressively more complex until we wind up writing a custom validator for features built into HTML since version 2.
tl;dr forms should be in `<form>`s
##########
experimental/traffic-portal/src/app/core/currentuser/currentuser.component.html:
##########
@@ -11,67 +11,71 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<tp-header [title]="currentUser ? currentUser.username : ''"></tp-header>
+<mat-card>
+ <main *ngIf="currentUser && !editMode">
+ <h1><span *ngIf=currentUser.fullName>{{currentUser.fullName}}, </span>{{currentUser.roleName}} user</h1>
+ <address>
+ <p *ngIf="currentUser.email || currentUser.phoneNumber"><a *ngIf=currentUser.email href="mailto:{{currentUser.email}}">{{currentUser.email}}</a><span *ngIf="currentUser.email && currentUser.phoneNumber">, </span><a *ngIf="currentUser.phoneNumber" href="tel:{{currentUser.phoneNumber}}">{{currentUser.phoneNumber}}</a></p>
+ <p *ngIf=currentUser.addressLine1>{{currentUser.addressLine1}}</p>
+ <p *ngIf=currentUser.addressLine2>{{currentUser.addressLine2}}</p>
+ <p *ngIf=currentUser.company>{{currentUser.company}}</p>
+ <p *ngIf="currentUser.city || currentUser.country || currentUser.stateOrProvince || currentUser.postalCode"><span *ngIf="currentUser.city">{{currentUser.city}}<span *ngIf="currentUser.country || currentUser.stateOrProvince || currentUser.postalCode"> </span></span><span *ngIf="currentUser.stateOrProvince">{{currentUser.stateOrProvince}}<span *ngIf="currentUser.country || currentUser.postalCode">, </span></span><span *ngIf="currentUser.country">{{currentUser.country}}<span *ngIf="currentUser.postalCode">, </span></span><span *ngIf=currentUser.postalCode>{{currentUser.postalCode}}</span></p>
+ </address>
+ <div>
+ <h2>User Theme</h2>
+ <button mat-button (click)="themeSvc.loadTheme(theme)" *ngFor="let theme of themeSvc.themes">{{theme.name}}</button>
+ </div>
+ </main>
-<main *ngIf="currentUser && !editMode">
-<h1><span *ngIf=currentUser.fullName>{{currentUser.fullName}}, </span>{{currentUser.roleName}} user</h1>
-<address>
- <p *ngIf="currentUser.email || currentUser.phoneNumber"><a *ngIf=currentUser.email href="mailto:{{currentUser.email}}">{{currentUser.email}}</a><span *ngIf="currentUser.email && currentUser.phoneNumber">, </span><a *ngIf="currentUser.phoneNumber" href="tel:{{currentUser.phoneNumber}}">{{currentUser.phoneNumber}}</a></p>
- <p *ngIf=currentUser.addressLine1>{{currentUser.addressLine1}}</p>
- <p *ngIf=currentUser.addressLine2>{{currentUser.addressLine2}}</p>
- <p *ngIf=currentUser.company>{{currentUser.company}}</p>
- <p *ngIf="currentUser.city || currentUser.country || currentUser.stateOrProvince || currentUser.postalCode"><span *ngIf="currentUser.city">{{currentUser.city}}<span *ngIf="currentUser.country || currentUser.stateOrProvince || currentUser.postalCode"> </span></span><span *ngIf="currentUser.stateOrProvince">{{currentUser.stateOrProvince}}<span *ngIf="currentUser.country || currentUser.postalCode">, </span></span><span *ngIf="currentUser.country">{{currentUser.country}}<span *ngIf="currentUser.postalCode">, </span></span><span *ngIf=currentUser.postalCode>{{currentUser.postalCode}}</span></p>
-</address>
-</main>
-
-<form *ngIf="editMode && editUser" ngNativeValidate (submit)="submitEdit($event)">
- <mat-form-field style="grid-area: a-start;">
- <mat-label>Username</mat-label>
- <input matInput [(ngModel)]="editUser.username" name="username" type="text" required/>
- </mat-form-field>
- <mat-form-field style="grid-area: z;">
- <mat-label>Full Name</mat-label>
- <input matInput [(ngModel)]="editUser.fullName" name="fullName" type="text" required/>
- </mat-form-field>
- <mat-form-field style="grid-area: b;">
- <mat-label>Email</mat-label>
- <input matInput [(ngModel)]="editUser.email" name="email" type="email"/>
- </mat-form-field>
- <mat-form-field style="grid-area: c;">
- <mat-label>Telephone</mat-label>
- <input matInput [(ngModel)]="editUser.phoneNumber" name="phoneNumber" type="tel"/>
- </mat-form-field>
- <mat-form-field style="grid-area: d;">
- <mat-label>Address Line 1</mat-label>
- <input matInput [(ngModel)]="editUser.addressLine1" name="addressLine1" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: e;">
- <mat-label>Address Line 2</mat-label>
- <input matInput [(ngModel)]="editUser.addressLine2" name="addressLine2" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: f;">
- <mat-label>Company</mat-label>
- <input matInput [(ngModel)]="editUser.company" name="company" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: g;">
- <mat-label>City</mat-label>
- <input matInput [(ngModel)]="editUser.city" name="city" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: h;">
- <mat-label>State or Province</mat-label>
- <input matInput [(ngModel)]="editUser.stateOrProvince" name="stateOrProvince" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: i;">
- <mat-label>Country</mat-label>
- <input matInput [(ngModel)]="editUser.country" name="country" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: j;">
- <mat-label>Postal Code</mat-label>
- <input matInput [(ngModel)]="editUser.postalCode" name="postalCode" type="text"/>
- </mat-form-field>
- <button mat-raised-button style="grid-area: k;">Submit</button>
- <button mat-raised-button color="accent" style="grid-area: l;" type="button" (click)="updatePassword()">Update Password</button>
- <button type="button" mat-raised-button color="warn" (click)="cancelEdit()" style="grid-area: m;">Cancel</button>
-</form>
+ <form *ngIf="editMode && editUser" ngNativeValidate (submit)="submitEdit($event)">
+ <mat-form-field style="grid-area: a-start;">
+ <mat-label>Username</mat-label>
+ <input matInput [(ngModel)]="editUser.username" name="username" type="text" required/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: z;">
+ <mat-label>Full Name</mat-label>
+ <input matInput [(ngModel)]="editUser.fullName" name="fullName" type="text" required/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: b;">
+ <mat-label>Email</mat-label>
+ <input matInput [(ngModel)]="editUser.email" name="email" type="email"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: c;">
+ <mat-label>Telephone</mat-label>
+ <input matInput [(ngModel)]="editUser.phoneNumber" name="phoneNumber" type="tel"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: d;">
+ <mat-label>Address Line 1</mat-label>
+ <input matInput [(ngModel)]="editUser.addressLine1" name="addressLine1" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: e;">
+ <mat-label>Address Line 2</mat-label>
+ <input matInput [(ngModel)]="editUser.addressLine2" name="addressLine2" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: f;">
+ <mat-label>Company</mat-label>
+ <input matInput [(ngModel)]="editUser.company" name="company" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: g;">
+ <mat-label>City</mat-label>
+ <input matInput [(ngModel)]="editUser.city" name="city" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: h;">
+ <mat-label>State or Province</mat-label>
+ <input matInput [(ngModel)]="editUser.stateOrProvince" name="stateOrProvince" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: i;">
+ <mat-label>Country</mat-label>
+ <input matInput [(ngModel)]="editUser.country" name="country" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: j;">
+ <mat-label>Postal Code</mat-label>
+ <input matInput [(ngModel)]="editUser.postalCode" name="postalCode" type="text"/>
+ </mat-form-field>
+ <button mat-raised-button style="grid-area: k;">Submit</button>
+ <button mat-raised-button color="accent" style="grid-area: l;" type="button" (click)="updatePassword()">Update Password</button>
+ <button type="button" mat-raised-button color="warn" (click)="cancelEdit()" style="grid-area: m;">Cancel</button>
Review Comment:
should these be in the card actions?
##########
experimental/traffic-portal/src/app/core/currentuser/currentuser.component.html:
##########
@@ -11,67 +11,71 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<tp-header [title]="currentUser ? currentUser.username : ''"></tp-header>
+<mat-card>
+ <main *ngIf="currentUser && !editMode">
+ <h1><span *ngIf=currentUser.fullName>{{currentUser.fullName}}, </span>{{currentUser.roleName}} user</h1>
+ <address>
+ <p *ngIf="currentUser.email || currentUser.phoneNumber"><a *ngIf=currentUser.email href="mailto:{{currentUser.email}}">{{currentUser.email}}</a><span *ngIf="currentUser.email && currentUser.phoneNumber">, </span><a *ngIf="currentUser.phoneNumber" href="tel:{{currentUser.phoneNumber}}">{{currentUser.phoneNumber}}</a></p>
+ <p *ngIf=currentUser.addressLine1>{{currentUser.addressLine1}}</p>
+ <p *ngIf=currentUser.addressLine2>{{currentUser.addressLine2}}</p>
+ <p *ngIf=currentUser.company>{{currentUser.company}}</p>
+ <p *ngIf="currentUser.city || currentUser.country || currentUser.stateOrProvince || currentUser.postalCode"><span *ngIf="currentUser.city">{{currentUser.city}}<span *ngIf="currentUser.country || currentUser.stateOrProvince || currentUser.postalCode"> </span></span><span *ngIf="currentUser.stateOrProvince">{{currentUser.stateOrProvince}}<span *ngIf="currentUser.country || currentUser.postalCode">, </span></span><span *ngIf="currentUser.country">{{currentUser.country}}<span *ngIf="currentUser.postalCode">, </span></span><span *ngIf=currentUser.postalCode>{{currentUser.postalCode}}</span></p>
+ </address>
+ <div>
+ <h2>User Theme</h2>
+ <button mat-button (click)="themeSvc.loadTheme(theme)" *ngFor="let theme of themeSvc.themes">{{theme.name}}</button>
Review Comment:
The default type of buttons is `submit` - this should be a `button[type=button]` because it doesn't submit a form it just performs an interactive action.
##########
experimental/traffic-portal/src/app/core/invalidation-jobs/invalidation-jobs.component.html:
##########
@@ -11,32 +11,39 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<tp-header title="{{deliveryservice ? deliveryservice.displayName : 'Loading'}} - Content Invalidation Jobs"></tp-header>
-<ul>
- <li class="invalidation-job" *ngFor="let j of jobs">
- <code>{{j.assetUrl}}</code> (active from <time [dateTime]="j.startTime">{{j.startTime | date:'medium'}}</time> to <time [dateTime]="endDate(j)">{{endDate(j) | date:'medium'}})</time>
- <button
- mat-icon-button
- type="button"
- color="accent"
- title="Edit this content invalidation job"
- aria-label="Edit this content invalidation job"
- [disabled]="j.startTime <= now"
- (click)="editJob(j)"
- >
- <fa-icon [icon]="editIcon"></fa-icon>
- </button>
- <button
- mat-icon-button
- type="button"
- color="warn"
- title="Delete this content invalidation job"
- aria-label="Delete this content invalidation job"
- [disabled]="isInProgress(j)"
- (click)="deleteJob(j.id)"
- >
- <fa-icon [icon]="deleteIcon"></fa-icon>
- </button>
- </li>
-</ul>
-<button mat-fab type="button" id="new" title="Create a new content invalidation job for this Delivery Service" (click)="newJob()"><fa-icon [icon]="addIcon"></fa-icon></button>
+<mat-card>
+ <ul>
+ <li class="invalidation-job" *ngFor="let j of jobs">
+ <div>
+ <div class="invalidation-info">
+ <span>{{j.assetUrl}} (active from <time [dateTime]="j.startTime">{{j.startTime | date:'medium'}}</time> to <time [dateTime]="endDate(j)">{{endDate(j) | date:'medium'}})</time></span>
+ </div>
+ <div class="spacer"></div>
Review Comment:
This div is unnecessary; the class applies no styling and it appears to exist simply to take up space. Just set the parent element's `justify-content` to `space-between` to achieve the same look without needing useless elements.
##########
experimental/traffic-portal/src/app/shared/theme-manager/theme-manager.service.ts:
##########
@@ -0,0 +1,154 @@
+/*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import {EventEmitter, Injectable} from "@angular/core";
+
+/**
+ * Defines a theme. If fileName is null, it is the default theme
+ */
+export interface Theme {
+ fileName?: string;
+ name: string;
+}
+
+/**
+ *
+ */
+@Injectable({
+ providedIn: "root"
+})
+export class ThemeManagerService {
+ private static readonly STORAGE_KEY = "current-theme-name";
+ private static readonly LINK_KEY = "themer";
+
+ public themeChanged = new EventEmitter<Theme>();
+
+ /**
+ * Initialize the theme service
+ */
+ public initTheme(): void {
+ const themeName = ThemeManagerService.loadStoredTheme();
+ if(themeName) {
+ this.loadTheme(themeName);
+ }
+ }
+
+ public readonly themes: Array<Theme> = [{
+ name: "Default"
+ },
+ {
+ fileName: "dark-default-theme.css",
+ name: "Dark"
+ }
+ ];
+
+ /**
+ * Given a themes bundle name, load the theme and cache the value
+ *
+ * @param theme Theme to load
+ */
+ public loadTheme(theme: Theme): void {
+ if(theme.fileName === undefined) {
+ this.clearTheme();
+ return;
+ }
+ ThemeManagerService.getThemeLinkElement().setAttribute("href", theme.fileName);
+ ThemeManagerService.storeTheme(theme);
+ this.themeChanged.emit(theme);
+ }
+
+ /**
+ * Revert to the default theme
+ */
+ public clearTheme(): void {
+ const linkEl = ThemeManagerService.getExistingThemeLinkElement();
+ if(linkEl) {
+ document.head.removeChild(linkEl);
Review Comment:
Access to `document` should be done using [the `DOCUMENT` injection token](https://angular.io/api/common/DOCUMENT). You can see an example in the `NewDeliveryServiceComponent` source file.
##########
experimental/traffic-portal/src/app/core/servers/update-status/update-status.component.ts:
##########
@@ -106,31 +94,29 @@ export class UpdateStatusComponent implements OnInit {
*
* @param e The submission event.
Review Comment:
This param no longer exists (but re: my earlier comment about forms, it should)
##########
experimental/traffic-portal/src/app/core/invalidation-jobs/invalidation-jobs.component.html:
##########
@@ -11,32 +11,39 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<tp-header title="{{deliveryservice ? deliveryservice.displayName : 'Loading'}} - Content Invalidation Jobs"></tp-header>
-<ul>
- <li class="invalidation-job" *ngFor="let j of jobs">
- <code>{{j.assetUrl}}</code> (active from <time [dateTime]="j.startTime">{{j.startTime | date:'medium'}}</time> to <time [dateTime]="endDate(j)">{{endDate(j) | date:'medium'}})</time>
- <button
- mat-icon-button
- type="button"
- color="accent"
- title="Edit this content invalidation job"
- aria-label="Edit this content invalidation job"
- [disabled]="j.startTime <= now"
- (click)="editJob(j)"
- >
- <fa-icon [icon]="editIcon"></fa-icon>
- </button>
- <button
- mat-icon-button
- type="button"
- color="warn"
- title="Delete this content invalidation job"
- aria-label="Delete this content invalidation job"
- [disabled]="isInProgress(j)"
- (click)="deleteJob(j.id)"
- >
- <fa-icon [icon]="deleteIcon"></fa-icon>
- </button>
- </li>
-</ul>
-<button mat-fab type="button" id="new" title="Create a new content invalidation job for this Delivery Service" (click)="newJob()"><fa-icon [icon]="addIcon"></fa-icon></button>
+<mat-card>
+ <ul>
Review Comment:
should this be a `mat-list`?
##########
experimental/traffic-portal/src/app/core/servers/server-details/server-details.component.html:
##########
@@ -11,130 +11,189 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<tp-header [title]="title"></tp-header>
-<div class="actions-container" *ngIf="!isNew">
- <button [disabled]="!isCache()" mat-button type="button">Manage Capabilities</button>
- <button [disabled]="!isCache()" mat-button type="button">Manage Delivery Services</button>
- <button [disabled]="!isCache()" mat-icon-button type="button" title="queue server updates" *ngIf="!server.updPending"><fa-icon [icon]="updateIcon"></fa-icon></button>
- <button [disabled]="!isCache()" mat-icon-button type="button" title="clear server updates" *ngIf="server.updPending"><fa-icon [icon]="clearUpdatesIcon"></fa-icon></button>
- <button type="button" mat-icon-button title="change server status" (click)="changeStatus($event)"><fa-icon [icon]="statusChangeIcon"></fa-icon></button>
-</div>
-<form ngNativeValidate #serverForm="ngForm" (ngSubmit)="submit($event)">
- <label for="id" *ngIf="!isNew">ID</label>
- <input type="number" [value]="server.id" readonly *ngIf="!isNew"/>
- <label for="lastUpdated" *ngIf="!isNew && server.lastUpdated">Last Updated</label>
- <input id="lastUpdated" *ngIf="!isNew && server.lastUpdated" [value]="server.lastUpdated.toLocaleString()" readonly/>
- <label for="hostname">Host Name</label>
- <input type="text" [(ngModel)]="server.hostName" id="hostname" name="hostname" required maxlength="50"/>
- <label for="domainname">Domain Name</label>
- <input type="text" [(ngModel)]="server.domainName" id="domainname" name="domainname" required maxlength="50"/>
- <label for="cachegroup">Cache Group</label>
- <select name="cachegroup" id="cachegroup" [(ngModel)]="server.cachegroupId" required>
- <option *ngFor="let cg of cacheGroups" [ngValue]="cg.id">{{cg.name}}</option>
- </select>
- <label for="cdn">CDN</label>
- <select name="cdn" id="cdn" [(ngModel)]="server.cdnId" required>
- <option *ngFor="let cdn of cdns" [ngValue]="cdn.id">{{cdn.name}}</option>
- </select>
- <label for="status">Status</label>
- <input type="text" id="status" name="status" readonly [value]="server.status" *ngIf="!isNew"/>
- <select id="status" name="status" *ngIf="isNew" [(ngModel)]="server.statusId" required>
- <option *ngFor="let status of statuses" [ngValue]="status.id">{{status.name}}</option>
- </select>
- <label for="profile">Profile</label>
- <select id="profile" name="profile" [(ngModel)]="server.profileId" required>
- <option *ngFor="let profile of profiles" [ngValue]="profile.id">{{profile.name}}</option>
- </select>
- <label for="type">Type</label>
- <select id="type" name="type" [(ngModel)]="server.typeId" required>
- <option *ngFor="let type of types" [ngValue]="type.id">{{type.name}}</option>
- </select>
- <label for="physLocation">Physical Location</label>
- <select id="physLocation" name="physLocation" [(ngModel)]="server.physLocationId" required>
- <option *ngFor="let physLocation of physicalLocations" [ngValue]="physLocation.id">{{physLocation.name}}</option>
- </select>
- <label for="httpport">HTTP Port</label>
- <input id="httpport" name="httpport" type="number" [(ngModel)]="server.tcpPort" min="1" max="65535"/>
- <label for="httpsport">HTTPS Port</label>
- <input id="httpsport" name="httpsport" type="number" [(ngModel)]="server.httpsPort" min="1" max="65535"/>
- <fieldset>
- <legend (click)="hideInterfaces=!hideInterfaces">Interfaces<button name="addInterfaceBtn" class="add-button" type="button" title="add a new interface" (click)="addInterface($event)"><fa-icon [icon]="addIcon"></fa-icon></button></legend>
- <fieldset [hidden]="hideInterfaces" *ngFor="let inf of server.interfaces; index as infInd">
- <legend>
- <label for="{{inf.name}}-name">Name</label>
- <input type="text" [(ngModel)]="inf.name" required aria-label="Interface name" id="{{inf.name}}-name" name="{{inf.name}}-name" class="interface-name-input"/>
- <button class="remove-button" type="button" title="delete this interface" (click)="deleteInterface(infInd)"><fa-icon [icon]="removeIcon"></fa-icon></button>
- </legend>
-
+<mat-card>
+ <mat-card-content>
+ <div class="actions-container" *ngIf="!isNew">
+ <button [disabled]="!isCache()" mat-button type="button">Manage Capabilities</button>
+ <button [disabled]="!isCache()" mat-button type="button">Manage Delivery Services</button>
+ <button [disabled]="!isCache()" mat-icon-button type="button" title="queue server updates" *ngIf="!server.updPending"><fa-icon [icon]="updateIcon"></fa-icon></button>
+ <button [disabled]="!isCache()" mat-icon-button type="button" title="clear server updates" *ngIf="server.updPending"><fa-icon [icon]="clearUpdatesIcon"></fa-icon></button>
+ <button type="button" mat-icon-button title="change server status" (click)="changeStatus($event)"><fa-icon [icon]="statusChangeIcon"></fa-icon></button>
+ </div>
+ <form ngNativeValidate #serverForm="ngForm" (ngSubmit)="submit($event)">
+ <mat-form-field>
+ <mat-label>Host Name</mat-label>
+ <input matInput [(ngModel)]="server.hostName" name="hostname" required maxlength="50"/>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Domain Name</mat-label>
+ <input matInput [(ngModel)]="server.domainName" name="domainname" required maxlength="50"/>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>CDN</mat-label>
+ <mat-select name="cdn" [(ngModel)]="server.cdnId" required>
+ <mat-option *ngFor="let cdn of cdns" [value]="cdn.id">{{cdn.name}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Cache Group</mat-label>
+ <mat-select name="cachegroup" [(ngModel)]="server.cachegroupId" required>
+ <mat-option *ngFor="let cg of cacheGroups" [value]="cg.id">{{cg.name}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Profile</mat-label>
+ <mat-select name="profile" [(ngModel)]="server.profileId" required>
+ <mat-option *ngFor="let profile of profiles" [value]="profile.id">{{profile.name}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Physical Location</mat-label>
+ <mat-select name="physLocation" [(ngModel)]="server.physLocationId" required>
+ <mat-option *ngFor="let physLocation of physicalLocations" [value]="physLocation.id">{{physLocation.name}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Status</mat-label>
+ <input matInput name="status" disabled [value]="server.status" *ngIf="!isNew"/>
+ <mat-select name="status" *ngIf="isNew" [(ngModel)]="server.statusId" required>
+ <mat-option *ngFor="let status of statuses" [value]="status.id">{{status.name}}</mat-option>
+ </mat-select>
+ </mat-form-field>
+ <mat-form-field *ngIf="!isNew && server.offlineReason">
+ <mat-label>Offline Reason</mat-label>
+ <input matInput name="offlineReason" disabled [value]="server.offlineReason"/>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Type</mat-label>
+ <mat-select name="type" [(ngModel)]="server.typeId" required>
+ <mat-option *ngFor="let type of types" [value]="type.id">{{type.name}}</mat-option>
+ </mat-select>
+ </mat-form-field>
<div>
- <label for="{{inf.name}}-monitor">Monitor this interface</label>
- <input id="{{inf.name}}-monitor" name="{{inf.name}}-monitor" type="checkbox" [(ngModel)]="inf.monitor"/>
- <label for="{{inf.name}}-mtu"><abbr title="Maximum Transmission Unit">MTU</abbr></label>
- <input id="{{inf.name}}-mtu" name="{{inf.name}}-mtu" type="number" min="1500" max="9000" step="7500" [(ngModel)]="inf.mtu"/>
- <!-- <small class="input-error" ng-show="hasPropertyError(serverForm[inf.name+'-mtu'], 'min') || hasPropertyError(serverForm[inf.name+'-mtu'], 'max') || hasPropertyError(serverForm[inf.name+'-mtu'], 'step')">Invalid MTU - must be 1500 or 9000</small> -->
- <label for="{{inf.name}}-max-bandwidth">Maximum Bandwidth</label>
- <input id="{{inf.name}}-max-bandwidth" [(ngModel)]="inf.maxBandwidth" min="0" type="number" name="{{inf.name}}-max-bandwidth"/>
- <small class="input-warning" [hidden]="inf.maxBandwidth !== 0">Setting Max Bandwidth to zero will cause cache servers to always be unavailable</small>
- <!-- <small class="input-error" ng-show="hasPropertyError(serverForm[inf.name+'-max-bandwidth'], 'min')">Cannot be negative</small> -->
+ <mat-form-field>
+ <mat-label>HTTP Port</mat-label>
+ <input matInput name="httpport" type="number" [(ngModel)]="server.tcpPort" min="1" max="65535"/>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>HTTPS Port</mat-label>
+ <input matInput name="httpsport" type="number" [(ngModel)]="server.httpsPort" min="1" max="65535"/>
+ </mat-form-field>
</div>
+ <mat-form-field>
+ <mat-label>Rack</mat-label>
+ <input matInput name="rack" [(ngModel)]="server.rack"/>
+ </mat-form-field>
+ <mat-form-field *ngIf="!isNew">
+ <mat-label>ID</mat-label>
+ <input name="serverId" matInput type="number" [value]="server.id" disabled/>
+ </mat-form-field>
+ <mat-form-field *ngIf="!isNew && server.lastUpdated">
+ <mat-label>Last Updated</mat-label>
+ <input matInput [value]="server.lastUpdated.toLocaleString()" disabled/>
+ </mat-form-field>
+ <mat-form-field *ngIf="!isNew">
+ <mat-label>Hash ID</mat-label>
+ <input matInput disabled name="xmppId" [value]="server.xmppId"/>
+ </mat-form-field>
+ <mat-form-field *ngIf="!isNew && server.statusLastUpdated">
+ <mat-label>Status Last Updated</mat-label>
+ <input matInput name="statusLastUpdated" disabled [value]="server.statusLastUpdated.toLocaleString()"/>
+ </mat-form-field>
+ <fieldset>
+ <legend (click)="hideInterfaces=!hideInterfaces">Interfaces<button name="addInterfaceBtn" class="add-button" type="button" title="add a new interface" (click)="addInterface($event)"><fa-icon [icon]="addIcon"></fa-icon></button></legend>
+ <fieldset [hidden]="hideInterfaces" *ngFor="let inf of server.interfaces; index as infInd">
+ <legend>
+ <label for="{{inf.name}}-name">Name</label>
+ <input [(ngModel)]="inf.name" required aria-label="Interface name" id="{{inf.name}}-name" name="{{inf.name}}-name" class="interface-name-input"/>
+ <button class="remove-button" type="button" title="delete this interface" (click)="deleteInterface(infInd)"><fa-icon [icon]="removeIcon"></fa-icon></button>
+ </legend>
+ <div>
+ <mat-checkbox [labelPosition]="'before'" id="{{inf.name}}-monitor" name="{{inf.name}}-monitor" [(ngModel)]="inf.monitor">Monitor this interface</mat-checkbox>
+ <mat-form-field>
+ <mat-label><abbr title="Maximum Transmission Unit">MTU</abbr></mat-label>
+ <input matInput id="{{inf.name}}-mtu" name="{{inf.name}}-mtu" type="number" min="1500" max="9000" step="7500" [(ngModel)]="inf.mtu"/>
+ </mat-form-field>
+ <!-- <small class="input-error" ng-show="hasPropertyError(serverForm[inf.name+'-mtu'], 'min') || hasPropertyError(serverForm[inf.name+'-mtu'], 'max') || hasPropertyError(serverForm[inf.name+'-mtu'], 'step')">Invalid MTU - must be 1500 or 9000</small> -->
+ <mat-form-field>
+ <mat-label>Maximum Bandwidth</mat-label>
+ <input matInput id="{{inf.name}}-max-bandwidth" [(ngModel)]="inf.maxBandwidth" min="0" type="number" name="{{inf.name}}-max-bandwidth"/>
+ <mat-error class="input-warning" *ngIf="inf.maxBandwidth !== 0">Setting Max Bandwidth to zero will cause cache servers to always be unavailable</mat-error>
+ </mat-form-field>
+ <!-- <small class="input-error" ng-show="hasPropertyError(serverForm[inf.name+'-max-bandwidth'], 'min')">Cannot be negative</small> -->
+ </div>
+
+ <fieldset>
+ <legend>IP Addresses<button name="addIPBtn" type="button" title="add new IP Address" class="add-button" (click)="addIP(inf)"><fa-icon [icon]="addIcon"></fa-icon></button></legend>
+ <div *ngFor="let ip of inf.ipAddresses; index as ipInd" [ngClass]="{'bordered-item': ipInd !== 0}">
+ <mat-checkbox [labelPosition]="'before'" name="{{inf.name}}-{{ip.address}}-serviceAddress" id="{{inf.name}}-{{ip.address}}-serviceAddress" class="service-addr-cb" [(ngModel)]="ip.serviceAddress">Is a Service Address</mat-checkbox>
+ <mat-form-field>
+ <mat-label>Address</mat-label>
+ <input matInput id="{{inf.name}}-{{ip.address}}" name="{{inf.name}}-{{ip.address}}" class="ip-input" [(ngModel)]="ip.address" [pattern]="validIPPattern" required placeholder="192.0.2.0/27" />
+ </mat-form-field>
+ <!-- <small class="input-error" ng-show="hasPropertyError(serverForm[inf.name+'-'+ip.address], 'pattern')">Invalid address</small>
+ <small class="input-error" ng-show="hasPropertyError(serverForm[inf.name+'-'+ip.address], 'required')">Required</small>
+ <small class="input-warning" ng-show="isLargeCIDR(ip.address)">Large CIDR detected. IPv4 with CIDR < 27 or IPv6 with CIDR < 64 can be problematic.</small> -->
+ <mat-form-field>
+ <mat-label>Gateway</mat-label>
+ <input matInput id="{{inf.name}}-{{ip.address}}-gateway" name="{{inf.name}}-{{ip.address}}-gateway" [(ngModel)]="ip.gateway" [pattern]="validGatewayPattern"/>
+ </mat-form-field>
+ <!-- <small class="input-error" ng-show="hasPropertyError(serverForm[inf.name+'-'+ip.address+'-gateway'], 'pattern')">Invalid gateway</small> -->
+ <button type="button" title="delete this IP address" class="remove-button" style="justify-self: start;" (click)="deleteIP(inf, ipInd)"><fa-icon [icon]="removeIcon"></fa-icon></button>
+ </div>
+ </fieldset>
+ </fieldset>
+ </fieldset>
<fieldset>
- <legend>IP Addresses<button name="addIPBtn" type="button" title="add new IP Address" class="add-button" (click)="addIP(inf)"><fa-icon [icon]="addIcon"></fa-icon></button></legend>
- <ul>
- <li *ngFor="let ip of inf.ipAddresses; index as ipInd" [ngClass]="{'bordered-item': ipInd !== 0}">
- <label for="{{inf.name}}-{{ip.address}}">Address</label>
- <input id="{{inf.name}}-{{ip.address}}" name="{{inf.name}}-{{ip.address}}" class="ip-input" type="text" [(ngModel)]="ip.address" [pattern]="validIPPattern" required placeholder="192.0.2.0/27" />
- <!-- <small class="input-error" ng-show="hasPropertyError(serverForm[inf.name+'-'+ip.address], 'pattern')">Invalid address</small>
- <small class="input-error" ng-show="hasPropertyError(serverForm[inf.name+'-'+ip.address], 'required')">Required</small>
- <small class="input-warning" ng-show="isLargeCIDR(ip.address)">Large CIDR detected. IPv4 with CIDR < 27 or IPv6 with CIDR < 64 can be problematic.</small> -->
- <label for="{{inf.name}}-{{ip.address}}-gateway">Gateway</label>
- <input type="text" id="{{inf.name}}-{{ip.address}}-gateway" name="{{inf.name}}-{{ip.address}}-gateway" [(ngModel)]="ip.gateway" [pattern]="validGatewayPattern"/>
- <!-- <small class="input-error" ng-show="hasPropertyError(serverForm[inf.name+'-'+ip.address+'-gateway'], 'pattern')">Invalid gateway</small> -->
- <label for="{{inf.name}}-{{ip.address}}-serviceAddress">Is a Service Address</label>
- <input type="checkbox" name="{{inf.name}}-{{ip.address}}-serviceAddress" id="{{inf.name}}-{{ip.address}}-serviceAddress" class="service-addr-cb" [(ngModel)]="ip.serviceAddress"/>
- <button type="button" title="delete this IP address" class="remove-button" style="justify-self: start;" (click)="deleteIP(inf, ipInd)"><fa-icon [icon]="removeIcon"></fa-icon></button>
- </li>
- </ul>
+ <legend (click)="hideILO=!hideILO"><abbr title="Integrated Lights-Out Management">ILO</abbr> Details</legend>
+ <div [hidden]="hideILO">
+ <mat-form-field>
+ <mat-label><abbr title="Integrated Lights-Out Management">ILO</abbr> IP Address</mat-label>
+ <input matInput name="iloIP" [(ngModel)]="server.iloIpAddress"/>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label><abbr title="Integrated Lights-Out Management">ILO</abbr> Gateway IP Address</mat-label>
+ <input matInput name="iloGateway" [(ngModel)]="server.iloIpGateway"/>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label><abbr title="Integrated Lights-Out Management">ILO</abbr> IP Netmask</mat-label>
+ <input matInput name="iloNetmask" [(ngModel)]="server.iloIpNetmask"/>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label><abbr title="Integrated Lights-Out Management">ILO</abbr> Username</mat-label>
+ <input matInput name="iloUsername" [(ngModel)]="server.iloUsername"/>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label><abbr title="Integrated Lights-Out Management">ILO</abbr> Password</mat-label>
+ <input matInput name="iloPassword" [(ngModel)]="server.iloPassword"/>
+ </mat-form-field>
+ </div>
</fieldset>
- </fieldset>
- </fieldset>
- <fieldset>
- <legend (click)="hideILO=!hideILO"><abbr title="Integrated Lights-Out Management">ILO</abbr> Details</legend>
- <div [hidden]="hideILO">
- <label for="iloIP"><abbr title="Integrated Lights-Out Management">ILO</abbr> IP Address</label>
- <input type="text" id="iloIP" name="iloIP" [(ngModel)]="server.iloIpAddress"/>
- <label for="iloGateway"><abbr title="Integrated Lights-Out Management">ILO</abbr> Gateway IP Address</label>
- <input type="text" id="iloGateway" name="iloGateway" [(ngModel)]="server.iloIpGateway"/>
- <label for="iloNetmask"><abbr title="Integrated Lights-Out Management">ILO</abbr> IP Netmask</label>
- <input type="text" id="iloNetmask" name="iloNetmask" [(ngModel)]="server.iloIpNetmask"/>
- <label for="iloUsername"><abbr title="Integrated Lights-Out Management">ILO</abbr> Username</label>
- <input type="text" id="iloUsername" name="iloUsername" [(ngModel)]="server.iloUsername"/>
- <label for="iloPassword"><abbr title="Integrated Lights-Out Management">ILO</abbr> Password</label>
- <input type="text" id="iloPassword" name="iloPassword" [(ngModel)]="server.iloPassword"/>
- </div>
- </fieldset>
- <fieldset>
- <legend (click)="hideManagement=!hideManagement">Management Interface Details</legend>
- <div [hidden]="hideManagement">
- <label for="mgmtIP">Management IP Address</label>
- <input type="text" id="mgmtIP" name="mgmtIP" [(ngModel)]="server.mgmtIpAddress"/>
- <label for="mgmtIpGateway">Management Gateway IP Address</label>
- <input type="text" id="mgmtIpGateway" name="mgmtIpGateway" [(ngModel)]="server.mgmtIpGateway"/>
- <label for="mgmtIpNetmask">Management IP Netmask</label>
- <input type="text" id="mgmtIpNetmask" name="mgmtIpNetmask" [(ngModel)]="server.mgmtIpNetmask"/>
- </div>
- </fieldset>
- <label *ngIf="!isNew" for="offlineReason">Offline Reason</label>
- <input *ngIf="!isNew" id="offlineReason" name="offlineReason" type="text" readonly [value]="server.offlineReason"/>
- <label for="rack">Rack</label>
- <input type="text" id="rack" name="rack" [(ngModel)]="server.rack"/>
- <label *ngIf="!isNew && server.statusLastUpdated" for="statusLastUpdated">Status Last Updated</label>
- <input *ngIf="!isNew && server.statusLastUpdated" type="text" id="statusLastUpdated" name="statusLastUpdated" readonly [value]="server.statusLastUpdated.toLocaleString()"/>
- <label *ngIf="!isNew" for="xmppId">Hash ID</label>
- <input readonly *ngIf="!isNew" id="xmppId" name="xmppId" [value]="server.xmppId"/>
- <div class="buttons">
- <button mat-raised-button>Submit</button>
- </div>
-</form>
+ <fieldset>
+ <legend (click)="hideManagement=!hideManagement">Management Interface Details</legend>
+ <div [hidden]="hideManagement">
+ <mat-form-field>
+ <mat-label>Management IP Address</mat-label>
+ <input matInput name="mgmtIP" [(ngModel)]="server.mgmtIpAddress"/>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Management Gateway IP Address</mat-label>
+ <input matInput name="mgmtIpGateway" [(ngModel)]="server.mgmtIpGateway"/>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Management IP Netmask</mat-label>
+ <input matInput name="mgmtIpNetmask" [(ngModel)]="server.mgmtIpNetmask"/>
+ </mat-form-field>
+ </div>
+ </fieldset>
+ <div class="buttons">
+ <button mat-raised-button>Submit</button>
+ </div>
+ </form>
+ </mat-card-content>
+</mat-card>
+<!--
<tp-update-status [servers]="[server]" (done)="doneUpdatingStatus($event)" *ngIf="changeStatusDialogOpen"></tp-update-status>
+-->
Review Comment:
This should be removed instead of just commented out
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] shamrickus commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
shamrickus commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r879446495
##########
experimental/traffic-portal/src/app/shared/tp-header/tp-header.component.scss:
##########
@@ -53,6 +57,10 @@ nav {
}
}
+a.mat-menu-item {
+ text-transform: uppercase;
Review Comment:
`mat-menu-item` and `mat-button` are mutually exclusive directives, at least on an ancor
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] ocket8888 commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
ocket8888 commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r878568880
##########
experimental/traffic-portal/src/app/core/currentuser/currentuser.component.html:
##########
@@ -11,67 +11,71 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<tp-header [title]="currentUser ? currentUser.username : ''"></tp-header>
+<mat-card>
+ <main *ngIf="currentUser && !editMode">
+ <h1><span *ngIf=currentUser.fullName>{{currentUser.fullName}}, </span>{{currentUser.roleName}} user</h1>
+ <address>
+ <p *ngIf="currentUser.email || currentUser.phoneNumber"><a *ngIf=currentUser.email href="mailto:{{currentUser.email}}">{{currentUser.email}}</a><span *ngIf="currentUser.email && currentUser.phoneNumber">, </span><a *ngIf="currentUser.phoneNumber" href="tel:{{currentUser.phoneNumber}}">{{currentUser.phoneNumber}}</a></p>
+ <p *ngIf=currentUser.addressLine1>{{currentUser.addressLine1}}</p>
+ <p *ngIf=currentUser.addressLine2>{{currentUser.addressLine2}}</p>
+ <p *ngIf=currentUser.company>{{currentUser.company}}</p>
+ <p *ngIf="currentUser.city || currentUser.country || currentUser.stateOrProvince || currentUser.postalCode"><span *ngIf="currentUser.city">{{currentUser.city}}<span *ngIf="currentUser.country || currentUser.stateOrProvince || currentUser.postalCode"> </span></span><span *ngIf="currentUser.stateOrProvince">{{currentUser.stateOrProvince}}<span *ngIf="currentUser.country || currentUser.postalCode">, </span></span><span *ngIf="currentUser.country">{{currentUser.country}}<span *ngIf="currentUser.postalCode">, </span></span><span *ngIf=currentUser.postalCode>{{currentUser.postalCode}}</span></p>
+ </address>
+ <div>
+ <h2>User Theme</h2>
+ <button mat-button (click)="themeSvc.loadTheme(theme)" *ngFor="let theme of themeSvc.themes">{{theme.name}}</button>
+ </div>
+ </main>
-<main *ngIf="currentUser && !editMode">
-<h1><span *ngIf=currentUser.fullName>{{currentUser.fullName}}, </span>{{currentUser.roleName}} user</h1>
-<address>
- <p *ngIf="currentUser.email || currentUser.phoneNumber"><a *ngIf=currentUser.email href="mailto:{{currentUser.email}}">{{currentUser.email}}</a><span *ngIf="currentUser.email && currentUser.phoneNumber">, </span><a *ngIf="currentUser.phoneNumber" href="tel:{{currentUser.phoneNumber}}">{{currentUser.phoneNumber}}</a></p>
- <p *ngIf=currentUser.addressLine1>{{currentUser.addressLine1}}</p>
- <p *ngIf=currentUser.addressLine2>{{currentUser.addressLine2}}</p>
- <p *ngIf=currentUser.company>{{currentUser.company}}</p>
- <p *ngIf="currentUser.city || currentUser.country || currentUser.stateOrProvince || currentUser.postalCode"><span *ngIf="currentUser.city">{{currentUser.city}}<span *ngIf="currentUser.country || currentUser.stateOrProvince || currentUser.postalCode"> </span></span><span *ngIf="currentUser.stateOrProvince">{{currentUser.stateOrProvince}}<span *ngIf="currentUser.country || currentUser.postalCode">, </span></span><span *ngIf="currentUser.country">{{currentUser.country}}<span *ngIf="currentUser.postalCode">, </span></span><span *ngIf=currentUser.postalCode>{{currentUser.postalCode}}</span></p>
-</address>
-</main>
-
-<form *ngIf="editMode && editUser" ngNativeValidate (submit)="submitEdit($event)">
- <mat-form-field style="grid-area: a-start;">
- <mat-label>Username</mat-label>
- <input matInput [(ngModel)]="editUser.username" name="username" type="text" required/>
- </mat-form-field>
- <mat-form-field style="grid-area: z;">
- <mat-label>Full Name</mat-label>
- <input matInput [(ngModel)]="editUser.fullName" name="fullName" type="text" required/>
- </mat-form-field>
- <mat-form-field style="grid-area: b;">
- <mat-label>Email</mat-label>
- <input matInput [(ngModel)]="editUser.email" name="email" type="email"/>
- </mat-form-field>
- <mat-form-field style="grid-area: c;">
- <mat-label>Telephone</mat-label>
- <input matInput [(ngModel)]="editUser.phoneNumber" name="phoneNumber" type="tel"/>
- </mat-form-field>
- <mat-form-field style="grid-area: d;">
- <mat-label>Address Line 1</mat-label>
- <input matInput [(ngModel)]="editUser.addressLine1" name="addressLine1" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: e;">
- <mat-label>Address Line 2</mat-label>
- <input matInput [(ngModel)]="editUser.addressLine2" name="addressLine2" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: f;">
- <mat-label>Company</mat-label>
- <input matInput [(ngModel)]="editUser.company" name="company" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: g;">
- <mat-label>City</mat-label>
- <input matInput [(ngModel)]="editUser.city" name="city" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: h;">
- <mat-label>State or Province</mat-label>
- <input matInput [(ngModel)]="editUser.stateOrProvince" name="stateOrProvince" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: i;">
- <mat-label>Country</mat-label>
- <input matInput [(ngModel)]="editUser.country" name="country" type="text"/>
- </mat-form-field>
- <mat-form-field style="grid-area: j;">
- <mat-label>Postal Code</mat-label>
- <input matInput [(ngModel)]="editUser.postalCode" name="postalCode" type="text"/>
- </mat-form-field>
- <button mat-raised-button style="grid-area: k;">Submit</button>
- <button mat-raised-button color="accent" style="grid-area: l;" type="button" (click)="updatePassword()">Update Password</button>
- <button type="button" mat-raised-button color="warn" (click)="cancelEdit()" style="grid-area: m;">Cancel</button>
-</form>
+ <form *ngIf="editMode && editUser" ngNativeValidate (submit)="submitEdit($event)">
+ <mat-form-field style="grid-area: a-start;">
+ <mat-label>Username</mat-label>
+ <input matInput [(ngModel)]="editUser.username" name="username" type="text" required/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: z;">
+ <mat-label>Full Name</mat-label>
+ <input matInput [(ngModel)]="editUser.fullName" name="fullName" type="text" required/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: b;">
+ <mat-label>Email</mat-label>
+ <input matInput [(ngModel)]="editUser.email" name="email" type="email"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: c;">
+ <mat-label>Telephone</mat-label>
+ <input matInput [(ngModel)]="editUser.phoneNumber" name="phoneNumber" type="tel"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: d;">
+ <mat-label>Address Line 1</mat-label>
+ <input matInput [(ngModel)]="editUser.addressLine1" name="addressLine1" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: e;">
+ <mat-label>Address Line 2</mat-label>
+ <input matInput [(ngModel)]="editUser.addressLine2" name="addressLine2" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: f;">
+ <mat-label>Company</mat-label>
+ <input matInput [(ngModel)]="editUser.company" name="company" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: g;">
+ <mat-label>City</mat-label>
+ <input matInput [(ngModel)]="editUser.city" name="city" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: h;">
+ <mat-label>State or Province</mat-label>
+ <input matInput [(ngModel)]="editUser.stateOrProvince" name="stateOrProvince" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: i;">
+ <mat-label>Country</mat-label>
+ <input matInput [(ngModel)]="editUser.country" name="country" type="text"/>
+ </mat-form-field>
+ <mat-form-field style="grid-area: j;">
+ <mat-label>Postal Code</mat-label>
+ <input matInput [(ngModel)]="editUser.postalCode" name="postalCode" type="text"/>
+ </mat-form-field>
+ <button mat-raised-button style="grid-area: k;">Submit</button>
+ <button mat-raised-button color="accent" style="grid-area: l;" type="button" (click)="updatePassword()">Update Password</button>
+ <button type="button" mat-raised-button color="warn" (click)="cancelEdit()" style="grid-area: m;">Cancel</button>
Review Comment:
I don't think it would be hard, but this is your crusade so I'll defer to you.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] ocket8888 commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
ocket8888 commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r879814365
##########
experimental/traffic-portal/src/app/shared/tp-header/tp-header.component.scss:
##########
@@ -53,6 +57,10 @@ nav {
}
}
+a.mat-menu-item {
+ text-transform: uppercase;
Review Comment:
Ah, `mat-button` wouldn't do it for you anyway:
> According to the Material design spec button text has to be capitalized, however we have opted not to capitalize buttons automatically via `text-transform: uppercase`, because it can cause issues in certain locales. It is also worth noting that using ALL CAPS in the text itself causes issues for screen-readers, which will read the text character-by-character. We leave the decision of how to approach this to the consuming app.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [trafficcontrol] ocket8888 commented on a diff in pull request #6753: Add Theming to TPv2
Posted by GitBox <gi...@apache.org>.
ocket8888 commented on code in PR #6753:
URL: https://github.com/apache/trafficcontrol/pull/6753#discussion_r870675093
##########
experimental/traffic-portal/src/app/core/users/users.component.html:
##########
@@ -11,9 +11,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<tp-header [title]="'Users'"></tp-header>
<main>
- <main>
+ <mat-card>
Review Comment:
This is why the e2e tests are failing; the selector for the page object is looking for `main > main` but you've changed that to `main > mat-card`. Which can probably just be `mat-card` since that's the only one on the page (whereas `main` wouldn't have worked because there were two of them).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@trafficcontrol.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org