Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/app/admin/organisation/organisation.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,20 @@ export class OrganisationService {
});
}

getMultipleWithGatewayAdmin(
limit: number = 1000,
offset: number = 0,
orderByColumn?: string,
orderByDirection?: string
): Observable<OrganisationGetManyResponse> {
return this.restService.get(`${this.URL}/gatewayAdmin`, {
limit,
offset,
orderOn: orderByColumn,
sort: orderByDirection,
});
}

delete(id: number) {
return this.restService.delete(this.URL, id);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<div class="gateway-change-organization-dialog">
<h1 mat-dialog-title>{{ "GATEWAY.CHANGE-ORGANIZATION.TITLE" | translate }}</h1>
<div mat-dialog-content>
<label class="form-label" for="organizationSelect">{{
"GATEWAY.CHANGE-ORGANIZATION.CHOOSE-ORGANIZATION" | translate
}}</label>
<mat-select
id="organizationSelect"
class="form-control"
panelClass="overflow-x-hidden"
[(value)]="gateway.organizationId"
[compareWith]="compare"
>
<mat-option *ngFor="let organization of filteredOrganizations | async" [value]="organization.id">
{{ organization.name }}
</mat-option>
</mat-select>
</div>
<div mat-dialog-actions class="d-flex flex-row">
<button (click)="onSubmit()" class="btn btn-primary">
{{ "GEN.SAVE" | translate }}
</button>
<button mat-dialog-close [mat-dialog-close]="false" class="btn btn-secondary ml-2">
{{ "GEN.CANCEL" | translate }}
</button>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.gateway-change-organization-dialog {
width: 50vw;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Component, Inject, OnInit } from "@angular/core";
import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog";
import { MatSnackBar } from "@angular/material/snack-bar";
import { Organisation } from "@app/admin/organisation/organisation.model";
import { OrganisationService } from "@app/admin/organisation/organisation.service";
import { TranslateService } from "@ngx-translate/core";
import { GatewayDialogModel } from "@shared/models/dialog.model";
import { ChirpstackGatewayService } from "@shared/services/chirpstack-gateway.service";
import { SharedVariableService } from "@shared/shared-variable/shared-variable.service";
import { ReplaySubject, Subscription } from "rxjs";
import { UpdateGatewayOrganization } from "../gateway.model";

@Component({
selector: "app-gateway-change-organization-dialog",
templateUrl: "./gateway-change-organization-dialog.component.html",
styleUrls: ["./gateway-change-organization-dialog.component.scss"],
})
export class GatewayChangeOrganizationDialogComponent implements OnInit {
public gatewaysSubscription: Subscription;
public organizationsSubscription: Subscription;
public gateway: UpdateGatewayOrganization;
public organizations: Organisation[];
public filteredOrganizations: ReplaySubject<Organisation[]> = new ReplaySubject<Organisation[]>(1);

constructor(
private gatewayService: ChirpstackGatewayService,
public translate: TranslateService,
private organizationService: OrganisationService,
private sharedVariableService: SharedVariableService,
private snackBar: MatSnackBar,
private dialog: MatDialogRef<GatewayChangeOrganizationDialogComponent>,
@Inject(MAT_DIALOG_DATA) public dialogModel: GatewayDialogModel
) {
this.gateway = {
organizationId: this.dialogModel.organizationId ?? this.sharedVariableService.getSelectedOrganisationId(),
};
}

ngOnInit(): void {
this.translate.use("da");
this.getOrganizations();
}

getOrganizations() {
this.organizationsSubscription = this.organizationService.getMultipleWithGatewayAdmin().subscribe(res => {
this.organizations = res.data;
this.filteredOrganizations.next(this.organizations.slice());
});
}

public compare(o1: any, o2: any): boolean {
return o1 === o2;
}

onSubmit() {
this.gatewaysSubscription = this.gatewayService
.updateGatewayOrganization(this.gateway, this.dialogModel.gatewayDbId)
.subscribe(gateway => {
this.snackBar.open(
this.translate.instant("GATEWAY.CHANGE-ORGANIZATION.SNACKBAR-SAVED", {
gatewayName: gateway.name,
organizationName: gateway.organization.name,
}),
"",
{
duration: 10000,
}
);
this.dialog.close(true);
});
}
}
30 changes: 29 additions & 1 deletion src/app/gateway/gateway-detail/gateway-detail.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import { ChartConfiguration } from "chart.js";
import { ColorGraphBlue1 } from "@shared/constants/color-constants";
import { formatDate } from "@angular/common";
import { DefaultPageSizeOptions } from "@shared/constants/page.constants";
import { MatDialog } from "@angular/material/dialog";
import { GatewayChangeOrganizationDialogComponent } from "../gateway-change-organization-dialog/gateway-change-organization-dialog.component";
import { GatewayDialogModel } from "@shared/models/dialog.model";

@Component({
selector: "app-gateway-detail",
Expand Down Expand Up @@ -50,7 +53,8 @@ export class GatewayDetailComponent implements OnInit, OnDestroy, AfterViewInit
private translate: TranslateService,
private router: Router,
private meService: MeService,
private deleteDialogService: DeleteDialogService
private deleteDialogService: DeleteDialogService,
private changeOrganizationDialog: MatDialog
) {}

ngOnInit(): void {
Expand Down Expand Up @@ -120,9 +124,18 @@ export class GatewayDetailComponent implements OnInit, OnDestroy, AfterViewInit
label: "LORA-GATEWAY-TABLE-ROW.SHOW-OPTIONS",
editRouterLink: "../../gateway-edit/" + this.gatewayId,
isErasable: true,
extraOptions: [],
}
: null;

this.translate.get("GATEWAY.CHANGE-ORGANIZATION.TITLE").subscribe(translation => {
this.dropdownButton.extraOptions.push({
id: this.gatewayId,
label: translation,
onClick: () => this.onOpenChangeOrganizationDialog(),
});
});

this.translate.get(["LORA-GATEWAY-TABLE-ROW.SHOW-OPTIONS"]).subscribe(translations => {
if (this.dropdownButton) {
this.dropdownButton.label = translations["LORA-GATEWAY-TABLE-ROW.SHOW-OPTIONS"];
Expand Down Expand Up @@ -188,6 +201,21 @@ export class GatewayDetailComponent implements OnInit, OnDestroy, AfterViewInit
});
}

onOpenChangeOrganizationDialog() {
const dialog = this.changeOrganizationDialog.open(GatewayChangeOrganizationDialogComponent, {
data: {
gatewayDbId: this.gateway.id,
organizationId: this.gateway.organizationId,
} as GatewayDialogModel,
});

dialog.afterClosed().subscribe(res => {
if (!res) return;

location.reload();
});
}

ngOnDestroy() {
if (this.gatewaySubscription) {
this.gatewaySubscription.unsubscribe();
Expand Down
5 changes: 5 additions & 0 deletions src/app/gateway/gateway-table/gateway-table.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@
"GEN.EDIT" | translate
}}</a>
</li>
<li class="dropdown-item">
<a (click)="onOpenChangeOrganizationDialog(gateway.id)" routerLinkActive="active">{{
"GATEWAY.CHANGE-ORGANIZATION.TITLE" | translate
}}</a>
</li>
<li class="dropdown-item">
<a (click)="clickDelete(gateway)" [routerLink]="[]">{{ "GEN.DELETE" | translate }}</a>
</li>
Expand Down
20 changes: 19 additions & 1 deletion src/app/gateway/gateway-table/gateway-table.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import { OrganizationAccessScope } from "@shared/enums/access-scopes";
import { DefaultPageSizeOptions } from "@shared/constants/page.constants";
import { TableColumn } from "@shared/types/table.type";
import { catchError, map, startWith, switchMap } from "rxjs/operators";
import { MatDialog } from "@angular/material/dialog";
import { GatewayDialogModel } from "@shared/models/dialog.model";
import { GatewayChangeOrganizationDialogComponent } from "../gateway-change-organization-dialog/gateway-change-organization-dialog.component";

const columnDefinitions: TableColumn[] = [
{
Expand Down Expand Up @@ -138,7 +141,8 @@ export class GatewayTableComponent implements AfterViewInit, OnDestroy, OnInit {
public translate: TranslateService,
private meService: MeService,
private deleteDialogService: DeleteDialogService,
private cdRef: ChangeDetectorRef
private cdRef: ChangeDetectorRef,
private changeOrganizationDialog: MatDialog
) {
this.translate.use("da");
moment.locale("da");
Expand Down Expand Up @@ -254,5 +258,19 @@ export class GatewayTableComponent implements AfterViewInit, OnDestroy, OnInit {
});
}

onOpenChangeOrganizationDialog(id: number) {
const dialog = this.changeOrganizationDialog.open(GatewayChangeOrganizationDialogComponent, {
data: {
gatewayDbId: id,
} as GatewayDialogModel,
});

dialog.afterClosed().subscribe(res => {
if (!res) return;

location.reload();
});
}

protected readonly columnDefinitions = columnDefinitions;
}
6 changes: 6 additions & 0 deletions src/app/gateway/gateway.model.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { EditPermission } from "@shared/models/edit-permission.model";
import { CommonLocation } from "@shared/models/common-location.model";
import { GatewayPlacement, GatewaySetupStatus, GatewayStatusInterval } from "./enums/gateway-status-interval.enum";
import { Organisation } from "@app/admin/organisation/organisation.model";

export class Gateway extends EditPermission {
id: number;
Expand All @@ -26,6 +27,7 @@ export class Gateway extends EditPermission {
lastSeenAt: Date;
organizationId: number;
organizationName: string;
organization: Organisation;
createdAt: Date;
updatedAt: Date;
createdBy: number;
Expand Down Expand Up @@ -93,3 +95,7 @@ export interface AllGatewayStatusResponse {
data: GatewayStatus[];
count: number;
}

export class UpdateGatewayOrganization {
public organizationId: number;
}
2 changes: 2 additions & 0 deletions src/app/gateway/gateway.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { GraphModule } from "@app/graph/graph.module";
import { GatewayListComponent } from "./gateway-overview/gateway-tabs/gateway-list/gateway-list.component";
import { GatewayMapComponent } from "./gateway-overview/gateway-tabs/gateway-map/gateway-map.component";
import { GatewayStatusOverviewComponent } from "./gateway-overview/gateway-tabs/gateway-status-overview/gateway-status-overview.component";
import { GatewayChangeOrganizationDialogComponent } from "./gateway-change-organization-dialog/gateway-change-organization-dialog.component";

const gatewayRoutes: Routes = [
{
Expand Down Expand Up @@ -51,6 +52,7 @@ const gatewayRoutes: Routes = [
GatewayListComponent,
GatewayMapComponent,
GatewayStatusOverviewComponent,
GatewayChangeOrganizationDialogComponent,
],
imports: [
CommonModule,
Expand Down
5 changes: 5 additions & 0 deletions src/app/shared/models/dialog.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ export class ApplicationDialogModel {
applicationId: number;
organizationId?: number;
}

export class GatewayDialogModel {
gatewayDbId: number;
organizationId?: number;
}
13 changes: 12 additions & 1 deletion src/app/shared/services/chirpstack-gateway.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { Injectable } from "@angular/core";
import { RestService } from "./rest.service";
import { Observable } from "rxjs";
import { GatewayResponse, Gateway, GatewayData, GatewayRequest, GatewayResponseMany } from "@app/gateway/gateway.model";
import {
GatewayResponse,
Gateway,
GatewayData,
GatewayRequest,
GatewayResponseMany,
UpdateGatewayOrganization,
} from "@app/gateway/gateway.model";
import moment from "moment";
import { SharedVariableService } from "@shared/shared-variable/shared-variable.service";
import { map } from "rxjs/operators";
Expand Down Expand Up @@ -69,6 +76,10 @@ export class ChirpstackGatewayService {
return this.restService.put(this.chripstackGatewayUrl, gatewayRequest, id);
}

public updateGatewayOrganization(body: UpdateGatewayOrganization, id: number): Observable<Gateway> {
return this.restService.put(`${this.chripstackGatewayUrl}/updateGatewayOrganization`, body, id);
}

public delete(gatewayId: string): Observable<any> {
return this.restService.delete(this.chripstackGatewayUrl, gatewayId);
}
Expand Down
5 changes: 5 additions & 0 deletions src/assets/i18n/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@
"PROJECT": "Projekt",
"PROTOTYPE": "Prototype",
"OTHER": "Andet"
},
"CHANGE-ORGANIZATION": {
"TITLE": "Skift organisation",
"CHOOSE-ORGANIZATION": "Vælg hvilken organisation denne gateway skal tilhøre",
"SNACKBAR-SAVED": "{{gatewayName}} tilhører nu {{organizationName}}"
}
},
"IOT-DEVICE": {
Expand Down