From d1bb87087d63000180a37b5d54d4043ce5e0b6bb Mon Sep 17 00:00:00 2001 From: "stefania.martziou" <19352921+smartziou@users.noreply.github.com> Date: Wed, 14 Jul 2021 12:16:40 +0000 Subject: [PATCH] Finished the multiuser access functionality --- package-lock.json | 1 + src/app/app.component.ts | 2 +- src/app/domain/typeScriptClasses.ts | 7 + src/app/pages/join/join.component.ts | 2 +- src/app/pages/repository/repository.module.ts | 36 +++-- .../update/sources-update-repo.component.html | 46 +----- .../update/sources-update-repo.component.ts | 2 +- .../update/update-repo-admins.component.html | 129 +++++++++++++++ .../update/update-repo-admins.component.ts | 147 ++++++++++++++++++ src/app/services/repository.service.ts | 30 +++- .../confirmation-dialog.component.html | 1 + .../confirmation-dialog.component.ts | 5 + .../repository-tiles.component.ts | 2 +- src/app/shared/sidemenu/sidemenu.component.ts | 2 +- 14 files changed, 339 insertions(+), 73 deletions(-) create mode 100644 src/app/pages/repository/update/update-repo-admins.component.html create mode 100644 src/app/pages/repository/update/update-repo-admins.component.ts diff --git a/package-lock.json b/package-lock.json index ccdaa263d..ea2e9a291 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4516,6 +4516,7 @@ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", "dev": true, + "hasInstallScript": true, "optional": true, "os": [ "darwin" diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 5276db78d..10c8de363 100755 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -72,7 +72,7 @@ export class AppComponent implements OnInit { } getReposOfUser(): void { - this.repositoryService.getRepositoriesOfUser() + this.repositoryService.getRepositoriesSnippetsOfUser() .subscribe( repos => { this.reposOfUser = repos; }, error => { console.log(error); }, diff --git a/src/app/domain/typeScriptClasses.ts b/src/app/domain/typeScriptClasses.ts index 60dbb8142..3cd6aac83 100755 --- a/src/app/domain/typeScriptClasses.ts +++ b/src/app/domain/typeScriptClasses.ts @@ -716,3 +716,10 @@ export class CollectionMonitorSummary { aggregationDetails: AggregationDetails[]; lastIndexedVersion: AggregationDetails; } + +export class User { + sub: string; + firstName: string; + lastName: string; + email: string; +} diff --git a/src/app/pages/join/join.component.ts b/src/app/pages/join/join.component.ts index e3c45fc6d..89bc11852 100644 --- a/src/app/pages/join/join.component.ts +++ b/src/app/pages/join/join.component.ts @@ -41,7 +41,7 @@ export class JoinComponent implements OnInit { } getReposOfUser(): void { - this.repositoryService.getRepositoriesOfUser() + this.repositoryService.getRepositoriesSnippetsOfUser() .subscribe( repos => { this.repositoriesOfUser = repos; diff --git a/src/app/pages/repository/repository.module.ts b/src/app/pages/repository/repository.module.ts index 6379f6c00..a8f0fe26f 100644 --- a/src/app/pages/repository/repository.module.ts +++ b/src/app/pages/repository/repository.module.ts @@ -3,23 +3,24 @@ import { CommonModule } from '@angular/common'; import { TabsModule } from 'ngx-bootstrap'; import { ReusableComponentsModule } from '../../shared/reusablecomponents/reusable-components.module'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { RepositoryComponent } from "./repository.component"; -import { RepositoryRoutingModule } from "./repository-routing.module"; -import { DashboardComponent } from "./dashboard/dashboard.component"; -import {AuthenticationInterceptor} from "../../services/authentication-interceptor"; -import {UsagestatsService} from "../../services/usagestats.service"; -import {RepositoryService} from "../../services/repository.service"; -import {AuthGuardService} from "../../services/auth-guard.service"; -import {ValidatorService} from "../../services/validator.service"; -import {AuthenticationService} from "../../services/authentication.service"; -import {MonitorService} from "../../services/monitor.service"; -import {PiwikService} from "../../services/piwik.service"; -import {StatisticsService} from "../../services/statistics.service"; -import {BrokerService} from "../../services/broker.service"; -import {DashboardService} from "../../services/dashboard.service"; -import { SharedService } from "../../services/shared.service"; -import { SourcesUpdateRepoComponent } from "./update/sources-update-repo.component"; -import {SourcesModule} from '../sources/sources.module'; +import { RepositoryComponent } from './repository.component'; +import { RepositoryRoutingModule } from './repository-routing.module'; +import { DashboardComponent } from './dashboard/dashboard.component'; +import {AuthenticationInterceptor} from '../../services/authentication-interceptor'; +import {UsagestatsService} from '../../services/usagestats.service'; +import {RepositoryService} from '../../services/repository.service'; +import {AuthGuardService} from '../../services/auth-guard.service'; +import {ValidatorService} from '../../services/validator.service'; +import {AuthenticationService} from '../../services/authentication.service'; +import {MonitorService} from '../../services/monitor.service'; +import {PiwikService} from '../../services/piwik.service'; +import {StatisticsService} from '../../services/statistics.service'; +import {BrokerService} from '../../services/broker.service'; +import {DashboardService} from '../../services/dashboard.service'; +import { SharedService } from '../../services/shared.service'; +import { SourcesUpdateRepoComponent } from './update/sources-update-repo.component'; +import { SourcesModule } from '../sources/sources.module'; +import { UpdateRepoAdminsComponent } from './update/update-repo-admins.component'; @NgModule ({ imports: [ @@ -36,6 +37,7 @@ import {SourcesModule} from '../sources/sources.module'; RepositoryComponent, DashboardComponent, SourcesUpdateRepoComponent, + UpdateRepoAdminsComponent // SourcesComponent, // SourcesRegisterComponent, // SourcesUpdateComponent, diff --git a/src/app/pages/repository/update/sources-update-repo.component.html b/src/app/pages/repository/update/sources-update-repo.component.html index 2a99591ba..d0ff3c82f 100755 --- a/src/app/pages/repository/update/sources-update-repo.component.html +++ b/src/app/pages/repository/update/sources-update-repo.component.html @@ -84,51 +84,7 @@
  • -
    -
    This is a mock representation of the update admins functionality coming soon..
    - -
    -
    -
    -
    - Email: - admin1@gmail.com -
    -
    - -
    -
    -
    -
    - Email: - admin2@gmail.com -
    -
    - -
    -
    -
    +
  • diff --git a/src/app/pages/repository/update/sources-update-repo.component.ts b/src/app/pages/repository/update/sources-update-repo.component.ts index b4f81cd5d..2e5cbff83 100755 --- a/src/app/pages/repository/update/sources-update-repo.component.ts +++ b/src/app/pages/repository/update/sources-update-repo.component.ts @@ -8,7 +8,7 @@ import { DatasourceUpdateFormComponent } from '../../../shared/reusablecomponent import { ConfirmationDialogComponent } from '../../../shared/reusablecomponents/confirmation-dialog.component'; import { AuthenticationService } from '../../../services/authentication.service'; import { DatasourceNewInterfaceFormComponent } from '../../../shared/reusablecomponents/sources-forms/datasource-new-interface-form.component'; -import {SharedService} from "../../../services/shared.service"; +import { SharedService } from '../../../services/shared.service'; @Component ({ selector: 'sources-update-repo', diff --git a/src/app/pages/repository/update/update-repo-admins.component.html b/src/app/pages/repository/update/update-repo-admins.component.html new file mode 100644 index 000000000..feff0f0bd --- /dev/null +++ b/src/app/pages/repository/update/update-repo-admins.component.html @@ -0,0 +1,129 @@ +
    +
    Update the users who can access the dashboard to manage the datasource.
    + +
    {{errorMessage}}
    +
    +
    + {{ loadingMessage }} +
    +
    +
    + +
    + + + +
    +
    +
    +
    + Email: + {{repoAdmin.email}} +
    +
    + +
    +
    + +
    + +
    + + + +
    {{modalErrorMessage}}
    + +
    +
    + {{ modalLoadingMessage }} +
    +
    +
    + + + + + + + +
    +
    Are you sure you want to remove this user admin?
    +
    +      
    +        {{selectedAdminForDelete.firstName}} {{selectedAdminForDelete.lastName}}
    +      
    +      {{ selectedAdminForDelete.email }}
    +    
    +
    + +
    + + + + +
    {{modalErrorMessage}}
    + +
    +
    + {{ modalLoadingMessage }} +
    +
    +
    + +
    Add the email address of the new user admin. Make sure the user already has an OpenAIRE account with this email address.
    +
    +
    + +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/pages/repository/update/update-repo-admins.component.ts b/src/app/pages/repository/update/update-repo-admins.component.ts new file mode 100644 index 000000000..7adbae643 --- /dev/null +++ b/src/app/pages/repository/update/update-repo-admins.component.ts @@ -0,0 +1,147 @@ +import {Component, Input, OnChanges, SimpleChanges, ViewChild} from '@angular/core'; +import { Repository, User } from '../../../domain/typeScriptClasses'; +import { RepositoryService } from '../../../services/repository.service'; +import {loadingRepoMessage} from '../../../domain/shared-messages'; +import {ConfirmationDialogComponent} from '../../../shared/reusablecomponents/confirmation-dialog.component'; +import {FormControl} from '@angular/forms'; + +declare var UIkit: any; + +@Component ({ + selector: 'app-update-repo-admins', + templateUrl: 'update-repo-admins.component.html', +}) + +export class UpdateRepoAdminsComponent implements OnChanges { + + @Input() repo: Repository; + + loadingMessage: string; + errorMessage: string; + + repoAdmins: User[]; + + selectedAdminForDelete: User; + + isDeleteModalShown: boolean; + @ViewChild('deleteRepositoryAdminModal') + public deleteRepositoryAdminModal: ConfirmationDialogComponent; + + isAddModalShown: boolean; + @ViewChild('addRepositoryAdminModal') + public addRepositoryAdminModal: ConfirmationDialogComponent; + + modalErrorMessage: string; + modalLoadingMessage: string; + + emailControl = new FormControl(); + + constructor (private repoService: RepositoryService) { } + + ngOnChanges(changes: SimpleChanges): void { + this.getRepositoryAdmins(); + } + + getRepositoryAdmins() { + + this.loadingMessage = 'Retrieving repository\'s admins...'; + + this.repoService.getRepositoryAdmins(this.repo.id).subscribe( + users => { + this.repoAdmins = users; + }, + error => { + console.log(error); + this.loadingMessage = ''; + this.errorMessage = 'Error retrieving the repository\'s admins'; + }, + () => { + this.loadingMessage = ''; + } + ); + } + + showDeletionModal(repoAdmin: User) { + + this.errorMessage = ''; + this.loadingMessage = ''; + + this.selectedAdminForDelete = repoAdmin; + if (this.selectedAdminForDelete) { + this.deleteRepositoryAdminModal.showModal(); + // UIkit.modal('#deletionModal').show(); + } + } + + closeDeletionModal() { + this.selectedAdminForDelete = null; + this.deleteRepositoryAdminModal.hideModal(); + // UIkit.modal('#deletionModal').hide(); + } + + deleteRepoAdmin(event: any) { + console.log('deleting: ', this.selectedAdminForDelete.email); + + // this.deleteRepositoryAdminModal.hideModal(); + this.modalLoadingMessage = 'Deleting admin...'; + + this.repoService.deleteRepositoryAdmin(this.repo.id, this.selectedAdminForDelete.email).subscribe( + res => { + this.selectedAdminForDelete = null; + this.deleteRepositoryAdminModal.hideModal(); + this.getRepositoryAdmins(); + }, + error => { + console.log('Error deleting repository\'s admins', error); + this.modalLoadingMessage = ''; + this.modalErrorMessage = 'Error deleting admin'; + }, + () => { + this.modalLoadingMessage = ''; + // this.deleteRepositoryAdminModal.hideModal(); + } + ); + + } + + showAddRepoAdminModal() { + + this.emailControl.reset(); + + this.modalErrorMessage = ''; + this.modalLoadingMessage = ''; + + this.addRepositoryAdminModal.showModal(); + // UIkit.modal('#addAdminModal').show(); + } + + addRepositoryAdmin() { + + this.modalLoadingMessage = 'Adding repository admin'; + + console.log('Adding repository admin..', this.emailControl.value); + + this.repoService.addRepositoryAdmin(this.repo.id, this.emailControl.value).subscribe( + res => { + this.addRepositoryAdminModal.hideModal(); + this.getRepositoryAdmins(); + }, error => { + console.log('Error adding repository admin', error); + this.modalLoadingMessage = ''; + if(error.status === 404) { + this.modalErrorMessage = 'This email address is not associated with an OpenAIRE user account.\n' + + 'Please make sure the user has an OpenAIRE account and then try again.'; + } else { + this.modalErrorMessage = 'Error deleting the user admin, please try again. If the error persists, ' + + 'please contact helpdesk@openaire.eu'; + } + }, + () => { + this.modalLoadingMessage = ''; + } + ); + + // UIkit.modal('#addAdminModal').hide(); + } + +} diff --git a/src/app/services/repository.service.ts b/src/app/services/repository.service.ts index 2c649035e..6a8b67f5a 100755 --- a/src/app/services/repository.service.ts +++ b/src/app/services/repository.service.ts @@ -12,7 +12,7 @@ import { RepositoryInterface, RepositorySnippet, RepositorySummaryInfo, Timezone, - Typology + Typology, User } from '../domain/typeScriptClasses'; import { Observable, of } from 'rxjs'; import { timezones } from '../domain/timezones'; @@ -28,7 +28,7 @@ const headerOptions = { @Injectable () export class RepositoryService { - private apiUrl = environment.API_ENDPOINT + '/repository/'; + private apiUrl = environment.API_ENDPOINT + '/repositories/'; private dashboardAPIUrl = environment.API_ENDPOINT + '/dashboard/'; constructor(private httpClient: HttpClient) { } @@ -91,15 +91,15 @@ export class RepositoryService { return this.httpClient.get(url, headerOptions); } - getRepositoriesOfUser(): Observable { - const url = `${this.apiUrl}getRepositoriesOfUser/0/100`; + getRepositoriesSnippetsOfUser(): Observable { + const url = `${this.apiUrl}snippets/user`; console.log(`knocking on: ${url}`); return this.httpClient.get(url, headerOptions); } getRepositoryById(id: string): Observable { - const url = `${this.apiUrl}getRepositoryById/${id}`; + const url = `${this.apiUrl}getRepositoryById/${id}`; console.log(`knocking on: ${url}`); return this.httpClient.get(url, headerOptions); } @@ -144,7 +144,7 @@ export class RepositoryService { } getCountries(): Observable { - const url = `${this.apiUrl}getCountries`; + const url = `${this.apiUrl}countries`; console.log(`knocking on: ${url}`); return this.httpClient.get(url, headerOptions); } @@ -193,4 +193,22 @@ export class RepositoryService { console.log(`knocking on: ${url}`); return this.httpClient.get(url, headerOptions); } + + getRepositoryAdmins(repoId: string): Observable { + const url = `${this.apiUrl}${repoId}/admins`; + console.log(`knocking on: ${url}`); + return this.httpClient.get(url, headerOptions); + } + + deleteRepositoryAdmin(repoId: string, repoAdminEmail: string) { + const url = `${this.apiUrl}${repoId}/admins/${repoAdminEmail}`; + console.log(`knocking on: ${url}`); + + return this.httpClient.delete(url, headerOptions); + } + + addRepositoryAdmin(repoId: string, repoAdminEmail: string) { + const url = `${this.apiUrl}${repoId}/admins`; + return this.httpClient.post(url, repoAdminEmail, headerOptions); + } } diff --git a/src/app/shared/reusablecomponents/confirmation-dialog.component.html b/src/app/shared/reusablecomponents/confirmation-dialog.component.html index cb6903103..de14ddbbc 100755 --- a/src/app/shared/reusablecomponents/confirmation-dialog.component.html +++ b/src/app/shared/reusablecomponents/confirmation-dialog.component.html @@ -31,6 +31,7 @@
    diff --git a/src/app/shared/reusablecomponents/confirmation-dialog.component.ts b/src/app/shared/reusablecomponents/confirmation-dialog.component.ts index c2e43cc28..33ff832ad 100755 --- a/src/app/shared/reusablecomponents/confirmation-dialog.component.ts +++ b/src/app/shared/reusablecomponents/confirmation-dialog.component.ts @@ -19,6 +19,7 @@ export class ConfirmationDialogComponent { @Input() public title: string; @Input() public confirmActionButton: string; + @Input() public confirmButNotCloseButton: string; @Input() public hideModalButton: string = 'Cancel'; @@ -50,4 +51,8 @@ export class ConfirmationDialogComponent { // this.hideModal(); } } + + public confirmedButNotCloseAction() { + this.emitObject.emit(this._ids); + } } diff --git a/src/app/shared/reusablecomponents/repository-tiles.component.ts b/src/app/shared/reusablecomponents/repository-tiles.component.ts index 261c549bc..4d46ba0cb 100755 --- a/src/app/shared/reusablecomponents/repository-tiles.component.ts +++ b/src/app/shared/reusablecomponents/repository-tiles.component.ts @@ -30,7 +30,7 @@ export class RepositoryTilesComponent implements OnInit { getReposOfUser(): void { this.loadingMessage = loadingReposMessage; - this.repoService.getRepositoriesOfUser() + this.repoService.getRepositoriesSnippetsOfUser() .subscribe( repos => this.reposOfUser = repos.sort( function(a, b) { if (a.officialname < b.officialname) { diff --git a/src/app/shared/sidemenu/sidemenu.component.ts b/src/app/shared/sidemenu/sidemenu.component.ts index 122c4b9b1..1864d48b4 100644 --- a/src/app/shared/sidemenu/sidemenu.component.ts +++ b/src/app/shared/sidemenu/sidemenu.component.ts @@ -154,7 +154,7 @@ export class SideMenuComponent implements OnInit { } getReposOfUser(): void { - this.repositoryService.getRepositoriesOfUser() + this.repositoryService.getRepositoriesSnippetsOfUser() .subscribe( repos => { this.reposOfUser = repos;