Skip to content

Commit 2b1d3ac

Browse files
GufCabAugustHA-IteratorAramAlsabtiaugusthjerrildbkd231
authored
Merge from stage prior to release v.1.1.0 (#69)
* Added message to prompt when attempting to delete application with SigFox device * Added message and functionality to check and to prompt when attempting to delete application with SigFox device * Made the first additions to multicast in frontend. Will try to connect to backend next. * Minor changes to make it work with backend. * PR Changes. Also made the check for sigfox devices in detail page, which i missed before. * Minor changes so detail page will show how updated/created the multicast * PR Changes + formatting * Moved two buttons, multicast and datatargets, to a tab bar in application details. * minor typo fix * Finalized CRUD in frontend. Removed list maps from datatarget and multicast because of change in requirements - now the multicast and datatarget is in a tab bar in the application detail page. * Init api key menu item * changed division in db so the frontend will receive a different promise. Mostly just changed property names because of this change. * First additions to "add device to multicast". A dropdown is made with all the possible sensors for the application, and the chosen ones is sent to backend. * Made frontend functionality so you can add devices to a multicast when you update or create. These devices is then shown in detail page. * made snack for fail to load on multicast edit page * Show api keys * removed 2 console logs * Api key management works * Cleanup after api key * Message to multicast. Made the form and service operations to send to backend, which will then handle the request to chirpstack * Changed details page. Not splitted up in basic details, and lorawan details. * PR changes plus search function for devices in multicast * PR changes - fixed pagination for multicast * Minor snack changes and check if devices is included before sending downlink * PR Changes * merge conflicting * Cleanup * Remove unique permissions pipe * API key cleanup * Fix sigfox group id * Add edit api key * Edit API key PR * Spell organization with "z" * Multicast text description changes * Fixed deleted word "adressen" in multicast creation. Is added again. * Moved hint description under the input form instead of before det input form. Matches the design of the rest of the document. * FIWARE datatarget (#67) * Datatarget multi-types administration and new FIWARE Datatarget type * PR fixes * DatatargetTypesService pr fixes * Optimize bulk import and the load on chirpstack (#65) * Batch bulk import create. Update missing * Reworked update many and cleanup * Comment on bulk import * Added device model error codes Co-authored-by: nlg <[email protected]> Co-authored-by: August Andersen <[email protected]> Co-authored-by: Aram Al-Sabti <[email protected]> Co-authored-by: augusthjerrild <[email protected]> Co-authored-by: AramAlsabti <[email protected]> Co-authored-by: Bartek <[email protected]> Co-authored-by: nlg <[email protected]>
1 parent ac22517 commit 2b1d3ac

File tree

109 files changed

+4678
-1113
lines changed

Some content is hidden

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

109 files changed

+4678
-1113
lines changed

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"typescript.tsdk": "node_modules\\typescript\\lib"
3+
}

src/app/admin/admin-routing.module.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import { UserDetailComponent } from './users/user-detail/user-detail.component';
1212
import { UserEditComponent } from './users/user-edit/user-edit.component';
1313
import { UserListComponent } from './users/user-list/user-list.component';
1414
import { UsersComponent } from './users/users.component';
15+
import { ApiKeyComponent } from './api-key/api-key.component';
16+
import { ApiKeyListComponent } from './api-key/api-key-list/api-key-list.component';
17+
import { ApiKeyEditComponent } from './api-key/api-key-edit/api-key-edit.component';
1518

1619

1720
const adminRoutes: Routes = [
@@ -44,6 +47,18 @@ const adminRoutes: Routes = [
4447
},
4548
],
4649
},
50+
{
51+
path: 'api-key',
52+
component: ApiKeyComponent,
53+
children: [
54+
{ path: '', component: ApiKeyListComponent },
55+
{ path: 'new-api-key', component: ApiKeyEditComponent },
56+
{
57+
path: ':api-key-id/edit-api-key',
58+
component: ApiKeyEditComponent,
59+
},
60+
],
61+
},
4762

4863

4964
];

src/app/admin/admin.module.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ import { UsersComponent } from './users/users.component';
2828
import { MatSelectModule } from '@angular/material/select';
2929
import { MatFormFieldModule } from '@angular/material/form-field';
3030
import { MatSelectSearchModule } from '@shared/components/mat-select-search/mat-select-search.module';
31+
import { ApiKeyComponent } from './api-key/api-key.component';
32+
import { ApiKeyListComponent } from './api-key/api-key-list/api-key-list.component';
33+
import { ApiKeyTableComponent } from './api-key/api-key-list/api-key-table/api-key-table.component';
34+
import { ApiKeyEditComponent } from './api-key/api-key-edit/api-key-edit.component';
3135

