Skip to content

Commit 0724906

Browse files
committed
Added new changes from stage-branch to datatarget-log, and fix big conflicts in translation-files..
2 parents b8bae1c + ec9810c commit 0724906

File tree

60 files changed

+1440
-450
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1440
-450
lines changed

package-lock.json

Lines changed: 289 additions & 276 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/admin/organisation/organisation.service.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,34 @@ export class OrganisationService {
6363
});
6464
}
6565

66+
getMultipleWithApplicationAdmin(
67+
limit: number = 1000,
68+
offset: number = 0,
69+
orderByColumn?: string,
70+
orderByDirection?: string
71+
): Observable<OrganisationGetManyResponse> {
72+
return this.restService.get(`${this.URL}/applicationAdmin`, {
73+
limit,
74+
offset,
75+
orderOn: orderByColumn,
76+
sort: orderByDirection,
77+
});
78+
}
79+
80+
getMultipleWithGatewayAdmin(
81+
limit: number = 1000,
82+
offset: number = 0,
83+
orderByColumn?: string,
84+
orderByDirection?: string
85+
): Observable<OrganisationGetManyResponse> {
86+
return this.restService.get(`${this.URL}/gatewayAdmin`, {
87+
limit,
88+
offset,
89+
orderOn: orderByColumn,
90+
sort: orderByDirection,
91+
});
92+
}
93+
6694
delete(id: number) {
6795
return this.restService.delete(this.URL, id);
6896
}

