Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
5939159
IOT-1144 add readonly mode for sigfox device type, serviceprofile and…
jeppeej Dec 16, 2020
fba8633
IOT-1012 add help navbar icon with link
jeppeej Dec 16, 2020
f8569e9
IOT-729 add title to main pages.
jeppeej Dec 16, 2020
f9a09cf
IOT-1087 add spinner to all sides with backend paginator
jeppeej Dec 16, 2020
3f109f8
IOT-1167 add title to dashboard
jeppeej Dec 17, 2020
0eb4150
Text da.json corrections
jeppeej Dec 17, 2020
a3f4b8b
IOT-1168 - removed top bar for user with no permissions
jeppeej Dec 17, 2020
76c3780
IOT-1167 - text changes
jeppeej Dec 17, 2020
44bbead
IOT-1169 - add read permission restrictions to downlink and edit sigf…
jeppeej Dec 17, 2020
194a33e
Avoid overflow on frontpage since topbar is now included
VirtualSatai Dec 17, 2020
aa3bdfd
IOT-1039: Only suggest to create organization if current user is glob…
VirtualSatai Dec 15, 2020
8f3e68b
IOT-1094: Add DeviceModelId and seperate LoRaWAN OTAA and ABP CSVs
VirtualSatai Dec 15, 2020
2a44f6f
IOT-1151: Set OpenDataDK checkbox to checked to be remembered
VirtualSatai Dec 16, 2020
755aac8
IOT-1161: Datatarget details page add links to payload decoders and i…
VirtualSatai Dec 16, 2020
8a29614
IOT-1147: Search for users and applications in permissions
VirtualSatai Dec 16, 2020
99ca6cc
IOT-1157: Gateway table pagination client side
VirtualSatai Dec 17, 2020
0bee86b
IOT-1147: Search for email and show email at results
VirtualSatai Dec 17, 2020
a22e656
IOT-1163: Remove excessive vertical spacing in navbar
VirtualSatai Dec 17, 2020
66d58e1
IOT-1172: Avoid sending an empty string as deviceModelId if it was no…
VirtualSatai Dec 17, 2020
26524d5
IOT-1173 - fit to bounds for multiple markers
jeppeej Dec 17, 2020
072fd85
text fix.
jeppeej Dec 18, 2020
153511f
Translate mat-paginator to danish
VirtualSatai Dec 18, 2020
9d4beba
IOT-1174: Set accept terms to true after data target eshare with open…
VirtualSatai Dec 18, 2020
ff4e817
New dashboard + change of color primary
Dec 17, 2020
96d077c
Update internatiolization on dashboard
Dec 18, 2020
1957fbd
IOT-1175 add title tag on organization and permission detail page
jeppeej Dec 18, 2020
d18fecc
Revert changes to navbar
VirtualSatai Dec 18, 2020
77798ee
Spacing around dashboard links
VirtualSatai Dec 18, 2020
400e4a7
Open links on dashboard in new tab
VirtualSatai Dec 18, 2020
aea6f73
IOT-1094: Add example row to csv files
VirtualSatai Dec 18, 2020
8d950fd
Delete margin on component
Dec 18, 2020
22431fe
IOT-1174: Datatarget avoid redirecting if save fails
VirtualSatai Dec 18, 2020
ef2262f
IOT-1176 fixed help click evet for mobile devices.
jeppeej Dec 18, 2020
517ab7d
IOT-1174: Avoid redirecting if an error occurs
VirtualSatai Dec 18, 2020
1a52e25
IOT-1166 hotfix
Dec 18, 2020
6587d8a
Remove SIGFOX from bulk import
VirtualSatai Dec 18, 2020
ece3fdf
Text fix
jeppeej Dec 18, 2020
69779fb
IOT-1178 add padding to map fittobounds
jeppeej Dec 18, 2020
a0acc33
IOT-1163: Use flexbox for spaceing
VirtualSatai Dec 18, 2020
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
4 changes: 3 additions & 1 deletion src/app/admin/admin.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { UserTableComponent } from './users/user-list/user-table/user-table.comp
import { UsersComponent } from './users/users.component';
import { MatSelectModule } from '@angular/material/select';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectSearchModule } from '@shared/components/mat-select-search/mat-select-search.module';

@NgModule({
declarations: [
Expand Down Expand Up @@ -60,6 +61,7 @@ import { MatFormFieldModule } from '@angular/material/form-field';
SharedModule,
MatSelectModule,
MatFormFieldModule,
MatSelectSearchModule,
],
exports: [
UserDetailComponent,
Expand All @@ -79,4 +81,4 @@ import { MatFormFieldModule } from '@angular/material/form-field';
OrganisationListComponent,
],
})
export class AdminModule { }
export class AdminModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { DeleteDialogService } from '@shared/components/delete-dialog/delete-dia
import { DropdownButton } from '@shared/models/dropdown-button.model';
import { ApplicationService } from '@applications/application.service';
import { environment } from '@environments/environment';
import { Title } from '@angular/platform-browser';

