Skip to content

Commit

Permalink
Create defaults list component
Browse files Browse the repository at this point in the history
- Intermediate component between simple list and full list
- Supply as little config as simple list, all of full list or anywhere in between
  • Loading branch information
richard-cox committed Oct 15, 2019
1 parent fb3db1e commit 247f2de
Show file tree
Hide file tree
Showing 17 changed files with 510 additions and 86 deletions.
15 changes: 10 additions & 5 deletions src/frontend/packages/cloud-foundry/src/cf-entity-generator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as moment from 'moment';

import {
IService,
IServiceBinding,
Expand Down Expand Up @@ -886,9 +887,6 @@ function generateCfApplicationEntity(endpointDefinition: StratosEndpointExtensio
}),
getLink: metadata => `/applications/${metadata.cfGuid}/${metadata.guid}/summary`,
getGuid: metadata => metadata.guid,
getLines: () => ([
['Creation Date', (meta) => meta.createdAt]
])
},
actionBuilders: applicationActionBuilder
},
Expand Down Expand Up @@ -921,9 +919,10 @@ function generateCfSpaceEntity(endpointDefinition: StratosEndpointExtensionDefin
orgGuid: space.entity.organization_guid ? space.entity.organization_guid : space.entity.organization.metadata.guid,
name: space.entity.name,
cfGuid: space.entity.cfGuid,
createdAt: moment(space.metadata.created_at).format('LLL'),
}),
getLink: metadata => `/cloud-foundry/${metadata.cfGuid}/organizations/${metadata.orgGuid}/spaces/${metadata.guid}/summary`,
getGuid: metadata => metadata.guid
getGuid: metadata => metadata.guid,
}
}
);
Expand Down Expand Up @@ -953,9 +952,14 @@ function generateCfOrgEntity(endpointDefinition: StratosEndpointExtensionDefinit
status: getOrgStatus(org),
name: org.entity.name,
cfGuid: org.entity.cfGuid,
createdAt: moment(org.metadata.created_at).format('LLL'),
}),
getLink: metadata => `/cloud-foundry/${metadata.cfGuid}/organizations/${metadata.guid}`,
getGuid: metadata => metadata.guid
getGuid: metadata => metadata.guid,
getLines: () => ([
['Name', (meta) => meta.name], // TODO: RC Nuke
['Creation Date', (meta) => meta.createdAt] // TODO: RC Nuke
])
}
}
);
Expand Down Expand Up @@ -985,3 +989,4 @@ function generateCFMetrics(endpointDefinition: StratosEndpointExtensionDefinitio
}
);
}

Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,10 @@
</span>
</button>
</app-page-sub-nav>
<app-list></app-list>
<app-defaults-list [actionOrConfig]="listActionConfig" [listConfig]="listConfig"
[dataSourceConfig]="dataSourceConfig"></app-defaults-list>
<!-- // TODO: RC Nuke all below -->
-------------
<app-simple-list [catalogueEntity]="catalogueEntity"></app-simple-list>
<!-- <app-list></app-list> -->
</div>
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
import { Component } from '@angular/core';
import { Observable } from 'rxjs';