src/app/admin/users/user-edit/user-edit.component.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,7 @@ export class UserEditComponent implements OnInit {
6868
this.user.email = response.email;
6969
this.user.id = response.id;
7070
this.user.active = response.active;
71-
this.user.globalAdmin = response.permissions.some(response =>
72-
this.meService.hasPermissions(response, PermissionType.GlobalAdmin)
73-
);
71+
this.user.globalAdmin = response.permissions.some(perm => perm.name === PermissionType.GlobalAdmin);
7472
this.isKombit = response.nameId != null;
7573
// We cannot set the password.
7674
});
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
@import "src/assets/scss/setup/variables";
2+
3+
a {
4+
color: $color-link;
5+
border-bottom: 0px transparent !important;
6+
cursor: pointer;
7+
text-decoration: none;
8+
9+
&:hover,
10+
&.link-hover,
11+
&:visited:hover {
12+
color: $color-link-hover;
13+
border-bottom: 0px $color-link-hover-bg !important;
14+
15+
&:disabled,
16+
.disabled {
17+
background-color: transparent !important;
18+
}
19+
}
20+
21+
&:active,
22+
&.link-active {
23+
background-color: inherit;
24+
color: $color-active;
25+
border-bottom: 0px $color-link-active-bg !important;
26+
}
27+
28+
&:focus,
29+
&.link-focus {
30+
color: $color-link-focus;
31+
background-color: transparent;
32+
border-bottom: 0px $color-link-focus-bg !important;
33+
}
34+
35+
&:disabled,
36+
&.disabled {
37+
box-shadow: none !important;
38+
cursor: not-allowed !important;
39+
//color: #000 !important; // FIXME: Hvad skal der der være her?
40+
outline-offset: inherit !important;
41+
42+
&:focus {
43+
outline: none;
44+
background-color: transparent;
45+
}
46+
}
47+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<div class="application-change-organization-dialog">
2+
<h1 mat-dialog-title>{{ "APPLICATION.CHANGE-ORGANIZATION.TITLE" | translate }}</h1>
3+
<div mat-dialog-content>
4+
<label class="form-label" for="organizationSelect">{{
5+
"APPLICATION.CHANGE-ORGANIZATION.CHOOSE-ORGANIZATION" | translate
6+
}}</label>
7+
<mat-select
8+
id="organizationSelect"
9+
class="form-control"
10+
panelClass="overflow-x-hidden"
11+
[(value)]="application.organizationId"
12+
[compareWith]="compare"
13+
(selectionChange)="onOrganizationChange()"
14+
>
15+
<mat-option *ngFor="let organization of filteredOrganizations | async" [value]="organization.id">
16+
{{ organization.name }}
17+
</mat-option>
18+
</mat-select>
19+
<label class="form-label" for="permissionSelect">{{
20+
"APPLICATION.CHANGE-ORGANIZATION.CHOOSE-USER-GROUPS" | translate
21+
}}</label>
22+
<div *ngIf="permissions.length > 0">
23+
<mat-select
24+
id="permissionSelect"
25+
class="form-control"
26+
[multiple]="true"
27+
panelClass="overflow-x-hidden"
28+
[(value)]="application.permissionIds"
29+
[compareWith]="compare"
30+
>
31+
<mat-option *ngFor="let permission of filteredPermissionsMulti | async" [value]="permission.id">
32+
{{ permission.name }}
33+
</mat-option>
34+
</mat-select>
35+
<mat-hint>{{ "APPLICATION.CHANGE-ORGANIZATION.USER-GROUP-AUTO-SELECT" | translate }}</mat-hint>
36+
</div>
37+
</div>
38+
<div mat-dialog-actions class="d-flex flex-row">
39+
<button (click)="onSubmit()" class="btn btn-primary">
40+
{{ "GEN.SAVE" | translate }}
41+
</button>
42+
<button mat-dialog-close [mat-dialog-close]="false" class="btn btn-secondary ml-2">
43+
{{ "GEN.CANCEL" | translate }}
44+
</button>
45+
</div>
46+
</div>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.application-change-organization-dialog {
2+
width: 50vw;
3+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { Component, Inject, OnInit } from "@angular/core";
2+
import { UntypedFormControl } from "@angular/forms";
3+
import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog";
4+
import { MatSnackBar } from "@angular/material/snack-bar";
5+
import { Organisation } from "@app/admin/organisation/organisation.model";
6+
import { OrganisationService } from "@app/admin/organisation/organisation.service";
7+
import { PermissionResponse } from "@app/admin/permission/permission.model";
8+
import { PermissionService } from "@app/admin/permission/permission.service";
9+
import { Application, UpdateApplicationOrganization } from "@applications/application.model";
10+
import { ApplicationService } from "@applications/application.service";
11+
import { TranslateService } from "@ngx-translate/core";
12+
import { ApplicationDialogModel } from "@shared/models/dialog.model";
13+
import { SharedVariableService } from "@shared/shared-variable/shared-variable.service";
14+
import { ReplaySubject, Subscription } from "rxjs";
15+
16+
@Component({
17+
selector: "app-change-organization-dialog",
18+
templateUrl: "./application-change-organization-dialog.component.html",
19+
styleUrls: ["./application-change-organization-dialog.component.scss"],
20+
})
21+
export class ApplicationChangeOrganizationDialogComponent implements OnInit {
22+
public applicationsSubscription: Subscription;
23+
public permissionsSubscription: Subscription;
24+
public organizationsSubscription: Subscription;
25+
public application: UpdateApplicationOrganization;
26+
public permissions: PermissionResponse[];
27+
public organizations: Organisation[];
28+
public filteredPermissionsMulti: ReplaySubject<PermissionResponse[]> = new ReplaySubject<PermissionResponse[]>(1);
29+
public filteredOrganizations: ReplaySubject<Organisation[]> = new ReplaySubject<Organisation[]>(1);
30+
31+
constructor(
32+
private applicationService: ApplicationService,
33+
public translate: TranslateService,
34+
private permissionService: PermissionService,
35+
private organizationService: OrganisationService,
36+
private sharedVariableService: SharedVariableService,
37+
private snackBar: MatSnackBar,
38+
private dialog: MatDialogRef<ApplicationChangeOrganizationDialogComponent>,
39+
@Inject(MAT_DIALOG_DATA) public dialogModel: ApplicationDialogModel
40+
) {
41+
this.application = {
42+
organizationId: this.dialogModel.organizationId ?? this.sharedVariableService.getSelectedOrganisationId(),
43+
permissionIds: [],
44+
};
45+
}
46+
47+
ngOnInit(): void {
48+
this.translate.use("da");
49+
if (this.dialogModel.applicationId) {
50+
this.getApplication(this.dialogModel.applicationId);
51+
}
52+
this.getOrganizations();
53+
this.getPermissions();
54+
}
55+
56+
getApplication(id: number): void {
57+
this.applicationsSubscription = this.applicationService.getApplication(id).subscribe((application: Application) => {
58+
this.application.permissionIds = application.permissionIds;
59+
});
60+
}
61+
62+
getOrganizations() {
63+
this.organizationsSubscription = this.organizationService.getMultipleWithApplicationAdmin().subscribe(res => {
64+
this.organizations = res.data;
65+
this.filteredOrganizations.next(this.organizations.slice());
66+
});
67+
}
68+
69+
getPermissions() {
70+
this.permissionsSubscription = this.permissionService.getPermissions(1000, 0).subscribe(res => {
71+
this.permissions = res.data.sort((a, b) => a.name.localeCompare(b.name, "da-DK", { numeric: true }));
72+
this.filteredPermissionsMulti.next(
73+
this.permissions.filter(p => p?.organization?.id === this?.application?.organizationId)
74+
);
75+
});
76+
}
77+
78+
public compare(o1: any, o2: any): boolean {
79+
return o1 === o2;
80+
}
81+
82+
onOrganizationChange() {
83+
this.filteredPermissionsMulti.next(
84+
this.permissions.filter(p => p?.organization?.id === this?.application?.organizationId)
85+
);
86+
this.filteredPermissionsMulti.subscribe(res => {
87+
this.application.permissionIds = res
88+
.filter(permission => permission.automaticallyAddNewApplications)
89+
.map(permission => permission.id);
90+
});
91+
}
92+
93+
onSubmit() {
94+
this.applicationsSubscription = this.applicationService
95+
.updateApplicationOrganization(this.application, this.dialogModel.applicationId)
96+
.subscribe(savedApplication => {
97+
this.snackBar.open(
98+
this.translate.instant("APPLICATION.CHANGE-ORGANIZATION.SNACKBAR-SAVED", {
99+
applicationName: savedApplication.name,
100+
organizationName: savedApplication.belongsTo.name,
101+
}),
102+
"",
103+
{
104+
duration: 10000,
105+
}
106+
);
107+
this.dialog.close(true);
108+
});
109+
}
110+
}

src/app/applications/application-detail/application-detail.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ <h3>{{ "APPLICATION.DETAILS" | translate }}</h3>
6666
</div>
6767
</div>
6868

69-
<nav mat-tab-nav-bar [tabPanel]="tabPanel" >
69+
<nav mat-tab-nav-bar [tabPanel]="tabPanel">
7070
<a
7171
mat-tab-link
7272
*ngFor="let link of navTabs"

src/app/applications/application-detail/application-detail.component.scss

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,49 @@
2020
.markerDescriptionDiv {
2121
margin-top: 10px;
2222
}
23+
24+
a {
25+
color: $color-link;
26+
border-bottom: 0px transparent !important;
27+
cursor: pointer;
28+
text-decoration: none;
29+
30+
&:hover,
31+
&.link-hover,
32+
&:visited:hover {
33+
color: $color-link-hover;
34+
border-bottom: 0px $color-link-hover-bg !important;
35+
36+
&:disabled,
37+
.disabled {
38+
background-color: transparent !important;
39+
}
40+
}
41+
42+
&:active,
43+
&.link-active {
44+
background-color: inherit;
45+
color: $color-active;
46+
border-bottom: 0px $color-link-active-bg !important;
47+
}
48+
49+
&:focus,
50+
&.link-focus {
51+
color: $color-link-focus;
52+
background-color: transparent;
53+
border-bottom: 0px $color-link-focus-bg !important;
54+
}
55+
56+
&:disabled,
57+
&.disabled {
58+
box-shadow: none !important;
59+
cursor: not-allowed !important;
60+
//color: #000 !important; // FIXME: Hvad skal der der være her?
61+
outline-offset: inherit !important;
62+
63+
&:focus {
64+
outline: none;
65+
background-color: transparent;
66+
}
67+
}
68+
}

src/app/applications/application-detail/application-detail.component.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@ import { DropdownButton } from "@shared/models/dropdown-button.model";
1010
import { MeService } from "@shared/services/me.service";
1111
import { Subscription } from "rxjs";
1212
import { OrganizationAccessScope } from "@shared/enums/access-scopes";
13-
import { IotDevicesApplicationMapResponse, IotDevicesResponse } from "@applications/iot-devices/iot-device.model";
13+
import { IotDevicesApplicationMapResponse } from "@applications/iot-devices/iot-device.model";
1414
import { RestService } from "@shared/services/rest.service";
1515
import { Observable } from "rxjs";
1616
import { map } from "rxjs/operators";
1717
import { SharedVariableService } from "@shared/shared-variable/shared-variable.service";
1818
import { ChirpstackGatewayService } from "@shared/services/chirpstack-gateway.service";
1919
import { Gateway, GatewayResponseMany } from "@app/gateway/gateway.model";
20+
import { MatDialog } from "@angular/material/dialog";
21+
import { ApplicationChangeOrganizationDialogComponent } from "../application-change-organization-dialog/application-change-organization-dialog.component";
22+
import { ApplicationDialogModel } from "@shared/models/dialog.model";
2023

2124
@Component({
2225
selector: "app-application",
@@ -68,7 +71,8 @@ export class ApplicationDetailComponent implements OnInit, OnDestroy, AfterViewI
6871
private deleteDialogService: DeleteDialogService,
6972
private restService: RestService,
7073
private sharedVariableService: SharedVariableService,
71-
private chirpstackGatewayService: ChirpstackGatewayService
74+
private chirpstackGatewayService: ChirpstackGatewayService,
75+
private changeOrganizationDialog: MatDialog
7276
) {}
7377

7478
ngOnInit(): void {
@@ -79,7 +83,16 @@ export class ApplicationDetailComponent implements OnInit, OnDestroy, AfterViewI
7983
label: "",
8084
editRouterLink: "../edit-application/" + this.id,
8185
isErasable: true,
86+
extraOptions: [],
8287
};
88+
89+
this.translate.get("APPLICATION.CHANGE-ORGANIZATION.TITLE").subscribe(translation => {
90+
this.dropdownButton.extraOptions.push({
91+
id: this.id,
92+
label: translation,
93+
onClick: () => this.onOpenChangeOrganizationDialog(),
94+
});
95+
});
8396
}
8497

8598
this.translate
@@ -113,11 +126,7 @@ export class ApplicationDetailComponent implements OnInit, OnDestroy, AfterViewI
113126

114127
private getGateways(): void {
115128
this.gatewaysSubscription = this.chirpstackGatewayService
116-
.getMultiple({
117-
limit: null,
118-
offset: null,
119-
sort: null,
120-
})
129+
.getForMaps()
121130
.subscribe((gateways: GatewayResponseMany) => {
122131
this.gateways = gateways.resultList;
123132
this.mapGatewaysToCoordinateList();
@@ -193,6 +202,15 @@ export class ApplicationDetailComponent implements OnInit, OnDestroy, AfterViewI
193202
});
194203
}
195204

205+
onOpenChangeOrganizationDialog() {
206+
this.changeOrganizationDialog.open(ApplicationChangeOrganizationDialogComponent, {
207+
data: {
208+
applicationId: this.id,
209+
organizationId: this.application.belongsTo.id,
210+
} as ApplicationDialogModel,
211+
});
212+
}
213+
196214
bindApplication(id: number): void {
197215
this.applicationsSubscription = this.applicationService.getApplication(id).subscribe(application => {
198216
this.application = application;

0 commit comments

Comments
 (0)