@Component({
selector: 'app-organisation-detail',
Expand Down Expand Up @@ -47,7 +48,8 @@ export class OrganisationDetailComponent implements OnInit, OnChanges, OnDestroy
private organisationService: OrganisationService,
private permissionsService: PermissionService,
private deleteDialogService: DeleteDialogService,
private location: Location
private location: Location,
private titleService: Title
) { }

ngOnChanges(changes: SimpleChanges): void {
Expand All @@ -64,10 +66,11 @@ export class OrganisationDetailComponent implements OnInit, OnChanges, OnDestroy
editRouterLink: 'edit-organisation',
isErasable: true,
}
this.translate.get(['NAV.ORGANISATIONS', 'ORGANISATION.DROPDOWN'])
this.translate.get(['NAV.ORGANISATIONS', 'ORGANISATION.DROPDOWN', 'TITLE.ORGANIZATION'])
.subscribe(translations => {
this.backButton.label = translations['NAV.ORGANISATIONS'];
this.dropdownButton.label = translations['ORGANISATION.DROPDOWN'];
this.titleService.setTitle(translations['TITLE.ORGANIZATION'])
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { Sort } from '@shared/models/sort.model';

Expand All @@ -9,9 +10,14 @@ import { Sort } from '@shared/models/sort.model';
})
export class OrganisationListComponent implements OnInit {

constructor(public translate: TranslateService) {
constructor(public translate: TranslateService, private titleService: Title) {
translate.use('da');
}

ngOnInit(): void { }
ngOnInit(): void {
this.translate.get(['TITLE.ORGANIZATION'])
.subscribe(translations => {
this.titleService.setTitle(translations['TITLE.ORGANIZATION']);
});
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<div class="mat-elevation-z8">
<div class="loading-shade" *ngIf="isLoadingResults">
<mat-spinner *ngIf="isLoadingResults"></mat-spinner>
</div>
<table mat-table [dataSource]="data" matSort matSortActive="name" matSortDirection="asc" matSortDisableClear>

<!-- Name Column -->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { Component, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { PermissionService } from '@app/admin/permission/permission.service';
import { Subscription } from 'rxjs';
import { PermissionResponse } from '../permission.model';
import { BackButton } from '@shared/models/back-button.model';
import { QuickActionButton } from '@shared/models/quick-action-button.model';
import { Application } from '@applications/application.model';
import { ApplicationService } from '@applications/application.service';
import { SharedVariableService } from '@shared/shared-variable/shared-variable.service';
import { OrganisationResponse } from '@app/admin/organisation/organisation.model';
import { OrganisationService } from '@app/admin/organisation/organisation.service';
import { UserResponse } from '@app/admin/users/user.model';
import { DropdownButton } from '@shared/models/dropdown-button.model';
import { DeleteDialogService } from '@shared/components/delete-dialog/delete-dialog.service';
import { environment } from '@environments/environment';
import { Title } from '@angular/platform-browser';


@Component({
Expand Down Expand Up @@ -53,6 +49,7 @@ export class PermissionDetailComponent implements OnInit, OnChanges {
private route: ActivatedRoute,
private permissionService: PermissionService,
private router: Router,
private titleService: Title,
private deleteDialogService: DeleteDialogService
) { }

Expand All @@ -67,10 +64,11 @@ export class PermissionDetailComponent implements OnInit, OnChanges {
isErasable: true,
}
}
this.translate.get(['NAV.PERMISSIONS', 'PERMISSION.DETAIL.DROPDOWN'])
this.translate.get(['NAV.PERMISSIONS', 'PERMISSION.DETAIL.DROPDOWN', 'TITLE.PERMISSION'])
.subscribe(translations => {
this.backButton.label = translations['NAV.PERMISSIONS'];
this.dropdownButton.label = translations['PERMISSION.DETAIL.DROPDOWN'];
this.titleService.setTitle(translations['TITLE.PERMISSION']);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,16 @@
</div>

<div class="form-group mt-3 col-12">
<label class="form-label" for="user">{{'PERMISSION.EDIT.USERS' | translate}}</label>
<mat-form-field>
<mat-select
name="users"
[multiple]="true"
#multiSelect
[compareWith]="compare"
[(value)]="permission.userIds">
<mat-option *ngFor="let user of users" [value]="user.id">
{{user.name}} ({{user.email}})
</mat-option>
<label class="form-label" for="user">{{'PERMISSION.EDIT.USERS' | translate}}</label>
<mat-select [formControl]="userMultiCtrl" placeholder="" [multiple]="true" panelClass="overflow-x-hidden"
[(value)]="permission.userIds" name="users" #multiSelect [compareWith]="compare">
<mat-select-search [formControl]="userMultiFilterCtrl"></mat-select-search>
<mat-option *ngFor="let user of filteredUsersMulti | async" [value]="user.id">
{{getTextForUser(user)}}
</mat-option>
</mat-select>
</mat-form-field>
</mat-form-field>
</div>

<div *ngIf="permission.level != 'GlobalAdmin'">
Expand All @@ -61,26 +58,28 @@
</div>
</div>

<div *ngIf="isOrganizationAdministrationPermission()">
<div class="form-group mt-3 col-12">
<div class="form-group mt-3 col-12" *ngIf="isOrganizationApplicationPermission()">
<mat-form-field>
<label class="form-label" for="name">{{'PERMISSION.EDIT.APPS' | translate}}</label>
<div class="col-12">
<select id="applicationIds" name="applicationIds" class="form-control" multiple
[(ngModel)]="permission.applicationIds"
placeholder="'PERMISSION.EDIT.APPS-PLACEHOLDER' | translate">
<option *ngFor="let app of applications" [value]="app.id"
[selected]="isApplicationPartOfPermission(app.id)">
{{app.name}}</option>
</select>
<mat-select [formControl]="applicationMultiCtrl" placeholder="" [multiple]="true"
panelClass="overflow-x-hidden" [(value)]="permission.applicationIds" id="applicationIds"
name="applicationIds" #multiSelect [compareWith]="compare">
<mat-select-search [formControl]="applicationMultiFilterCtrl"></mat-select-search>
<mat-option *ngFor="let app of filteredApplicationsMulti | async" [value]="app.id">
{{app.name}}
</mat-option>
</mat-select>
</div>
</div>
</mat-form-field>
</div>

<div *ngIf="isReadOrWrite()">
<div class="form-group mt-3 col-12">
<label class="form-label" for="name">{{'PERMISSION.EDIT.ADD-APPLICATION-AUTOMATIC' | translate}}</label>
<div class="row">
<mat-slide-toggle [(ngModel)]="permission.automaticallyAddNewApplications" id="automaticallyAddNewApplications" name="automaticallyAddNewApplications">
<mat-slide-toggle [(ngModel)]="permission.automaticallyAddNewApplications"
id="automaticallyAddNewApplications" name="automaticallyAddNewApplications">
{{'PERMISSION.EDIT.ADD-APPLICATION-ON-CREATE' | translate}}</mat-slide-toggle>
</div>
</div>
Expand Down
109 changes: 99 additions & 10 deletions src/app/admin/permission/permission-edit/permission-edit.component.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { HttpErrorResponse } from '@angular/common/http';
import { FormGroup } from '@angular/forms';
import { FormControl, FormGroup } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { Subscription } from 'rxjs';
import { ReplaySubject, Subject, Subscription } from 'rxjs';
import { Location } from '@angular/common';
import { PermissionService } from '../permission.service';
import { PermissionRequest, PermissionType } from '../permission.model';
Expand All @@ -15,13 +15,14 @@ import { ApplicationService } from '@applications/application.service';
import { Application } from '@applications/application.model';
import { BackButton } from '@shared/models/back-button.model';
import { ErrorMessageService } from '@shared/error-message.service';
import { takeUntil } from 'rxjs/operators';

@Component({
selector: 'app-permission-edit',
templateUrl: './permission-edit.component.html',
styleUrls: ['./permission-edit.component.scss'],
})
export class PermissionEditComponent implements OnInit {
export class PermissionEditComponent implements OnInit, OnDestroy {
permission = new PermissionRequest();
public organisations: OrganisationResponse[];
public users: UserResponse[];
Expand All @@ -31,7 +32,10 @@ export class PermissionEditComponent implements OnInit {
public errorFields: string[];
public formFailedSubmit = false;
public form: FormGroup;
public backButton: BackButton = { label: '', routerLink: ['admin','permissions'] };
public backButton: BackButton = {
label: '',
routerLink: ['admin', 'permissions'],
};
public title = '';
public submitButton = '';
public isEditMode = false;
Expand All @@ -41,6 +45,18 @@ export class PermissionEditComponent implements OnInit {
userSubscription: Subscription;
applicationSubscription: Subscription;

public userMultiCtrl: FormControl = new FormControl();
public userMultiFilterCtrl: FormControl = new FormControl();
public filteredUsersMulti: ReplaySubject<UserResponse[]> = new ReplaySubject<
UserResponse[]
>(1);

public applicationMultiCtrl: FormControl = new FormControl();
public applicationMultiFilterCtrl: FormControl = new FormControl();
public filteredApplicationsMulti: ReplaySubject<
Application[]
> = new ReplaySubject<Application[]>(1);

constructor(
private translate: TranslateService,
private route: ActivatedRoute,
Expand Down Expand Up @@ -69,6 +85,64 @@ export class PermissionEditComponent implements OnInit {
this.isEditMode = true;
this.setBackButton();
}

this.userMultiFilterCtrl.valueChanges
.pipe(takeUntil(this._onDestroy))
.subscribe(() => {
this.filterUsersMulti();
});

this.applicationMultiFilterCtrl.valueChanges
.pipe(takeUntil(this._onDestroy))
.subscribe(() => {
this.filterApplicationsMulti();
});
}

private filterApplicationsMulti() {
if (!this.applications) {
return;
}
// get the search keyword
let search = this.applicationMultiFilterCtrl.value;
if (!search) {
this.filteredApplicationsMulti.next(this.applications.slice());
return;
} else {
search = search.toLowerCase();
}
// filter the banks
this.filteredApplicationsMulti.next(
this.applications.filter(
(app) => app.name.toLowerCase().indexOf(search) > -1
)
);
}

private filterUsersMulti() {
if (!this.users) {
return;
}
// get the search keyword
let search = this.userMultiFilterCtrl?.value?.trim();
if (!search) {
this.filteredUsersMulti.next(this.users.slice());
return;
} else {
search = search.toLowerCase();
}
const filtered = this.users.filter((user) => {
return (
user.name.toLocaleLowerCase().indexOf(search) > -1 ||
user?.email?.toLocaleLowerCase()?.indexOf(search) > -1
);
});
// filter the banks
this.filteredUsersMulti.next(filtered);
}

getTextForUser(user: UserResponse): string {
return `${user.name}` + (user.email ? ` (${user.email})` : ``);
}

private setBackButton() {
Expand All @@ -92,6 +166,7 @@ export class PermissionEditComponent implements OnInit {
this.userSubscription = this.userService.getMultiple().subscribe(
(users) => {
this.users = users.data;
this.filteredUsersMulti.next(this.users.slice());
},
(error: HttpErrorResponse) => {
this.showError(error);
Expand All @@ -113,6 +188,7 @@ export class PermissionEditComponent implements OnInit {
.subscribe(
(res) => {
this.applications = res.data;
this.filteredApplicationsMulti.next(this.applications.slice());
},
(error: HttpErrorResponse) => {
this.showError(error);
Expand All @@ -127,7 +203,9 @@ export class PermissionEditComponent implements OnInit {
this.permission.name = response.name;
this.permission.level = response.type;
this.permission.userIds = response.users.map((x) => x.id);
this.permission.automaticallyAddNewApplications = response.automaticallyAddNewApplications;
this.userMultiCtrl.setValue(this.permission.userIds);
this.permission.automaticallyAddNewApplications =
response.automaticallyAddNewApplications;

if (response.type !== PermissionType.GlobalAdmin) {
this.permission.organizationId = response?.organization?.id;
Expand All @@ -141,6 +219,7 @@ export class PermissionEditComponent implements OnInit {
this.permission.applicationIds = response.applications.map(
(x) => x.id
);
this.applicationMultiCtrl.setValue(this.permission.applicationIds);
}
},
(error: HttpErrorResponse) => {
Expand Down Expand Up @@ -199,17 +278,19 @@ export class PermissionEditComponent implements OnInit {
}
}

isOrganizationAdministrationPermission() {
isOrganizationApplicationPermission() {
return (
this.permission.level ==
PermissionType.OrganizationApplicationPermissions ||
this.permission.level == PermissionType.Write ||
this.permission.level == PermissionType.Read
this.isReadOrWrite()
);
}

isReadOrWrite(): boolean {
return this.permission.level === PermissionType.Read || this.permission.level === PermissionType.Write
return (
this.permission.level === PermissionType.Read ||
this.permission.level === PermissionType.Write
);
}

onSubmit(): void {
Expand All @@ -229,4 +310,12 @@ export class PermissionEditComponent implements OnInit {
routeBack(): void {
this.location.back();
}

/** Subject that emits when the component has been destroyed. */
private _onDestroy = new Subject<void>();

ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<app-top-bar [sort]="sort" [pageLimit]="pageLimit" [title]="'NAV.PERMISSIONS' | translate"
<app-top-bar [pageLimit]="pageLimit" [title]="'NAV.PERMISSIONS' | translate"
[ctaLabel]="'FORM.CREATE-NEW-PERMISSION' | translate" [ctaRouterLink]="'new-permission'"></app-top-bar>
<div class="container-fluid">
<div class="row">
Expand Down
Loading