3236
@NgModule({
3337
declarations: [
@@ -46,6 +50,10 @@ import { MatSelectSearchModule } from '@shared/components/mat-select-search/mat-
4650
OrganisationDetailComponent,
4751
OrganisationEditComponent,
4852
OrganisationListComponent,
53+
ApiKeyComponent,
54+
ApiKeyListComponent,
55+
ApiKeyTableComponent,
56+
ApiKeyEditComponent,
4957
],
5058
imports: [
5159
AdminRoutingModule,
@@ -79,6 +87,10 @@ import { MatSelectSearchModule } from '@shared/components/mat-select-search/mat-
7987
OrganisationDetailComponent,
8088
OrganisationEditComponent,
8189
OrganisationListComponent,
90+
ApiKeyComponent,
91+
ApiKeyListComponent,
92+
ApiKeyTableComponent,
93+
ApiKeyEditComponent,
8294
],
8395
})
8496
export class AdminModule {}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<app-form-header [backButton]="backButton" [title]="title"></app-form-header>
2+
3+
<form (ngSubmit)="onSubmit()" class="os2-form p-3 mt-4">
4+
<div *ngIf="errorMessages" class="error-messages p-3">
5+
<ul class="mb-0">
6+
<li *ngFor="let error of errorMessages">
7+
{{ error | translate }}
8+
</li>
9+
</ul>
10+
</div>
11+
12+
<div class="row mb-5">
13+
<div class="form-group mt-3 col-12">
14+
<label class="form-label" for="name">{{
15+
'API-KEY.EDIT.NAME' | translate
16+
}}</label
17+
>*
18+
<input
19+
type="text"
20+
class="form-control"
21+
id="name"
22+
name="name"
23+
[placeholder]="'API-KEY.EDIT.NAME-PLACEHOLDER' | translate"
24+
maxlength="50"
25+
required
26+
[(ngModel)]="apiKeyRequest.name"
27+
[ngClass]="{
28+
'is-invalid': formFailedSubmit && errorFields.includes('name'),
29+
'is-valid': formFailedSubmit && !errorFields.includes('name')
30+
}"
31+
/>
32+
</div>
33+
</div>
34+
35+
<div class="row mb-5">
36+
<div class="form-group mt-3 col-12">
37+
<label class="form-label" for="permissions">{{
38+
'QUESTION.PERMISSION.SELECT-PERMISSION' | translate
39+
}}</label
40+
>*
41+
<mat-select
42+
class="form-control"
43+
name="permissions"
44+
[compareWith]="compare"
45+
[(ngModel)]="apiKeyRequest.permissionIds"
46+
[multiple]="true"
47+
>
48+
<mat-option
49+
*ngFor="let permission of permissions"
50+
[value]="permission.id"
51+
>
52+
{{ permission.name }}
53+
</mat-option>
54+
</mat-select>
55+
</div>
56+
</div>
57+
58+
<div class="form-group mt-5">
59+
<button (click)="routeBack()" class="btn btn-secondary" type="button">
60+
{{ 'GEN.CANCEL' | translate }}
61+
</button>
62+
<button class="btn btn-primary ml-2" type="submit">
63+
{{ 'GEN.SAVE' | translate }}
64+
</button>
65+
</div>
66+
</form>
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { Location } from '@angular/common';
2+
import { HttpErrorResponse } from '@angular/common/http';
3+
import { Component, OnInit } from '@angular/core';
4+
import { ActivatedRoute } from '@angular/router';
5+
import { PermissionResponse } from '@app/admin/permission/permission.model';
6+
import { PermissionService } from '@app/admin/permission/permission.service';
7+
import { TranslateService } from '@ngx-translate/core';
8+
import { ErrorMessageService } from '@shared/error-message.service';
9+
import { BackButton } from '@shared/models/back-button.model';
10+
import { SharedVariableService } from '@shared/shared-variable/shared-variable.service';
11+
import { ApiKeyRequest } from '../api-key.model';
12+
import { ApiKeyService } from '../api-key.service';
13+
14+
@Component({
15+
selector: 'app-api-key-edit',
16+
templateUrl: './api-key-edit.component.html',
17+
styleUrls: ['./api-key-edit.component.scss'],
18+
})
19+
export class ApiKeyEditComponent implements OnInit {
20+
apiKeyRequest = new ApiKeyRequest();
21+
public backButton: BackButton = {
22+
label: '',
23+
routerLink: ['admin', 'api-key'],
24+
};
25+
public title = '';
26+
public submitButton = '';
27+
public errorMessage: string;
28+
public errorMessages: string[];
29+
public errorFields: string[];
30+
public formFailedSubmit = false;
31+
public permissions: PermissionResponse[] = [];
32+
private organizationId: number;
33+
private id: number;
34+
35+
constructor(
36+
private translate: TranslateService,
37+
private route: ActivatedRoute,
38+
private location: Location,
39+
private apiKeyService: ApiKeyService,
40+
private permissionService: PermissionService,
41+
private errorMessageService: ErrorMessageService,
42+
private sharedVariableService: SharedVariableService
43+
) {}
44+
45+
ngOnInit(): void {
46+
this.getPermissions();
47+
this.translate.use('da');
48+
this.translate
49+
.get(['NAV.API-KEY', 'FORM.EDIT-API-KEY', 'API-KEY.EDIT.SAVE'])
50+
.subscribe((translations) => {
51+
this.backButton.label = translations['NAV.API-KEY'];
52+
this.title = translations['FORM.EDIT-API-KEY'];
53+
this.submitButton = translations['API-KEY.EDIT.SAVE'];
54+
});
55+
56+
this.id = +this.route.snapshot.paramMap.get('api-key-id');
57+
58+
if (this.id > 0) {
59+
this.getApiKey(this.id);
60+
}
61+
this.organizationId = this.sharedVariableService.getSelectedOrganisationId();
62+
}
63+
64+
private getPermissions() {
65+
this.permissionService
66+
.getPermissions(
67+
undefined,
68+
undefined,
69+
undefined,
70+
undefined,
71+
undefined,
72+
this.organizationId
73+
)
74+
.subscribe(
75+
(permissionsResponse) => {
76+
this.permissions = permissionsResponse.data.filter(
77+
(x) => x.organization?.id === this.organizationId
78+
);
79+
},
80+
(error: HttpErrorResponse) => {
81+
this.showError(error);
82+
}
83+
);
84+
}
85+
86+
private getApiKey(id: number) {
87+
this.apiKeyService.get(id).subscribe((key) => {
88+
this.apiKeyRequest.id = key.id;
89+
this.apiKeyRequest.name = key.name;
90+
this.apiKeyRequest.permissionIds = key.permissions.map((pm) => pm.id);
91+
});
92+
}
93+
94+
onSubmit(): void {
95+
this.id ? this.update() : this.create();
96+
}
97+
98+
private create(): void {
99+
this.apiKeyService.create(this.apiKeyRequest).subscribe(
100+
() => this.routeBack(),
101+
(err) => this.showError(err)
102+
);
103+
}
104+
105+
private update(): void {
106+
this.apiKeyService.update(this.apiKeyRequest, this.id).subscribe(
107+
() => this.routeBack(),
108+
(err) => this.showError(err)
109+
);
110+
}
111+
112+
public compare(
113+
matOptionValue: number,
114+
ngModelObject: number
115+
): boolean {
116+
return matOptionValue === ngModelObject;
117+
}
118+
119+
showError(err: HttpErrorResponse) {
120+
const result = this.errorMessageService.handleErrorMessageWithFields(err);
121+
this.errorFields = result.errorFields;
122+
this.errorMessages = result.errorMessages;
123+
}
124+
125+
routeBack(): void {
126+
this.location.back();
127+
}
128+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<app-top-bar
2+
[title]="'NAV.API-KEY' | translate"
3+
[ctaLabel]="'API-KEY.CREATE-NEW-API-KEY' | translate"
4+
[ctaRouterLink]="'new-api-key'"
5+
>
6+
</app-top-bar>
7+
<div class="container-fluid">
8+
<div class="row">
9+
<div class="col-12">
10+
<div class="jumbotron--table">
11+
<app-api-key-table
12+
[organisationId]="organisationId"
13+
></app-api-key-table>
14+
</div>
15+
</div>
16+
</div>
17+
</div>

src/app/admin/api-key/api-key-list/api-key-list.component.scss

Whitespace-only changes.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Component, Input, OnInit } from '@angular/core';
2+
import { Title } from '@angular/platform-browser';
3+
import { TranslateService } from '@ngx-translate/core';
4+
import { SharedVariableService } from '@shared/shared-variable/shared-variable.service';
5+
6+
@Component({
7+
selector: 'app-api-key-list',
8+
templateUrl: './api-key-list.component.html',
9+
styleUrls: ['./api-key-list.component.scss'],
10+
})
11+
export class ApiKeyListComponent implements OnInit {
12+
@Input() organisationId: number;
13+
14+
constructor(
15+
public translate: TranslateService,
16+
private titleService: Title,
17+
private globalService: SharedVariableService
18+
) {
19+
translate.use('da');
20+
}
21+
22+
ngOnInit(): void {
23+
this.translate.get(['TITLE.API-KEY']).subscribe((translations) => {
24+
this.titleService.setTitle(translations['TITLE.API-KEY']);
25+
});
26+
this.organisationId = this.globalService.getSelectedOrganisationId();
27+
}
28+
}

0 commit comments

Comments
 (0)