[NIFI-13177] ensure consistent typography rendering (#8786)

* [NIFI-13177] ensure consistent rendering of component type, name, and icon

* ensure font-size consistency with .refresh-container and .mat-mdc-paginator

* attempt at unifying how component context is displayed (#6)

* use drop icon by default

* final touches

---------

Co-authored-by: Rob Fellows <rob.fellows@gmail.com>

This closes #8786
This commit is contained in:
Scott Aslan 2024-05-10 11:58:52 -04:00 committed by GitHub
parent c09144051f
commit 6b48e61295
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 94 additions and 147 deletions

View File

@ -56,23 +56,11 @@
<div class="flex justify-between items-center">
<form [formGroup]="policyForm">
<div class="flex gap-x-2">
<div class="flex gap-x-1 -mt-2">
<div class="operation-context-logo flex flex-col">
<i class="accent-color icon" [class]="getContextIcon()"></i>
</div>
<div class="flex flex-col">
<div class="operation-context-name">
{{
policyComponentState.label
? policyComponentState.label
: resourceIdentifier
}}
</div>
<div class="operation-context-type primary-color">
{{ getContextType() }}
</div>
</div>
</div>
<component-context
[type]="getContextType()"
[name]="
policyComponentState.label ? policyComponentState.label : resourceIdentifier
"></component-context>
<div class="policy-select">
<mat-form-field>
<mat-label>Policy</mat-label>

View File

@ -25,18 +25,4 @@
width: 300px;
}
}
.operation-context-logo {
.icon {
font-size: 36px;
}
}
.operation-context-name {
font-size: 18px;
width: 370px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}

View File

