diff --git a/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-details/route-details.component.html b/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-details/route-details.component.html index 5f2905e91f..4135dfbb27 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-details/route-details.component.html +++ b/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-details/route-details.component.html @@ -54,6 +54,11 @@ routeRule.forwardFields.nextTid : routeRule.intermediaryForwardFields.nextTid }} + {{ + getLabel(routeRule.forwardFields ? + routeRule.forwardFields.nextTid : + routeRule.intermediaryForwardFields.nextTid) + }} @@ -69,6 +74,11 @@ routeRule.appFields.routeDescriptor.dstPk : routeRule.forwardFields.routeDescriptor.dstPk }} + {{ + getLabel(routeRule.appFields ? + routeRule.appFields.routeDescriptor.dstPk : + routeRule.forwardFields.routeDescriptor.dstPk) + }}
{{ 'routes.details.specific-fields.source-pk' | translate }} @@ -77,6 +87,11 @@ routeRule.appFields.routeDescriptor.srcPk : routeRule.forwardFields.routeDescriptor.srcPk }} + {{ + getLabel(routeRule.appFields ? + routeRule.appFields.routeDescriptor.srcPk : + routeRule.forwardFields.routeDescriptor.srcPk) + }}
{{ 'routes.details.specific-fields.destination-port' | translate }} diff --git a/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-details/route-details.component.ts b/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-details/route-details.component.ts index 8d1febe809..71ebe39d29 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-details/route-details.component.ts +++ b/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-details/route-details.component.ts @@ -3,6 +3,7 @@ import { MatDialogRef, MAT_DIALOG_DATA, MatDialog, MatDialogConfig } from '@angu import { AppConfig } from 'src/app/app.config'; import { Route } from 'src/app/app.datatypes'; +import { StorageService } from 'src/app/services/storage.service'; /** * Modal window for showing the details of a route. @@ -39,6 +40,7 @@ export class RouteDetailsComponent { constructor( @Inject(MAT_DIALOG_DATA) data: Route, private dialogRef: MatDialogRef, + private storageService: StorageService, ) { this.routeRule = data; } @@ -54,4 +56,17 @@ export class RouteDetailsComponent { closePopup() { this.dialogRef.close(); } + + /** + * Gets the label the user has set for an ID or pk. + */ + getLabel(id: string) { + const label = this.storageService.getLabelInfo(id); + + if (label) { + return ' (' + label.label + ')'; + } + + return ''; + } } diff --git a/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-list.component.html b/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-list.component.html index 370b0bb027..cc1b7c4797 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-list.component.html +++ b/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-list.component.html @@ -67,9 +67,17 @@ {{ 'routes.key' | translate }} {{ dataSorter.sortingArrow }} - - {{ 'routes.rule' | translate }} - {{ dataSorter.sortingArrow }} + + {{ 'routes.type' | translate }} + {{ dataSorter.sortingArrow }} + + + {{ 'routes.source' | translate }} + {{ dataSorter.sortingArrow }} + + + {{ 'routes.destination' | translate }} + {{ dataSorter.sortingArrow }} @@ -85,8 +93,47 @@ {{ route.key }} - + {{ getTypeName(route.type) }} + + + + + + + + + + + + + + --- + + + + + + + + --- + --- +
diff --git a/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-list.component.ts b/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-list.component.ts index 1a6d48aa92..5dcf9016d7 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-list.component.ts +++ b/static/skywire-manager-src/src/app/components/pages/node/routing/route-list/route-list.component.ts @@ -18,6 +18,8 @@ import { TranslateService } from '@ngx-translate/core'; import { FilterProperties, FilterFieldTypes } from 'src/app/utils/filters'; import { SortingColumn, SortingModes, DataSorter } from 'src/app/utils/lists/data-sorter'; import { DataFilterer } from 'src/app/utils/lists/data-filterer'; +import { LabeledElementTextComponent } from 'src/app/components/layout/labeled-element-text/labeled-element-text.component'; +import { LabeledElementTypes, StorageService } from 'src/app/services/storage.service'; /** * Shows the list of routes of a node. I can be used to show a short preview, with just some @@ -36,7 +38,11 @@ export class RouteListComponent implements OnDestroy { // Vars with the data of the columns used for sorting the data. keySortData = new SortingColumn(['key'], 'routes.key', SortingModes.Number); - ruleSortData = new SortingColumn(['rule'], 'routes.rule', SortingModes.Text); + typeSortData = new SortingColumn(['type'], 'routes.type', SortingModes.Number); + sourceSortData = new SortingColumn(['src'], 'routes.source', SortingModes.Text, ['src_label']); + destinationSortData = new SortingColumn(['dst'], 'routes.destination', SortingModes.Text, ['dst_label']); + + labeledElementTypes = LabeledElementTypes; private dataSortedSubscription: Subscription; private dataFiltererSubscription: Subscription; @@ -72,6 +78,42 @@ export class RouteListComponent implements OnDestroy { @Input() set routes(val: Route[]) { this.allRoutes = val; + // Include additional properties with helpful data. Mostly for displating the data and for + // using the filterer and sorter objects. + this.allRoutes.forEach(route => { + // Save the type in the root of the object to be able to use it with the filterer. + if (route.ruleSummary.ruleType || route.ruleSummary.ruleType === 0) { + route['type'] = route.ruleSummary.ruleType; + } else { + route['type'] = ''; + } + + if (route.appFields || route.forwardFields) { + const routeDescriptor = route.appFields ? route.appFields.routeDescriptor : route.forwardFields.routeDescriptor; + + // Save the source and destination visor keys and the associated labels. + route['src'] = routeDescriptor.srcPk; + route['src_label'] = + LabeledElementTextComponent.getCompleteLabel(this.storageService, this.translateService, route['src']); + route['dst'] = routeDescriptor.dstPk; + route['dst_label'] = + LabeledElementTextComponent.getCompleteLabel(this.storageService, this.translateService, route['dst']); + } else if (route.intermediaryForwardFields) { + // Save the destination transport id and the associated label. There is no source transport. + route['src'] = ''; + route['src_label'] = ''; + route['dst'] = route.intermediaryForwardFields.nextTid; + route['dst_label'] = + LabeledElementTextComponent.getCompleteLabel(this.storageService, this.translateService, route['dst']); + } else { + // Special case. + route['src'] = ''; + route['src_label'] = ''; + route['dst'] = ''; + route['dst_label'] = ''; + } + }); + this.dataFilterer.setData(this.allRoutes); } @@ -84,13 +126,30 @@ export class RouteListComponent implements OnDestroy { maxlength: 8, }, { - filterName: 'routes.filter-dialog.rule', - keyNameInElementsArray: 'rule', + filterName: 'routes.filter-dialog.source', + keyNameInElementsArray: 'src', + secondaryKeyNameInElementsArray: 'src_label', type: FilterFieldTypes.TextInput, - maxlength: 150, - } + maxlength: 66, + }, + { + filterName: 'routes.filter-dialog.destination', + keyNameInElementsArray: 'dst', + secondaryKeyNameInElementsArray: 'dst_label', + type: FilterFieldTypes.TextInput, + maxlength: 66, + }, ]; + /** + * Map with the types of route rules that the hypervisor can return and are known by this app. + */ + private ruleTypes = new Map([ + [0, 'App'], + [1, 'Forward'], + [2, 'Int. forward'] + ]); + private navigationsSubscription: Subscription; private operationSubscriptionsGroup: Subscription[] = []; @@ -101,11 +160,14 @@ export class RouteListComponent implements OnDestroy { private router: Router, private snackbarService: SnackbarService, private translateService: TranslateService, + private storageService: StorageService, ) { // Initialize the data sorter. const sortableColumns: SortingColumn[] = [ this.keySortData, - this.ruleSortData, + this.typeSortData, + this.sourceSortData, + this.destinationSortData, ]; this.dataSorter = new DataSorter(this.dialog, this.translateService, sortableColumns, 0, this.listId); this.dataSortedSubscription = this.dataSorter.dataSorted.subscribe(() => { @@ -113,6 +175,27 @@ export class RouteListComponent implements OnDestroy { this.recalculateElementsToShow(); }); + // Include the known route types in the filterer config array. + const typeFilterConfig: FilterProperties = { + filterName: 'routes.filter-dialog.type', + keyNameInElementsArray: 'type', + type: FilterFieldTypes.Select, + printableLabelsForValues: [ + { + value: '', + label: 'routes.filter-dialog.any-type-option', + } + ], + }; + this.ruleTypes.forEach((v, k) => { + typeFilterConfig.printableLabelsForValues.push({ + value: k + '', + label: v, + }); + }); + this.filterProperties = [typeFilterConfig].concat(this.filterProperties); + + // Initialize the data filterer. this.dataFilterer = new DataFilterer(this.dialog, this.route, this.router, this.filterProperties, this.listId); this.dataFiltererSubscription = this.dataFilterer.dataFiltered.subscribe(data => { this.filteredRoutes = data; @@ -142,6 +225,24 @@ export class RouteListComponent implements OnDestroy { this.dataSorter.dispose(); } + /** + * Asks the node data to be refreshed. + */ + refreshData() { + NodeComponent.refreshCurrentDisplayedData(); + } + + /** + * Gets the name of a route type. + */ + getTypeName(type: number): string { + if (this.ruleTypes.has(type)) { + return this.ruleTypes.get(type); + } + + return 'Unknown'; + } + /** * Changes the selection state of an entry (modifies the state of its checkbox). */ @@ -154,7 +255,7 @@ export class RouteListComponent implements OnDestroy { } /** - * Check if at lest one entry has been selected via its checkbox. + * Checks if at lest one entry has been selected via its checkbox. */ hasSelectedElements(): boolean { if (!this.selections) { diff --git a/static/skywire-manager-src/src/assets/i18n/en.json b/static/skywire-manager-src/src/assets/i18n/en.json index 81502feea5..8d432b6ba0 100644 --- a/static/skywire-manager-src/src/assets/i18n/en.json +++ b/static/skywire-manager-src/src/assets/i18n/en.json @@ -494,7 +494,9 @@ "info": "Paths used to reach the remote visors to which transports have been established. Routes are automatically generated as needed.", "list-title": "Route list", "key": "Key", - "rule": "Rule", + "type": "Type", + "source": "Source", + "destination": "Destination", "delete-confirmation": "Are you sure you want to delete the route?", "delete-selected-confirmation": "Are you sure you want to delete the selected routes?", "delete": "Delete route", @@ -530,7 +532,10 @@ }, "filter-dialog": { "key": "The key must contain", - "rule": "The rule must contain" + "type": "The type must be", + "source": "The source must contain", + "destination": "The destination must contain", + "any-type-option": "Any" } }, diff --git a/static/skywire-manager-src/src/assets/i18n/es.json b/static/skywire-manager-src/src/assets/i18n/es.json index 734c8ce36d..b0b53bc426 100644 --- a/static/skywire-manager-src/src/assets/i18n/es.json +++ b/static/skywire-manager-src/src/assets/i18n/es.json @@ -490,7 +490,9 @@ "title": "Rutas", "list-title": "Lista de rutas", "key": "Llave", - "rule": "Regla", + "type": "Tipo", + "source": "Inicio", + "destination": "Destino", "delete-confirmation": "¿Seguro que desea borrar la ruta?", "delete-selected-confirmation": "¿Seguro que desea borrar las rutas seleccionadas?", "delete": "Borrar ruta", @@ -526,7 +528,10 @@ }, "filter-dialog": { "key": "La llave debe contener", - "rule": "La regla debe contener" + "type": "El tipo debe ser", + "source": "El inicio debe contener", + "destination": "El destino debe contener", + "any-type-option": "Cualquiera" } }, diff --git a/static/skywire-manager-src/src/assets/i18n/es_base.json b/static/skywire-manager-src/src/assets/i18n/es_base.json index 92b7dc7ae0..1f14d32215 100644 --- a/static/skywire-manager-src/src/assets/i18n/es_base.json +++ b/static/skywire-manager-src/src/assets/i18n/es_base.json @@ -490,7 +490,9 @@ "title": "Routes", "list-title": "Route list", "key": "Key", - "rule": "Rule", + "type": "Type", + "source": "Source", + "destination": "Destination", "delete-confirmation": "Are you sure you want to delete the route?", "delete-selected-confirmation": "Are you sure you want to delete the selected routes?", "delete": "Delete route", @@ -526,7 +528,10 @@ }, "filter-dialog": { "key": "The key must contain", - "rule": "The rule must contain" + "type": "The type must be", + "source": "The source must contain", + "destination": "The destination must contain", + "any-type-option": "Any" } },