import { IOrganization } from '../../../../../../core/src/core/cf-api.types';
import { CurrentUserPermissions } from '../../../../../../core/src/core/current-user-permissions.config';
import { CurrentUserPermissionsService } from '../../../../../../core/src/core/current-user-permissions.service';
import { ListConfig } from '../../../../../../core/src/shared/components/list/list.component.types';
import { entityCatalogue } from '../../../../../../core/src/core/entity-catalogue/entity-catalogue.service';
import {
IListDataSourceConfig,
} from '../../../../../../core/src/shared/components/list/data-sources-controllers/list-data-source-config';
import {
ListDefaultsActionOrConfig,
} from '../../../../../../core/src/shared/components/list/defaults-list/defaults-datasource';
import { IListConfig, ListViewTypes } from '../../../../../../core/src/shared/components/list/list.component.types';
import { ListView } from '../../../../../../store/src/actions/list.actions';
import { APIResource } from '../../../../../../store/src/types/api.types';
import { PaginationEntityState } from '../../../../../../store/src/types/pagination.types';
import { CF_ENDPOINT_TYPE } from '../../../../../cf-types';
import {
domainEntityType,
organizationEntityType,
privateDomainsEntityType,
quotaDefinitionEntityType,
routeEntityType,
spaceEntityType,
} from '../../../../cf-entity-types';
import { createEntityRelationKey } from '../../../../entity-relations/entity-relations.types';
import { CfOrgCardComponent } from '../../../../shared/components/list/list-types/cf-orgs/cf-org-card/cf-org-card.component';
import { CfOrgsListConfigService } from '../../../../shared/components/list/list-types/cf-orgs/cf-orgs-list-config.service';
import { CloudFoundryEndpointService } from '../../services/cloud-foundry-endpoint.service';
Expand All @@ -13,19 +34,153 @@ import { CloudFoundryEndpointService } from '../../services/cloud-foundry-endpoi
templateUrl: './cloud-foundry-organizations.component.html',
styleUrls: ['./cloud-foundry-organizations.component.scss'],
providers: [
{
provide: ListConfig,
useClass: CfOrgsListConfigService
}
CfOrgsListConfigService // TODO: RC only needed for demoing old way
]
})
export class CloudFoundryOrganizationsComponent {
public canAddOrg$: Observable<boolean>;
public listActionConfig: ListDefaultsActionOrConfig;
public listConfig: Partial<IListConfig<any>>;
public dataSourceConfig: Partial<IListDataSourceConfig<any, any>>;


// TODO: RC Nuke all below to ctor (keep setup minimal contents)
// TODO: RC Nuke CfOrgsListConfigService && CfOrgsDataSourceService
private entityConfig = {
entityType: organizationEntityType,
endpointType: CF_ENDPOINT_TYPE
};
public catalogueEntity = entityCatalogue.getEntity(this.entityConfig);

private setupWithAction() {
const endpointGuid = this.cfEndpointService.cfGuid;
const action = CloudFoundryEndpointService.createGetAllOrganizations(endpointGuid);
this.listActionConfig = action;
}

private setupWithEntityConfig() {
const endpointGuid = this.cfEndpointService.cfGuid;
const action = CloudFoundryEndpointService.createGetAllOrganizations(endpointGuid);
// this.listActionConfig = {
const a = {
entityConfig: this.entityConfig,
endpointGuid,
paginationKey: action.paginationKey,
extraArgs: {
includeRelations: [
createEntityRelationKey(organizationEntityType, spaceEntityType),
createEntityRelationKey(organizationEntityType, domainEntityType),
createEntityRelationKey(organizationEntityType, quotaDefinitionEntityType),
createEntityRelationKey(organizationEntityType, privateDomainsEntityType),
createEntityRelationKey(spaceEntityType, routeEntityType), // Not really needed at top level, but if we drop down into an org with
// lots of spaces it saves spaces x routes requests
], populateMissing: false
}
};
this.listActionConfig = action;
}

private setupWithListOverrides() {
this.listConfig = {
cardComponent: CfOrgCardComponent,
viewType: ListViewTypes.BOTH,
defaultView: 'cards' as ListView,
getColumns: () => [{
columnId: 'name',
headerCell: () => 'Name',
cellDefinition: {
valuePath: 'entity.name',
// getLink: (row: APIResource<IOrganization>) => `${row.metadata.guid}`
getLink: (row: APIResource<IOrganization>) => `/cloud-foundry/${this.cfEndpointService.cfGuid}/organizations/${row.metadata.guid}`
},
sort: {
type: 'sort',
orderKey: 'name',
field: 'entity.name'
}
}, {
columnId: 'createdAt',
headerCell: () => 'Creation',
cellDefinition: {
valuePath: 'metadata.created_at'
},
sort: {
type: 'sort',
orderKey: 'createdAt',
field: 'metadata.created_at'
},
}],
text: {
title: 'CUSTOM TITLE (OR NONE)',
filter: 'Search by nameaaa',
noEntries: 'There are no organizations'
}
};
}

private setupWithDataSourceOverrides() {
this.dataSourceConfig = {
refresh: null,
transformEntities: [
{ type: 'filter', field: 'entity.name' },
(entities: any[], paginationState: PaginationEntityState) => {
return entities;
// return [entities[0], entities[1]];
}]
};
}

private setupWithOriginalListConfig() {
this.listConfig = this.temp;
}

private setupWithMinimalListConfig() {
this.listActionConfig = CloudFoundryEndpointService.createGetAllOrganizations(this.cfEndpointService.cfGuid);
this.listConfig = {
cardComponent: CfOrgCardComponent,
viewType: ListViewTypes.CARD_ONLY,
defaultView: 'cards' as ListView,
getColumns: () => [{
columnId: 'name',
headerCell: () => 'Name',
sort: {
type: 'sort',
orderKey: 'name',
field: 'entity.name'
}
}, {
columnId: 'createdAt',
headerCell: () => 'Creation',
sort: {
type: 'sort',
orderKey: 'createdAt',
field: 'metadata.created_at'
},
}],
text: {
title: null,
filter: 'Search by name',
noEntries: 'There are no organizations'
}
};
this.dataSourceConfig = {
transformEntities: [{ type: 'filter', field: 'entity.name' }] // Note - this will go away once fixed in default case
};
}

constructor(
public cfEndpointService: CloudFoundryEndpointService,
currentUserPermissionsService: CurrentUserPermissionsService
currentUserPermissionsService: CurrentUserPermissionsService,
private temp: CfOrgsListConfigService,
) {
this.canAddOrg$ = currentUserPermissionsService.can(CurrentUserPermissions.ORGANIZATION_CREATE, this.cfEndpointService.cfGuid);

// TODO: RC Nuke all below (keep setup minimal contents)
this.setupWithAction();
// this.setupWithEntityConfig();
this.setupWithListOverrides();
this.setupWithDataSourceOverrides();
// this.setupWithOriginalListConfig();// (ListService provider)
// this.setupWithMinimalListConfig();// (same as original but overrides instead of service)
}
cardComponent = CfOrgCardComponent;
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ export interface IListDataSourceConfig<A, T> {

/**
* A function which fetches an observable containing a specific row's state
*
*/
getRowState?(row: T): Observable<RowState>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Store } from '@ngrx/store';

import { isPaginatedAction, PaginatedAction } from '../../../../../../store/src/types/pagination.types';
import { StratosBaseCatalogueEntity } from '../../../../core/entity-catalogue/entity-catalogue-entity';
import { entityCatalogue } from '../../../../core/entity-catalogue/entity-catalogue.service';
import { EntityCatalogueEntityConfig } from '../../../../core/entity-catalogue/entity-catalogue.types';
import { ListDataSource } from '../data-sources-controllers/list-data-source';
import { IListDataSourceConfig } from '../data-sources-controllers/list-data-source-config';
import { IListConfig } from '../list.component.types';

export type ListDefaultsActionOrConfig = PaginatedAction | ListDefaultsConfig;

export interface ListDefaultsConfig {
entityConfig: EntityCatalogueEntityConfig;
endpointGuid?: string;
paginationKey?: string;
extraArgs?: Record<any, any>;
}

function actionFromConfig(config: ListDefaultsConfig): PaginatedAction {
const catalogueEntity = entityCatalogue.getEntity(config.entityConfig);
const getAllActionBuilder = catalogueEntity.actionOrchestrator.getActionBuilder('getMultiple');
if (!getAllActionBuilder) {
throw Error(`List Error: ${catalogueEntity.entityKey} has no action builder for the getMultiple action.`);
}
return getAllActionBuilder(config.endpointGuid, config.paginationKey, config.extraArgs);
}

export function createListActionFromActionOrConfig(actionOrConfig: ListDefaultsActionOrConfig): {
action: PaginatedAction,
catalogueEntity: StratosBaseCatalogueEntity
} {
const action = isPaginatedAction(actionOrConfig) || actionFromConfig(actionOrConfig as ListDefaultsConfig);
const catalogueEntity = entityCatalogue.getEntity(action);
return {
action,
catalogueEntity
};
}

export class ListDefaultsDataSource<A, T> extends ListDataSource<T, A> {

constructor(actionOrConfig: ListDefaultsActionOrConfig,
listConfig: IListConfig<T>,
store: Store<any>,
dataSourceConfig?: Partial<IListDataSourceConfig<A, T>>, ) {
const { action, catalogueEntity } = createListActionFromActionOrConfig(actionOrConfig);
super({
store,
action,
paginationKey: action.paginationKey,
schema: catalogueEntity.getSchema(action.schemaKey),
getRowUniqueId: entity => catalogueEntity.getGuidFromEntity(entity),
listConfig,
isLocal: true, // assume true unless overwritten
...dataSourceConfig
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Store } from '@ngrx/store';

import { IListDataSourceConfig } from '../data-sources-controllers/list-data-source-config';
import { IListConfig } from '../list.component.types';
import { CatalogueEntityDrivenListConfig } from '../simple-list/entity-catalogue-list-config';
import {
createListActionFromActionOrConfig,
ListDefaultsActionOrConfig,
ListDefaultsDataSource as ListDefaultsDataSource,
} from './defaults-datasource';

function createListConfig<A, T>(
actionOrConfig?: ListDefaultsActionOrConfig,
listConfig?: Partial<IListConfig<T>>
) {
if (actionOrConfig) {
const { catalogueEntity } = createListActionFromActionOrConfig(actionOrConfig);
return {
...new CatalogueEntityDrivenListConfig<T>(catalogueEntity),
...listConfig
};
} else if (listConfig) {
// Going on the assumption that the list is not a partial if used in this way
return listConfig as IListConfig<T>;
} else {
throw Error(`Either \`actionOrConfig\` or \`listConfig\` must be supplied when creating a defaults list`);
}
}

function createDataSource<A, T>(
store: Store<any>,
listConfig: IListConfig<T>,
actionOrConfig?: ListDefaultsActionOrConfig,
dataSourceConfig?: Partial<IListDataSourceConfig<A, T>>,
) {
const existingDs = listConfig.getDataSource ? listConfig.getDataSource() : null;
return existingDs || new ListDefaultsDataSource<A, T>(
actionOrConfig,
listConfig,
store,
dataSourceConfig
);
}


export function createListDefaultConfig<A, T>(
store: Store<any>,
actionOrConfig?: ListDefaultsActionOrConfig,
listConfig?: Partial<IListConfig<T>>,
dataSourceConfig?: Partial<IListDataSourceConfig<A, T>>,
): IListConfig<T> {

const newListConfig = createListConfig<A, T>(
actionOrConfig,
listConfig,
);

const ds = createDataSource(
store,
newListConfig,
actionOrConfig,
dataSourceConfig
);
newListConfig.getDataSource = () => ds;

return newListConfig;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<ng-template list-host></ng-template>
Loading

0 comments on commit 247f2de

Please sign in to comment.