Skip to content

Commit 0d021ed

Browse files
nwmacrichard-cox
andauthored
Improve recent and favourites display (#4421)
* Improve recent and favourites display * Remove debug logging * Remove debug logging/subscription leak * Unit test fix * Tweaks following review * Changes following review - favourite & recent icon changes Co-authored-by: Richard Cox <[email protected]>
1 parent e457a61 commit 0d021ed

17 files changed

+170
-315
lines changed

src/frontend/packages/cloud-foundry/src/cf-entity-generator.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -1143,10 +1143,11 @@ function generateCfApplicationEntity(endpointDefinition: StratosEndpointExtensio
11431143
label: 'Application',
11441144
labelPlural: 'Applications',
11451145
endpoint: endpointDefinition,
1146+
icon: 'apps',
11461147
tableConfig: {
11471148
rowBuilders: [
11481149
['Name', (entity) => entity.entity.name],
1149-
['Creation Date', (entity) => entity.metadata.created_at]
1150+
['Created', (entity) => entity.metadata.created_at]
11501151
]
11511152
}
11521153
};
@@ -1172,7 +1173,7 @@ function generateCfApplicationEntity(endpointDefinition: StratosEndpointExtensio
11721173
getLink: metadata => `/applications/${metadata.cfGuid}/${metadata.guid}/summary`,
11731174
getGuid: metadata => metadata.guid,
11741175
getLines: () => ([
1175-
['Creation Date', (meta) => meta.createdAt]
1176+
['Created', (meta) => meta.createdAt]
11761177
])
11771178
},
11781179
actionBuilders: applicationActionBuilder
@@ -1191,6 +1192,8 @@ function generateCfSpaceEntity(endpointDefinition: StratosEndpointExtensionDefin
11911192
label: 'Space',
11921193
labelPlural: 'Spaces',
11931194
endpoint: endpointDefinition,
1195+
icon: 'virtual_space',
1196+
iconFont: 'stratos-icons'
11941197
};
11951198
cfEntityCatalog.space = new StratosCatalogEntity<ISpaceFavMetadata, APIResource<ISpace>, SpaceActionBuilders>(
11961199
spaceDefinition,
@@ -1210,7 +1213,7 @@ function generateCfSpaceEntity(endpointDefinition: StratosEndpointExtensionDefin
12101213
createdAt: moment(space.metadata.created_at).format('LLL'),
12111214
}),
12121215
getLines: () => ([
1213-
['Creation Date', (meta) => meta.createdAt]
1216+
['Created', (meta) => meta.createdAt]
12141217
]),
12151218
getLink: metadata => `/cloud-foundry/${metadata.cfGuid}/organizations/${metadata.orgGuid}/spaces/${metadata.guid}/summary`,
12161219
getGuid: metadata => metadata.guid
@@ -1227,6 +1230,8 @@ function generateCfOrgEntity(endpointDefinition: StratosEndpointExtensionDefinit
12271230
label: 'Organization',
12281231
labelPlural: 'Organizations',
12291232
endpoint: endpointDefinition,
1233+
icon: 'organization',
1234+
iconFont: 'stratos-icons'
12301235
};
12311236
cfEntityCatalog.org = new StratosCatalogEntity<
12321237
IOrgFavMetadata,
@@ -1252,7 +1257,7 @@ function generateCfOrgEntity(endpointDefinition: StratosEndpointExtensionDefinit
12521257
}),
12531258
getLink: metadata => `/cloud-foundry/${metadata.cfGuid}/organizations/${metadata.guid}`,
12541259
getLines: () => ([
1255-
['Creation Date', (meta) => meta.createdAt]
1260+
['Created', (meta) => meta.createdAt]
12561261
]),
12571262
getGuid: metadata => metadata.guid
12581263
}

src/frontend/packages/core/src/app.module.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -231,18 +231,20 @@ export class AppModule {
231231
}
232232
);
233233