@ -337,27 +337,27 @@ export class ComponentAccessPolicies implements OnInit, OnDestroy {
return 'icon-group';
}
getContextType(): string {
getContextType(): ComponentType | string | null {
switch (this.resource) {
case 'processors':
return 'Processor';
return ComponentType.Processor;
case 'input-ports':
return 'Input Ports';
return ComponentType.InputPort;
case 'output-ports':
return 'Output Ports';
return ComponentType.OutputPort;
case 'funnels':
return 'Funnel';
return ComponentType.Funnel;
case 'labels':
return 'Label';
return ComponentType.Label;
case 'remote-process-groups':
return 'Remote Process Group';
return ComponentType.RemoteProcessGroup;
case 'parameter-contexts':
return 'Parameter Contexts';
return 'Parameter Context';
case 'parameter-providers':
return 'Parameter Provider';
return ComponentType.ParameterProvider;
}
return 'Process Group';
return ComponentType.ProcessGroup;
}
policyActionChanged(value: string): void {

View File

@ -29,6 +29,7 @@ import { NifiTooltipDirective } from '../../../../ui/common/tooltips/nifi-toolti
import { PolicyTable } from '../common/policy-table/policy-table.component';
import { MatButtonModule } from '@angular/material/button';
import { ErrorBanner } from '../../../../ui/common/error-banner/error-banner.component';
import { ComponentContext } from '../../../../ui/common/component-context/component-context.component';
@NgModule({
declarations: [ComponentAccessPolicies],
@ -45,7 +46,8 @@ import { ErrorBanner } from '../../../../ui/common/error-banner/error-banner.com
NifiTooltipDirective,
PolicyTable,
MatButtonModule,
ErrorBanner
ErrorBanner,
ComponentContext
]
})
export class ComponentAccessPoliciesModule {}

View File

@ -33,20 +33,10 @@
@if (!operationCollapsed) {
@if (canvasUtils.getSelection(); as selection) {
<div class="w-72 px-2.5 pb-2.5 flex flex-col gap-y-2">
<div class="operation-context flex flex-col gap-y-1">
<div class="flex gap-x-1">
<div class="operation-context-logo flex flex-col">
<i class="icon accent-color" [class]="getContextIcon(selection)"></i>
</div>
<div class="flex flex-col">
<div class="operation-context-name">{{ getContextName(selection) }}</div>
<div class="operation-context-type primary-color">
{{ getContextType(selection) }}
</div>
</div>
</div>
<div class="operation-context-id accent-color">{{ getContextId(selection) }}</div>
</div>
<component-context
[type]="getContextType(selection)"
[name]="getContextName(selection)"
[id]="getContextId(selection)"></component-context>
<div class="flex flex-col gap-y-1">
<div class="flex gap-x-1">
<button

View File

@ -36,32 +36,4 @@ div.operation-control {
font-size: 12px;
letter-spacing: 0.05rem;
}
.operation-context-logo {
text-align: start;
height: 40px;
line-height: 40px;
.icon {
font-size: 32px;
}
}
.operation-context-name {
font-size: 15px;
height: 20px;
width: 225px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.operation-context-type {
font-size: 12px;
}
.operation-context-id {
height: 18px;
font-size: 12px;
}
}

View File

@ -29,12 +29,14 @@ import * as d3 from 'd3';
import { CanvasView } from '../../../../service/canvas-view.service';
import { Client } from '../../../../../../service/client.service';
import { CanvasActionsService } from '../../../../service/canvas-actions.service';
import { ComponentContext } from '../../../../../../ui/common/component-context/component-context.component';
import { ComponentType } from '../../../../../../state/shared';
@Component({
selector: 'operation-control',
standalone: true,
templateUrl: './operation-control.component.html',
imports: [MatButtonModule],
imports: [MatButtonModule, ComponentContext],
styleUrls: ['./operation-control.component.scss']
})
export class OperationControl {
@ -136,29 +138,29 @@ export class OperationControl {
}
}
getContextType(selection: d3.Selection<any, any, any, any>): string {
getContextType(selection: d3.Selection<any, any, any, any>): ComponentType | null {
if (selection.size() === 0) {
return 'Process Group';
return ComponentType.ProcessGroup;
} else if (selection.size() > 1) {
return '';
return null;
}
if (this.canvasUtils.isProcessor(selection)) {
return 'Processor';
return ComponentType.Processor;
} else if (this.canvasUtils.isInputPort(selection)) {
return 'Input Port';
return ComponentType.InputPort;
} else if (this.canvasUtils.isOutputPort(selection)) {
return 'Output Port';
return ComponentType.OutputPort;
} else if (this.canvasUtils.isFunnel(selection)) {
return 'Funnel';
return ComponentType.Funnel;
} else if (this.canvasUtils.isLabel(selection)) {
return 'Label';
return ComponentType.Label;
} else if (this.canvasUtils.isProcessGroup(selection)) {
return 'Process Group';
return ComponentType.ProcessGroup;
} else if (this.canvasUtils.isRemoteProcessGroup(selection)) {
return 'Remote Process Group';
return ComponentType.RemoteProcessGroup;
} else {
return 'Connection';
return ComponentType.Connection;
}
}

View File

@ -14,7 +14,3 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.refresh-container {
line-height: normal;
}

View File

@ -17,10 +17,6 @@
@use '@angular/material' as mat;
.refresh-container {
line-height: normal;
}
.manage-remote-ports-table {
.listing-table {
@include mat.table-density(-4);

View File

@ -14,7 +14,3 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.refresh-container {
line-height: normal;
}

View File

@ -23,7 +23,7 @@ import { ComponentType } from '../state/shared';
standalone: true
})
export class ComponentTypeNamePipe implements PipeTransform {
transform(type: ComponentType): string {
transform(type: ComponentType | string): string {
switch (type) {
case ComponentType.Connection:
return 'Connection';
@ -54,7 +54,7 @@ export class ComponentTypeNamePipe implements PipeTransform {
case ComponentType.ReportingTask:
return 'Reporting Task';
default:
return '';
return type;
}
}
}

View File

@ -17,17 +17,19 @@
<div class="component-context flex flex-col">
<div class="flex gap-x-1 items-center">
<div class="component-context-logo flex flex-col">
<div class="context-logo flex flex-col">
<i class="icon accent-color" [class]="componentIconClass"></i>
</div>
<div class="flex flex-col flex-1">
<div class="component-context-name w-full">{{ name }}</div>
<div class="component-context-type primary-color w-full">
{{ type | componentTypeName }}
<div class="context-name w-full">{{ name }}</div>
<div class="context-type pt-1 primary-color w-full">
@if (type) {
{{ type | componentTypeName }}
}
</div>
</div>
</div>
@if (id) {
<div class="component-context-id accent-color">{{ id }}</div>
<div class="context-id accent-color">{{ id }}</div>
}
</div>

View File

@ -14,28 +14,3 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.component-context {
.component-context-logo {
text-align: start;
.icon {
font-size: 32px;
}
}
.component-context-name {
font-size: 15px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.component-context-type {
font-size: 12px;
line-height: 16px;
}
.component-context-id {
font-size: 12px;
}
}

View File

@ -27,22 +27,25 @@ import { ComponentTypeNamePipe } from '../../../pipes/component-type-name.pipe';
styleUrl: './component-context.component.scss'
})
export class ComponentContext {
private _componentType: ComponentType = ComponentType.Processor;
private _componentType: ComponentType | string | null = ComponentType.Processor;
componentIconClass: string = '';
@Input() set type(type: ComponentType) {
@Input() set type(type: ComponentType | string | null) {
this._componentType = type;
this.componentIconClass = this.getIconClassName(type);
}
get type(): ComponentType {
get type(): ComponentType | string | null {
return this._componentType;
}
@Input() id: string | null = null;
@Input() name: string = '';
private getIconClassName(type: ComponentType) {
private getIconClassName(type: ComponentType | string | null) {
if (type === null) {
return 'icon-drop';
}
switch (type) {
case ComponentType.Connection:
return 'icon-connect';
@ -61,7 +64,7 @@ export class ComponentContext {
case ComponentType.RemoteProcessGroup:
return 'icon-group-remote';
default:
return 'icon-connect';
return 'icon-drop';
}
}
}

View File

@ -35,7 +35,9 @@
<th mat-header-cell *matHeaderCellDef>Property</th>
<td mat-cell *matCellDef="let item" [class.font-bold]="item.descriptor.required">
<div class="flex justify-between items-center">
<div class="whitespace-nowrap overflow-hidden text-ellipsis leading-normal" [title]="item.descriptor.displayName">
<div
class="whitespace-nowrap overflow-hidden text-ellipsis leading-normal"
[title]="item.descriptor.displayName">
{{ item.descriptor.displayName }}
</div>
<i
@ -81,7 +83,9 @@
</ng-template>
<ng-template #nonBlank let-resolvedValue>
<div class="flex justify-between items-center">
<div class="whitespace-nowrap overflow-hidden text-ellipsis leading-normal" [title]="resolvedValue">
<div
class="whitespace-nowrap overflow-hidden text-ellipsis leading-normal"
[title]="resolvedValue">
{{ resolvedValue }}
</div>
@if (hasExtraWhitespace(resolvedValue)) {

View File

@ -65,6 +65,41 @@
opacity: 0.8;
}
.context-logo {
text-align: start;
height: 40px;
line-height: 40px;
.icon {
font-size: 32px;
}
}
.context-name {
font-size: 15px;
line-height: 15px;
height: 15px;
width: 225px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.context-type {
font-size: 12px;
line-height: 12px;
}
.context-id {
font-size: 12px;
line-height: 12px;
}
.refresh-container {
line-height: normal;
font-size: 12px;
}
.hidden {
display: none;
}