From be9a4f3fe8e3b101ffc4a96c996dfc553d3a4e1f Mon Sep 17 00:00:00 2001 From: ersonp Date: Mon, 2 Aug 2021 18:00:41 +0530 Subject: [PATCH 01/19] Add stcpr heartbeat --- pkg/transport/network/addrresolver/client.go | 41 ++++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/pkg/transport/network/addrresolver/client.go b/pkg/transport/network/addrresolver/client.go index 286e114c20..04275b59e0 100644 --- a/pkg/transport/network/addrresolver/client.go +++ b/pkg/transport/network/addrresolver/client.go @@ -27,12 +27,14 @@ import ( const ( // sudphPriority is used to set an order how connection filters apply. - sudphPriority = 1 - stcprBindPath = "/bind/stcpr" - addrChSize = 1024 - udpKeepAliveInterval = 10 * time.Second - udpKeepAliveMessage = "keepalive" - defaultUDPPort = "30178" + sudphPriority = 1 + stcprBindPath = "/bind/stcpr" + stcprAlivePath = "/alive/stcpr/%s" + stcprKeepAliveInterval = 300 * time.Second + addrChSize = 1024 + udpKeepAliveInterval = 10 * time.Second + udpKeepAliveMessage = "keepalive" + defaultUDPPort = "30178" ) var ( @@ -216,6 +218,12 @@ func (c *httpClient) BindSTCPR(ctx context.Context, port string) error { return fmt.Errorf("status: %d, error: %w", resp.StatusCode, extractError(resp.Body)) } + go func() { + if err := c.keepStcprAliveLoop(ctx); err != nil { + c.log.WithError(err).Errorf("Failed to send TCP keep alive signal to address-resolver") + } + }() + return nil } @@ -273,7 +281,7 @@ func (c *httpClient) BindSUDPH(filter *pfilter.PacketFilter, hs Handshake) (<-ch addrCh := c.readSUDPHMessages(arConn) go func() { - if err := c.keepAliveLoop(arConn); err != nil { + if err := c.keepSudphAliveLoop(arConn); err != nil { c.log.WithError(err).Errorf("Failed to send keep alive UDP packet to address-resolver") } }() @@ -413,8 +421,25 @@ func (c *httpClient) Close() error { return nil } +// Keep stcpr alive in address-resolver +func (c *httpClient) keepStcprAliveLoop(ctx context.Context) error { + for { + select { + case <-c.closed: + return nil + default: + _, err := c.Get(ctx, fmt.Sprintf(stcprAlivePath, c.pk.String())) + if err != nil { + return err + } + + time.Sleep(stcprKeepAliveInterval) + } + } +} + // Keep NAT mapping alive. -func (c *httpClient) keepAliveLoop(w io.Writer) error { +func (c *httpClient) keepSudphAliveLoop(w io.Writer) error { for { select { case <-c.closed: From 12befebf750d448568388cc0f16aae9b2c71fe99 Mon Sep 17 00:00:00 2001 From: ersonp Date: Mon, 2 Aug 2021 22:26:42 +0530 Subject: [PATCH 02/19] Update url --- pkg/transport/network/addrresolver/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/transport/network/addrresolver/client.go b/pkg/transport/network/addrresolver/client.go index 04275b59e0..42ca3d180c 100644 --- a/pkg/transport/network/addrresolver/client.go +++ b/pkg/transport/network/addrresolver/client.go @@ -428,7 +428,7 @@ func (c *httpClient) keepStcprAliveLoop(ctx context.Context) error { case <-c.closed: return nil default: - _, err := c.Get(ctx, fmt.Sprintf(stcprAlivePath, c.pk.String())) + _, err := c.Get(ctx, stcprAlivePath) if err != nil { return err } From fa85ee30ac561221629c51f89320ea9f14c8b8da Mon Sep 17 00:00:00 2001 From: ersonp Date: Mon, 2 Aug 2021 22:30:56 +0530 Subject: [PATCH 03/19] Fix url --- pkg/transport/network/addrresolver/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/transport/network/addrresolver/client.go b/pkg/transport/network/addrresolver/client.go index 42ca3d180c..9974c34dbe 100644 --- a/pkg/transport/network/addrresolver/client.go +++ b/pkg/transport/network/addrresolver/client.go @@ -29,7 +29,7 @@ const ( // sudphPriority is used to set an order how connection filters apply. sudphPriority = 1 stcprBindPath = "/bind/stcpr" - stcprAlivePath = "/alive/stcpr/%s" + stcprAlivePath = "/alive/stcpr" stcprKeepAliveInterval = 300 * time.Second addrChSize = 1024 udpKeepAliveInterval = 10 * time.Second From 1c5cd683e8848b90d931bf8b40526e7fdcb78383 Mon Sep 17 00:00:00 2001 From: ersonp Date: Wed, 18 Aug 2021 14:58:26 +0530 Subject: [PATCH 04/19] Change alive to heartbeat --- pkg/transport/network/addrresolver/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/transport/network/addrresolver/client.go b/pkg/transport/network/addrresolver/client.go index 9974c34dbe..73a37d9d47 100644 --- a/pkg/transport/network/addrresolver/client.go +++ b/pkg/transport/network/addrresolver/client.go @@ -29,7 +29,7 @@ const ( // sudphPriority is used to set an order how connection filters apply. sudphPriority = 1 stcprBindPath = "/bind/stcpr" - stcprAlivePath = "/alive/stcpr" + stcprAlivePath = "/heartbeat/stcpr" stcprKeepAliveInterval = 300 * time.Second addrChSize = 1024 udpKeepAliveInterval = 10 * time.Second From 1b5152083fcc2ea81a88b4cfeda1fb6ba77a212d Mon Sep 17 00:00:00 2001 From: ersonp Date: Wed, 18 Aug 2021 15:17:03 +0530 Subject: [PATCH 05/19] Update keepStcprHeartbeatLoop logic --- pkg/transport/network/addrresolver/client.go | 45 ++++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/pkg/transport/network/addrresolver/client.go b/pkg/transport/network/addrresolver/client.go index 73a37d9d47..8d63850b11 100644 --- a/pkg/transport/network/addrresolver/client.go +++ b/pkg/transport/network/addrresolver/client.go @@ -27,14 +27,14 @@ import ( const ( // sudphPriority is used to set an order how connection filters apply. - sudphPriority = 1 - stcprBindPath = "/bind/stcpr" - stcprAlivePath = "/heartbeat/stcpr" - stcprKeepAliveInterval = 300 * time.Second - addrChSize = 1024 - udpKeepAliveInterval = 10 * time.Second - udpKeepAliveMessage = "keepalive" - defaultUDPPort = "30178" + sudphPriority = 1 + stcprBindPath = "/bind/stcpr" + stcprHeartbeatPath = "/heartbeat/stcpr" + stcprKeepHeartbeatInterval = 300 * time.Second + addrChSize = 1024 + udpKeepHeartbeatInterval = 10 * time.Second + udpKeepHeartbeatMessage = "heartbeat" + defaultUDPPort = "30178" ) var ( @@ -219,8 +219,8 @@ func (c *httpClient) BindSTCPR(ctx context.Context, port string) error { } go func() { - if err := c.keepStcprAliveLoop(ctx); err != nil { - c.log.WithError(err).Errorf("Failed to send TCP keep alive signal to address-resolver") + if err := c.keepStcprHeartbeatLoop(ctx); err != nil { + c.log.WithError(err).Errorf("Failed to send TCP heartbeat signal to address-resolver") } }() @@ -281,8 +281,8 @@ func (c *httpClient) BindSUDPH(filter *pfilter.PacketFilter, hs Handshake) (<-ch addrCh := c.readSUDPHMessages(arConn) go func() { - if err := c.keepSudphAliveLoop(arConn); err != nil { - c.log.WithError(err).Errorf("Failed to send keep alive UDP packet to address-resolver") + if err := c.keepSudphHeartbeatLoop(arConn); err != nil { + c.log.WithError(err).Errorf("Failed to send UDP heartbeat packet to address-resolver") } }() @@ -421,35 +421,34 @@ func (c *httpClient) Close() error { return nil } -// Keep stcpr alive in address-resolver -func (c *httpClient) keepStcprAliveLoop(ctx context.Context) error { +// Keep stcpr heartbeat in address-resolver +func (c *httpClient) keepStcprHeartbeatLoop(ctx context.Context) error { for { + _, err := c.Get(ctx, stcprHeartbeatPath) + if err != nil { + return err + } select { case <-c.closed: return nil default: - _, err := c.Get(ctx, stcprAlivePath) - if err != nil { - return err - } - - time.Sleep(stcprKeepAliveInterval) + time.Sleep(stcprKeepHeartbeatInterval) } } } // Keep NAT mapping alive. -func (c *httpClient) keepSudphAliveLoop(w io.Writer) error { +func (c *httpClient) keepSudphHeartbeatLoop(w io.Writer) error { for { select { case <-c.closed: return nil default: - if _, err := w.Write([]byte(udpKeepAliveMessage)); err != nil { + if _, err := w.Write([]byte(udpKeepHeartbeatMessage)); err != nil { return err } - time.Sleep(udpKeepAliveInterval) + time.Sleep(udpKeepHeartbeatInterval) } } } From 780f550c3341061b1502b41278a37e66708ee11a Mon Sep 17 00:00:00 2001 From: ersonp Date: Wed, 18 Aug 2021 15:25:10 +0530 Subject: [PATCH 06/19] Test logs --- pkg/transport/network/addrresolver/client.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkg/transport/network/addrresolver/client.go b/pkg/transport/network/addrresolver/client.go index 8d63850b11..82e205e845 100644 --- a/pkg/transport/network/addrresolver/client.go +++ b/pkg/transport/network/addrresolver/client.go @@ -218,7 +218,13 @@ func (c *httpClient) BindSTCPR(ctx context.Context, port string) error { return fmt.Errorf("status: %d, error: %w", resp.StatusCode, extractError(resp.Body)) } + c.log.Errorf("HERERERERERERERERERE") + c.log.Errorf("HERERERERERERERERERE") + c.log.Errorf("HERERERERERERERERERE") + c.log.Errorf("HERERERERERERERERERE") go func() { + c.log.Errorf("2222222222222222222") + if err := c.keepStcprHeartbeatLoop(ctx); err != nil { c.log.WithError(err).Errorf("Failed to send TCP heartbeat signal to address-resolver") } @@ -424,6 +430,9 @@ func (c *httpClient) Close() error { // Keep stcpr heartbeat in address-resolver func (c *httpClient) keepStcprHeartbeatLoop(ctx context.Context) error { for { + c.log.Errorf("233333333333333333333") + c.log.Errorf("233333333333333333333") + c.log.Errorf("233333333333333333333") _, err := c.Get(ctx, stcprHeartbeatPath) if err != nil { return err From 4736e520788f858e52d3209f13a139a294cd74f4 Mon Sep 17 00:00:00 2001 From: ersonp Date: Wed, 18 Aug 2021 15:29:53 +0530 Subject: [PATCH 07/19] Logs --- pkg/transport/network/addrresolver/client.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/transport/network/addrresolver/client.go b/pkg/transport/network/addrresolver/client.go index 82e205e845..4a7eae4a08 100644 --- a/pkg/transport/network/addrresolver/client.go +++ b/pkg/transport/network/addrresolver/client.go @@ -228,6 +228,7 @@ func (c *httpClient) BindSTCPR(ctx context.Context, port string) error { if err := c.keepStcprHeartbeatLoop(ctx); err != nil { c.log.WithError(err).Errorf("Failed to send TCP heartbeat signal to address-resolver") } + c.log.Errorf("444444444444444444") }() return nil @@ -435,6 +436,7 @@ func (c *httpClient) keepStcprHeartbeatLoop(ctx context.Context) error { c.log.Errorf("233333333333333333333") _, err := c.Get(ctx, stcprHeartbeatPath) if err != nil { + c.log.Error(err) return err } select { From 91b554c2a6d5c77a8eb0b96d62c4a184f2cd0226 Mon Sep 17 00:00:00 2001 From: ersonp Date: Wed, 18 Aug 2021 15:45:09 +0530 Subject: [PATCH 08/19] Logs --- pkg/transport/network/addrresolver/client.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/transport/network/addrresolver/client.go b/pkg/transport/network/addrresolver/client.go index 4a7eae4a08..0db8965369 100644 --- a/pkg/transport/network/addrresolver/client.go +++ b/pkg/transport/network/addrresolver/client.go @@ -145,12 +145,14 @@ func (c *httpClient) initHTTPClient() { func (c *httpClient) Get(ctx context.Context, path string) (*http.Response, error) { <-c.ready + c.log.Errorf("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy") addr := c.httpClient.Addr() + path req, err := http.NewRequest(http.MethodGet, addr, new(bytes.Buffer)) if err != nil { return nil, err } + c.log.Errorf("xzzzzzzzzzzzzzzzzzzzzzzzzzzz") return c.httpClient.Do(req.WithContext(ctx)) } @@ -439,6 +441,7 @@ func (c *httpClient) keepStcprHeartbeatLoop(ctx context.Context) error { c.log.Error(err) return err } + c.log.Errorf("xxxxxxxxxxxxxxxxxxxx") select { case <-c.closed: return nil From e835e906ba49c21db725bde24425675ff065c626 Mon Sep 17 00:00:00 2001 From: ersonp Date: Wed, 18 Aug 2021 15:54:10 +0530 Subject: [PATCH 09/19] Remove test logs --- pkg/transport/network/addrresolver/client.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pkg/transport/network/addrresolver/client.go b/pkg/transport/network/addrresolver/client.go index 0db8965369..8d63850b11 100644 --- a/pkg/transport/network/addrresolver/client.go +++ b/pkg/transport/network/addrresolver/client.go @@ -145,14 +145,12 @@ func (c *httpClient) initHTTPClient() { func (c *httpClient) Get(ctx context.Context, path string) (*http.Response, error) { <-c.ready - c.log.Errorf("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy") addr := c.httpClient.Addr() + path req, err := http.NewRequest(http.MethodGet, addr, new(bytes.Buffer)) if err != nil { return nil, err } - c.log.Errorf("xzzzzzzzzzzzzzzzzzzzzzzzzzzz") return c.httpClient.Do(req.WithContext(ctx)) } @@ -220,17 +218,10 @@ func (c *httpClient) BindSTCPR(ctx context.Context, port string) error { return fmt.Errorf("status: %d, error: %w", resp.StatusCode, extractError(resp.Body)) } - c.log.Errorf("HERERERERERERERERERE") - c.log.Errorf("HERERERERERERERERERE") - c.log.Errorf("HERERERERERERERERERE") - c.log.Errorf("HERERERERERERERERERE") go func() { - c.log.Errorf("2222222222222222222") - if err := c.keepStcprHeartbeatLoop(ctx); err != nil { c.log.WithError(err).Errorf("Failed to send TCP heartbeat signal to address-resolver") } - c.log.Errorf("444444444444444444") }() return nil @@ -433,15 +424,10 @@ func (c *httpClient) Close() error { // Keep stcpr heartbeat in address-resolver func (c *httpClient) keepStcprHeartbeatLoop(ctx context.Context) error { for { - c.log.Errorf("233333333333333333333") - c.log.Errorf("233333333333333333333") - c.log.Errorf("233333333333333333333") _, err := c.Get(ctx, stcprHeartbeatPath) if err != nil { - c.log.Error(err) return err } - c.log.Errorf("xxxxxxxxxxxxxxxxxxxx") select { case <-c.closed: return nil From a314e2adfd401ebc4f08e4ca8fe1e77a0f4bee09 Mon Sep 17 00:00:00 2001 From: ersonp Date: Thu, 19 Aug 2021 22:04:27 +0530 Subject: [PATCH 10/19] Add debug log --- pkg/transport/network/addrresolver/client.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/transport/network/addrresolver/client.go b/pkg/transport/network/addrresolver/client.go index 8d63850b11..ac06860d6d 100644 --- a/pkg/transport/network/addrresolver/client.go +++ b/pkg/transport/network/addrresolver/client.go @@ -428,6 +428,8 @@ func (c *httpClient) keepStcprHeartbeatLoop(ctx context.Context) error { if err != nil { return err } + + c.log.Debugf("Sent TCP heartbeat signal to address-resolver") select { case <-c.closed: return nil From 6c54030cdcd19a9946b123d96c50f356124bc4b0 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Fri, 27 Aug 2021 19:50:36 -0400 Subject: [PATCH 11/19] Add the persistent transports to the UI --- .../src/app/app.datatypes.ts | 11 +- .../pages/node-list/node-list.component.html | 2 +- .../pages/node-list/node-list.component.scss | 4 - .../all-transports.component.html | 7 +- .../all-transports.component.ts | 10 +- .../pages/node/routing/routing.component.html | 5 +- .../pages/node/routing/routing.component.ts | 6 +- .../transport-details.component.html | 10 +- .../transport-details.component.scss | 5 + .../transport-list.component.html | 74 +++-- .../transport-list.component.scss | 15 + .../transport-list.component.ts | 270 ++++++++++++------ .../src/app/services/node.service.ts | 14 +- .../src/app/services/transport.service.ts | 5 + .../src/assets/i18n/en.json | 43 +-- .../src/assets/i18n/es.json | 43 +-- .../src/assets/i18n/es_base.json | 43 +-- .../src/assets/scss/_text.scss | 4 + 18 files changed, 384 insertions(+), 187 deletions(-) diff --git a/static/skywire-manager-src/src/app/app.datatypes.ts b/static/skywire-manager-src/src/app/app.datatypes.ts index d540a8a604..b60920c3f1 100644 --- a/static/skywire-manager-src/src/app/app.datatypes.ts +++ b/static/skywire-manager-src/src/app/app.datatypes.ts @@ -5,6 +5,7 @@ export class Node { version: string; apps: Application[]; transports: Transport[]; + persistentTransports: PersistentTransport[]; routesCount: number; minHops: number; routes?: Route[]; @@ -26,13 +27,21 @@ export interface Application { } export interface Transport { - isUp: boolean; id: string; localPk: string; remotePk: string; type: string; recv: number|null; sent: number|null; + + // Calculated internally + isPersistent?: boolean; + notFound?: boolean; +} + +export interface PersistentTransport { + pk: string; + type: string; } export interface Route { diff --git a/static/skywire-manager-src/src/app/components/pages/node-list/node-list.component.html b/static/skywire-manager-src/src/app/components/pages/node-list/node-list.component.html index 6ce6c3ff95..fb6135f10a 100644 --- a/static/skywire-manager-src/src/app/components/pages/node-list/node-list.component.html +++ b/static/skywire-manager-src/src/app/components/pages/node-list/node-list.component.html @@ -81,7 +81,7 @@ - star_outline + star_outline {{ dataSorter.sortingArrow }} diff --git a/static/skywire-manager-src/src/app/components/pages/node-list/node-list.component.scss b/static/skywire-manager-src/src/app/components/pages/node-list/node-list.component.scss index 296715889c..ce07e8576f 100644 --- a/static/skywire-manager-src/src/app/components/pages/node-list/node-list.component.scss +++ b/static/skywire-manager-src/src/app/components/pages/node-list/node-list.component.scss @@ -23,10 +23,6 @@ color: $yellow; } -.gray-text { - color: $light-gray !important; -} - .small-column { width: 1px; } diff --git a/static/skywire-manager-src/src/app/components/pages/node/routing/all-transports/all-transports.component.html b/static/skywire-manager-src/src/app/components/pages/node/routing/all-transports/all-transports.component.html index 44f648e5c8..5c2f454be5 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/routing/all-transports/all-transports.component.html +++ b/static/skywire-manager-src/src/app/components/pages/node/routing/all-transports/all-transports.component.html @@ -1,6 +1,5 @@ + *ngIf="node" + [node]="node" + [showShortList]="false"> diff --git a/static/skywire-manager-src/src/app/components/pages/node/routing/all-transports/all-transports.component.ts b/static/skywire-manager-src/src/app/components/pages/node/routing/all-transports/all-transports.component.ts index 77f24aa195..eb25b043ac 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/routing/all-transports/all-transports.component.ts +++ b/static/skywire-manager-src/src/app/components/pages/node/routing/all-transports/all-transports.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, OnDestroy } from '@angular/core'; import { Subscription } from 'rxjs'; -import { Node, Transport } from '../../../../../app.datatypes'; +import { Node } from '../../../../../app.datatypes'; import { NodeComponent } from '../../node.component'; /** @@ -13,17 +13,13 @@ import { NodeComponent } from '../../node.component'; styleUrls: ['./all-transports.component.scss'] }) export class AllTransportsComponent implements OnInit, OnDestroy { - transports: Transport[]; - nodePK: string; + node: Node; private dataSubscription: Subscription; ngOnInit() { // Get the node data from the parent page. - this.dataSubscription = NodeComponent.currentNode.subscribe((node: Node) => { - this.nodePK = node.localPk; - this.transports = node.transports; - }); + this.dataSubscription = NodeComponent.currentNode.subscribe((node: Node) => this.node = node); } ngOnDestroy() { diff --git a/static/skywire-manager-src/src/app/components/pages/node/routing/routing.component.html b/static/skywire-manager-src/src/app/components/pages/node/routing/routing.component.html index 8b6b5eb125..54b16c449d 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/routing/routing.component.html +++ b/static/skywire-manager-src/src/app/components/pages/node/routing/routing.component.html @@ -1,7 +1,6 @@ + [node]="node" + [showShortList]="true"> { this.nodePK = node.localPk; - this.transports = node.transports; + this.node = node; this.routes = node.routes; }); } diff --git a/static/skywire-manager-src/src/app/components/pages/node/routing/transport-list/transport-details/transport-details.component.html b/static/skywire-manager-src/src/app/components/pages/node/routing/transport-list/transport-details/transport-details.component.html index 0896336b00..900d27e54b 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/routing/transport-list/transport-details/transport-details.component.html +++ b/static/skywire-manager-src/src/app/components/pages/node/routing/transport-list/transport-details/transport-details.component.html @@ -4,10 +4,12 @@ list{{ 'transports.details.basic.title' | translate }}
- {{ 'transports.details.basic.state' | translate }} -
- {{ ('transports.statuses.' + (data.isUp ? 'online' : 'offline')) | translate }} -
+ {{ 'transports.details.basic.persistent' | translate }} + + {{ 'common.yes' | translate }} + help + + {{ 'common.no' | translate }}
{{ 'transports.details.basic.id' | translate }} {{ data.id }} diff --git a/static/skywire-manager-src/src/app/components/pages/node/routing/transport-list/transport-details/transport-details.component.scss b/static/skywire-manager-src/src/app/components/pages/node/routing/transport-list/transport-details/transport-details.component.scss index e69de29bb2..a54adeac41 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/routing/transport-list/transport-details/transport-details.component.scss +++ b/static/skywire-manager-src/src/app/components/pages/node/routing/transport-list/transport-details/transport-details.component.scss @@ -0,0 +1,5 @@ +.help-icon { + opacity: 0.5; + font-size: 14px; + cursor: default; +} diff --git a/static/skywire-manager-src/src/app/components/pages/node/routing/transport-list/transport-list.component.html b/static/skywire-manager-src/src/app/components/pages/node/routing/transport-list/transport-list.component.html index 6b88138f81..8a48b2f032 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/routing/transport-list/transport-list.component.html +++ b/static/skywire-manager-src/src/app/components/pages/node/routing/transport-list/transport-list.component.html @@ -32,15 +32,18 @@ *ngIf="dataSource && dataSource.length > 0" >more_horiz -
- {{ 'transports.remove-all-offline' | translate }} -
{{ 'selection.select-all' | translate }}
{{ 'selection.unselect-all' | translate }}
+
+ {{ 'transports.make-selected-persistent' | translate }} +
+
+ {{ 'transports.make-selected-non-persistent' | translate }} +
{{ 'selection.delete-all' | translate }}
@@ -70,9 +73,9 @@ - - - {{ dataSorter.sortingArrow }} + + star_outline + {{ dataSorter.sortingArrow }} {{ 'transports.id' | translate }} @@ -103,7 +106,7 @@ - + - + + - + + {{ 'transports.offline' | translate }} + + + {{ 'transports.offline' | translate }} {{ transport.type }} - + {{ transport.sent | autoScale }} - + {{ transport.recv | autoScale }} + + {{ 'transports.offline' | translate }} + + + {{ 'transports.offline' | translate }} +