234+
// This updates the names of any recents
234235
debouncedApiRequestData$.pipe(
235236
withLatestFrom(recents$)
236237
).subscribe(
237238
([entities, recents]) => {
238-
Object.values(recents.entities).forEach(recentEntity => {
239+
Object.values(recents).forEach(recentEntity => {
239240
const mapper = this.favoritesConfigMapper.getMapperFunction(recentEntity);
240241
const entityKey = entityCatalog.getEntityKey(recentEntity);
241242
if (entities[entityKey] && entities[entityKey][recentEntity.entityId]) {
242243
const entity = entities[entityKey][recentEntity.entityId];
243244
const entityToMetadata = this.favoritesConfigMapper.getEntityMetadata(recentEntity, entity);
244245
const name = mapper(entityToMetadata).name;
245246
if (name && name !== recentEntity.name) {
247+
// Update the entity name
246248
this.store.dispatch(new SetRecentlyVisitedEntityAction({
247249
...recentEntity,
248250
name

src/frontend/packages/core/src/features/home/home/home-page.component.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ $page-padding: 20px;
1515
flex: 1;
1616
flex-direction: column;
1717
margin: 0 -#{$page-padding} -#{$page-padding};
18-
padding: 24px;
18+
padding: 20px;
1919
@include breakpoint(tablet) {
2020
margin: -#{$page-padding} -#{$page-padding} -#{$page-padding} $page-padding;
2121
}

src/frontend/packages/core/src/shared/components/favorites-meta-card/favorites-meta-card.component.html

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
[entityConfig]="entityConfig">
44
<app-meta-card-title class="fav-meta-card__header">
55
<div class="fav-meta-card__header">
6-
<div *ngIf="!compact" class="fav-meta-card__icon-panel">
7-
<img class="fav-meta-card__icon" *ngIf="iconUrl$ | async as imageUrl" [src]="imageUrl" />
6+
<div *ngIf="!compact" class="fav-meta-card__logo-panel">
7+
<img class="fav-meta-card__logo" *ngIf="icon.logoUrl" [src]="icon.logoUrl" />
8+
</div>
9+
<div *ngIf="compact" class="fav-meta-card__icon-panel">
10+
<mat-icon class="fav-meta-card__icon" *ngIf="icon.icon && !icon.logoUrl" [fontSet]="icon.iconFont">{{ icon.icon }}</mat-icon>
811
</div>
912
<div class="fav-meta-card__header-text-panel">
1013
<h2 class="fav-meta-card__header-text" *ngIf="!compact">

src/frontend/packages/core/src/shared/components/favorites-meta-card/favorites-meta-card.component.scss

+12-4
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,26 @@
3535
}
3636
&__header {
3737
display: flex;
38-
white-space: nowrap;
3938
}
40-
&__icon-panel {
39+
&__logo-panel {
4140
display: flex;
42-
justify-content: center;
41+
justify-content: left;
4342
width: 56px;
4443
}
45-
&__icon {
44+
&__logo {
4645
height: 48px;
4746
margin-right: 8px;
4847
width: auto;
4948
}
49+
&__icon {
50+
margin-right: 4px;
51+
opacity: .7;
52+
}
53+
&__icon-panel {
54+
display: flex;
55+
justify-content: left;
56+
width: 32px;
57+
}
5058
&__panel {
5159
display: flex;
5260
:first-child {

src/frontend/packages/core/src/shared/components/favorites-meta-card/favorites-meta-card.component.ts

+17
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ import { isEndpointConnected } from '../../../features/endpoints/connect.service
1414
import { ConfirmationDialogConfig } from '../confirmation-dialog.config';
1515
import { ConfirmationDialogService } from '../confirmation-dialog.service';
1616

17+
interface FavoriteIconData {
18+
hasIcon: boolean;
19+
icon?: string;
20+
iconFont?: string;
21+
logoUrl?: string;
22+
}
1723

1824
@Component({
1925
selector: 'app-favorites-meta-card',
@@ -64,6 +70,9 @@ export class FavoritesMetaCardComponent {
6470
// Optional icon for the favorite
6571
public iconUrl$: Observable<string>;
6672

73+
// Optional icon for the favorite
74+
public icon: FavoriteIconData;
75+
6776
@Input()
6877
set favoriteEntity(favoriteEntity: IFavoriteEntity) {
6978
if (!this.placeholder && favoriteEntity) {
@@ -88,6 +97,14 @@ export class FavoritesMetaCardComponent {
8897
this.iconUrl$ = observableOf('');
8998
}
9099

100+
const entityDef = entityCatalog.getEntity(this.favorite.endpointType, this.favorite.entityType);
101+
this.icon = {
102+
hasIcon: !!entityDef.definition.logoUrl || !!entityDef.definition.icon,
103+
icon: entityDef.definition.icon,
104+
iconFont: entityDef.definition.iconFont,
105+
logoUrl: entityDef.definition.logoUrl,
106+
};
107+
91108
this.setConfirmation(this.prettyName, favorite);
92109

93110
const config = cardMapper && favorite && favorite.metadata ? cardMapper(favorite.metadata) : null;

src/frontend/packages/core/src/shared/components/page-header/page-header.component.theme.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
background-color: mat-color($foreground, divider);
4141
}
4242
&__history {
43-
color: $subdued;
43+
color: mat-color($foreground, text);
4444
}
4545
&__underflow {
4646
background-color: $underflow-background;

src/frontend/packages/core/src/shared/components/page-header/page-header.component.ts

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { TemplatePortal } from '@angular/cdk/portal';
22
import { AfterViewInit, Component, Input, OnDestroy, TemplateRef, ViewChild } from '@angular/core';
33
import { ActivatedRoute, Router } from '@angular/router';
44
import { Store } from '@ngrx/store';
5+
import * as moment from 'moment';
56
import { Observable } from 'rxjs';
67
import { map, startWith } from 'rxjs/operators';
78

@@ -96,6 +97,7 @@ export class PageHeaderComponent implements OnDestroy, AfterViewInit {
9697
const { name, routerLink } = mapperFunction(favorite.metadata);
9798
this.store.dispatch(new AddRecentlyVisitedEntityAction({
9899
guid: favorite.guid,
100+
date: moment().valueOf(),
99101
entityType: favorite.entityType,
100102
endpointType: favorite.endpointType,
101103
entityId: favorite.entityId,

src/frontend/packages/core/src/shared/components/recent-entities/recent-entities.component.html

+19-32
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,7 @@
1+
<!-- history is set when used in the dropdown menu to only show recent history-->
2+
13
<mat-card *ngIf="!history && ((hasHits$ | async) === true)">
2-
<mat-tab-group dynamicHeight="true" animationDuration="0ms"
3-
mat-stretch-tabs>
4-
<mat-tab label="Top">
5-
<div class="recent-tab" *ngIf="frecentEntities$ | async as frecentEntities">
6-
<div *ngIf="frecentEntities && frecentEntities.length > 0" class="recent-entities">
7-
<div [routerLink]="countedEntity.entity.routerLink" [ngClass]="{clickable: !!countedEntity.entity.routerLink}"
8-
class="recent-entity" *ngFor="let countedEntity of frecentEntities">
9-
<a class="recent-entity--name" *ngIf="countedEntity.entity.routerLink as routerLink; else noLink">{{
10-
countedEntity.entity.name }}</a>
11-
<ng-template #noLink>
12-
<div class="recent-entity--name">{{ countedEntity.entity.name }}</div>
13-
</ng-template>
14-
<div class="type-info">
15-
<span>{{ countedEntity.subText$ | async }}</span>
16-
</div>
17-
</div>
18-
</div>
19-
</div>
20-
</mat-tab>
21-
<mat-tab label="Recent">
22-
<ng-container *ngTemplateOutlet="historyTemplate"></ng-container>
23-
</mat-tab>
24-
</mat-tab-group>
4+
<ng-container *ngTemplateOutlet="historyTemplate"></ng-container>
255
</mat-card>
266

277
<ng-container *ngIf="!history && ((hasHits$ | async) === false)">
@@ -39,16 +19,23 @@
3919
<div *ngIf="recentEntities && recentEntities.length > 0" class="recent-entities">
4020
<div [routerLink]="countedEntity.entity.routerLink" [ngClass]="{clickable: !!countedEntity.entity.routerLink}"
4121
class="recent-entity" *ngFor="let countedEntity of recentEntities">
42-
<a class="recent-entity--name" *ngIf="countedEntity.entity.routerLink as routerLink; else noLink">{{
43-
countedEntity.entity.name }}</a>
44-
<ng-template #noLink>
45-
<div class="recent-entity--name">{{ countedEntity.entity.name }}</div>
46-
</ng-template>
47-
<div class="type-info" *ngIf="countedEntity.mostRecentHit">
48-
{{ countedEntity.mostRecentHit | amTimeAgo }}
22+
<div class="recent-entity__icon-container" *ngIf="countedEntity.icon">
23+
<mat-icon class="recent-entity__icon" [fontSet]="countedEntity.iconFont">{{ countedEntity.icon }}</mat-icon>
4924
</div>
50-
<div class="type-info">
51-
<span>{{ countedEntity.subText$ | async }}</span>
25+
<div>
26+
<a class="recent-entity--name" *ngIf="countedEntity.entity.routerLink as routerLink; else noLink">{{
27+
countedEntity.entity.name }}</a>
28+
<ng-template #noLink>
29+
<div class="recent-entity--name">{{ countedEntity.entity.name }}</div>
30+
</ng-template>
31+
<!-- Don't show the date
32+
<div class="type-info" *ngIf="countedEntity.mostRecentHit">
33+
{{ countedEntity.mostRecentHit | amTimeAgo }}
34+
</div>
35+
-->
36+
<div class="type-info">
37+
<span>{{ countedEntity.subText$ | async }}</span>
38+
</div>
5239
</div>
5340
</div>
5441
</div>

src/frontend/packages/core/src/shared/components/recent-entities/recent-entities.component.scss

+10-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ $spacing: 10px;
55
opacity: .6;
66
}
77
.recent-entity {
8+
display: flex;
89
outline: 0;
910
padding: $spacing;
1011
& + & {
@@ -21,14 +22,22 @@ $spacing: 10px;
2122
&--name {
2223
word-break: break-all;
2324
}
25+
&__icon {
26+
opacity: .7;
27+
}
28+
&__icon-container {
29+
display: flex;
30+
height: 24px;
31+
text-align: center;
32+
width: 32px;
33+
}
2434
}
2535

2636
.clickable {
2737
cursor: pointer;
2838
}
2939

3040
.recent-tab {
31-
padding-top: $spacing;
3241
&.standalone {
3342
padding-top: 0;
3443
}

0 commit comments

Comments
 (0)