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 @@ -63,6 +63,20 @@ export class OrganisationService {
});
}

getMultipleWithApplicationAdmin(
limit: number = 1000,
offset: number = 0,
orderByColumn?: string,
orderByDirection?: string
): Observable<OrganisationGetManyResponse> {
return this.restService.get(`${this.URL}/applicationAdmin`, {
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,46 @@
<div class="application-change-organization-dialog">
<h1 mat-dialog-title>{{ "APPLICATION.CHANGE-ORGANIZATION.TITLE" | translate }}</h1>
<div mat-dialog-content>
<label class="form-label" for="organizationSelect">{{
"APPLICATION.CHANGE-ORGANIZATION.CHOOSE-ORGANIZATION" | translate
}}</label>
<mat-select
id="organizationSelect"
class="form-control"
panelClass="overflow-x-hidden"
[(value)]="application.organizationId"
[compareWith]="compare"
(selectionChange)="onOrganizationChange()"
>
<mat-option *ngFor="let organization of filteredOrganizations | async" [value]="organization.id">
{{ organization.name }}
</mat-option>
</mat-select>
<label class="form-label" for="permissionSelect">{{
"APPLICATION.CHANGE-ORGANIZATION.CHOOSE-USER-GROUPS" | translate
}}</label>
<div *ngIf="permissions.length > 0">
<mat-select
id="permissionSelect"
class="form-control"
[multiple]="true"
panelClass="overflow-x-hidden"
[(value)]="application.permissionIds"
[compareWith]="compare"
>
<mat-option *ngFor="let permission of filteredPermissionsMulti | async" [value]="permission.id">
{{ permission.name }}
</mat-option>
</mat-select>
<mat-hint>{{ "APPLICATION.CHANGE-ORGANIZATION.USER-GROUP-AUTO-SELECT" | translate }}</mat-hint>
</div>
</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 @@
.application-change-organization-dialog {
width: 50vw;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { Component, Inject, OnInit } from "@angular/core";
import { UntypedFormControl } from "@angular/forms";
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 { PermissionResponse } from "@app/admin/permission/permission.model";
import { PermissionService } from "@app/admin/permission/permission.service";
import { Application, UpdateApplicationOrganization } from "@applications/application.model";
import { ApplicationService } from "@applications/application.service";
import { TranslateService } from "@ngx-translate/core";
import { ApplicationDialogModel } from "@shared/models/dialog.model";
import { SharedVariableService } from "@shared/shared-variable/shared-variable.service";
import { ReplaySubject, Subscription } from "rxjs";

@Component({
selector: "app-change-organization-dialog",
templateUrl: "./application-change-organization-dialog.component.html",
styleUrls: ["./application-change-organization-dialog.component.scss"],
})
export class ApplicationChangeOrganizationDialogComponent implements OnInit {
public applicationsSubscription: Subscription;
public permissionsSubscription: Subscription;
public organizationsSubscription: Subscription;
public application: UpdateApplicationOrganization;
public permissions: PermissionResponse[];
public organizations: Organisation[];
public filteredPermissionsMulti: ReplaySubject<PermissionResponse[]> = new ReplaySubject<PermissionResponse[]>(1);
public filteredOrganizations: ReplaySubject<Organisation[]> = new ReplaySubject<Organisation[]>(1);

constructor(
private applicationService: ApplicationService,
public translate: TranslateService,
private permissionService: PermissionService,
private organizationService: OrganisationService,
private sharedVariableService: SharedVariableService,
private snackBar: MatSnackBar,
private dialog: MatDialogRef<ApplicationChangeOrganizationDialogComponent>,
@Inject(MAT_DIALOG_DATA) public dialogModel: ApplicationDialogModel
) {
this.application = {
organizationId: this.dialogModel.organizationId ?? this.sharedVariableService.getSelectedOrganisationId(),
permissionIds: [],
};
}

ngOnInit(): void {
this.translate.use("da");
if (this.dialogModel.applicationId) {
this.getApplication(this.dialogModel.applicationId);
}
this.getOrganizations();
this.getPermissions();
}

getApplication(id: number): void {
this.applicationsSubscription = this.applicationService.getApplication(id).subscribe((application: Application) => {
this.application.permissionIds = application.permissionIds;
});
}

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

getPermissions() {
this.permissionsSubscription = this.permissionService.getPermissions(1000, 0).subscribe(res => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dit get permissions her henter kun for de organisationer hvor brugeren har userAdmin rettighed, hvilket vil sige at man ikke altid kan se alle da permissions ikke er herakiske. (Den bør nok laves om til at lave et fetch for den givne organisations permissions hvis man er applikations admin). Alternativt skal vi lige diskutere den rettighed her med Mogens

this.permissions = res.data.sort((a, b) => a.name.localeCompare(b.name, "da-DK", { numeric: true }));
this.filteredPermissionsMulti.next(
this.permissions.filter(p => p?.organization?.id === this?.application?.organizationId)
);
});
}

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

onOrganizationChange() {
this.filteredPermissionsMulti.next(
this.permissions.filter(p => p?.organization?.id === this?.application?.organizationId)
);
this.filteredPermissionsMulti.subscribe(res => {
this.application.permissionIds = res
.filter(permission => permission.automaticallyAddNewApplications)
.map(permission => permission.id);
});
}

onSubmit() {
this.applicationsSubscription = this.applicationService
.updateApplicationOrganization(this.application, this.dialogModel.applicationId)
.subscribe(savedApplication => {
this.snackBar.open(
this.translate.instant("APPLICATION.CHANGE-ORGANIZATION.SNACKBAR-SAVED", {
applicationName: savedApplication.name,
organizationName: savedApplication.belongsTo.name,
}),
"",
{
duration: 10000,
}
);
this.dialog.close(true);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ <h3>{{ "APPLICATION.DETAILS" | translate }}</h3>
</div>
</div>

<nav mat-tab-nav-bar [tabPanel]="tabPanel" >
<nav mat-tab-nav-bar [tabPanel]="tabPanel">
<a
mat-tab-link
*ngFor="let link of navTabs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import { map } from "rxjs/operators";
import { SharedVariableService } from "@shared/shared-variable/shared-variable.service";
import { ChirpstackGatewayService } from "@shared/services/chirpstack-gateway.service";
import { Gateway, GatewayResponseMany } from "@app/gateway/gateway.model";
import { MatDialog } from "@angular/material/dialog";
import { ApplicationChangeOrganizationDialogComponent } from "../application-change-organization-dialog/application-change-organization-dialog.component";
import { ApplicationDialogModel } from "@shared/models/dialog.model";

@Component({
selector: "app-application",
Expand Down Expand Up @@ -68,7 +71,8 @@ export class ApplicationDetailComponent implements OnInit, OnDestroy, AfterViewI
private deleteDialogService: DeleteDialogService,
private restService: RestService,
private sharedVariableService: SharedVariableService,
private chirpstackGatewayService: ChirpstackGatewayService
private chirpstackGatewayService: ChirpstackGatewayService,
private changeOrganizationDialog: MatDialog
) {}

ngOnInit(): void {
Expand All @@ -79,7 +83,16 @@ export class ApplicationDetailComponent implements OnInit, OnDestroy, AfterViewI
label: "",
editRouterLink: "../edit-application/" + this.id,
isErasable: true,
extraOptions: [],
};

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

this.translate
Expand Down Expand Up @@ -193,6 +206,15 @@ export class ApplicationDetailComponent implements OnInit, OnDestroy, AfterViewI
});
}

onOpenChangeOrganizationDialog() {
this.changeOrganizationDialog.open(ApplicationChangeOrganizationDialogComponent, {
data: {
applicationId: this.id,
organizationId: this.application.belongsTo.id,
} as ApplicationDialogModel,
});
}

bindApplication(id: number): void {
this.applicationsSubscription = this.applicationService.getApplication(id).subscribe(application => {
this.application = application;
Expand Down
5 changes: 5 additions & 0 deletions src/app/applications/application.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,8 @@ export interface ApplicationData {
ok?: boolean;
count?: number;
}

export class UpdateApplicationOrganization {
public organizationId: number;
public permissionIds: number[];
}
8 changes: 7 additions & 1 deletion src/app/applications/application.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Injectable } from "@angular/core";
import { Application, ApplicationData } from "@applications/application.model";
import { Application, ApplicationData, UpdateApplicationOrganization } from "@applications/application.model";
import { RestService } from "../shared/services/rest.service";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
Expand Down Expand Up @@ -76,4 +76,10 @@ export class ApplicationService {
deleteApplication(id: number) {
return this.restService.delete("application", id);
}

updateApplicationOrganization(body: UpdateApplicationOrganization, id: number): Observable<Application> {
return this.restService.put("application/updateApplicationOrganization", body, id, {
observe: "response",
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@
"APPLICATION-TABLE-ROW.EDIT" | translate
}}</a>
</li>
<li class="dropdown-item">
<a (click)="onOpenChangeOrganizationDialog(element.id)" routerLinkActive="active">{{
"APPLICATION.CHANGE-ORGANIZATION.TITLE" | translate
}}</a>
</li>
<li class="dropdown-item">
<a (click)="deleteApplication(element.id)" [routerLink]="[]">{{
"APPLICATION-TABLE-ROW.DELETE" | translate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import { ApplicationDeviceType } from "@applications/models/application-device-t
import { Datatarget } from "@applications/datatarget/datatarget.model";
import { faFlag } from "@fortawesome/free-solid-svg-icons";
import { TableColumn } from "@shared/types/table.type";
import { MatDialog } from "@angular/material/dialog";
import { ApplicationDialogModel } from "@shared/models/dialog.model";
import { ApplicationChangeOrganizationDialogComponent } from "@applications/application-change-organization-dialog/application-change-organization-dialog.component";

const columnDefinitions: TableColumn[] = [
{
Expand Down Expand Up @@ -144,7 +147,8 @@ export class ApplicationsTableComponent implements AfterViewInit, OnInit {
private applicationService: ApplicationService,
private router: Router,
private deleteDialogService: DeleteDialogService,
private cdRef: ChangeDetectorRef
private cdRef: ChangeDetectorRef,
private changeOrganizationDialog: MatDialog
) {}

ngOnInit() {
Expand Down Expand Up @@ -268,5 +272,19 @@ export class ApplicationsTableComponent implements AfterViewInit, OnInit {
return !!result;
}

onOpenChangeOrganizationDialog(id: number) {
const dialog = this.changeOrganizationDialog.open(ApplicationChangeOrganizationDialogComponent, {
data: {
applicationId: id,
} as ApplicationDialogModel,
});

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

location.reload();
});
}

protected readonly columnDefinitions = columnDefinitions;
}
2 changes: 2 additions & 0 deletions src/app/applications/applications.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { PipesModule } from "@shared/pipes/pipes.module";
import { ApplicationsTableComponent } from "./applications-list/applications-table/applications-table.component";
import { MulticastModule } from "./multicast/multicast.module";
import { ReactiveFormsModule } from "@angular/forms";
import { ApplicationChangeOrganizationDialogComponent } from "./application-change-organization-dialog/application-change-organization-dialog.component";

@NgModule({
declarations: [
Expand All @@ -28,6 +29,7 @@ import { ReactiveFormsModule } from "@angular/forms";
ApplicationsListComponent,
ApplicationsTableComponent,
BulkImportComponent,
ApplicationChangeOrganizationDialogComponent,
],
exports: [ApplicaitonsRoutingModule, ApplicationsComponent, ApplicationsTableComponent],
imports: [
Expand Down
3 changes: 3 additions & 0 deletions src/app/shared/components/top-bar/top-bar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ export class TopBarComponent implements OnInit {

onClickExtraDropdownOption(id: string) {
this.extraDropdownOptions.emit(id);
const extraDropdownOption = this.dropDownButton.extraOptions.find(opt => opt.id === id);

extraDropdownOption?.onClick();
}

public goToHelp() {
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 @@ -12,3 +12,8 @@ export class DialogModel {
export class WelcomeDialogModel {
hasSomePermission: boolean;
}

export class ApplicationDialogModel {
applicationId: number;
organizationId?: number;
}
1 change: 1 addition & 0 deletions src/app/shared/models/dropdown-button.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { PermissionType } from "@app/admin/permission/permission.model";
export interface ExtraDropdownOption {
id: string | number;
label: string;
onClick?: () => void
}

export interface DropdownButton {
Expand Down
Loading