Resolved Connect-Admin release 25th May 2023 #1

This commit is contained in:
Konstantinos Triantafyllou 2023-05-25 17:37:38 +03:00
commit f98a3e9550
41 changed files with 1088 additions and 816 deletions

View File

@ -39,7 +39,7 @@
"sass-loader": "7.3.1", "sass-loader": "7.3.1",
"ts-md5": "^1.2.0", "ts-md5": "^1.2.0",
"tslib": "^2.0.0", "tslib": "^2.0.0",
"uikit": "3.12.0", "uikit": "3.13.10",
"zone.js": "~0.11.4" "zone.js": "~0.11.4"
}, },
"devDependencies": { "devDependencies": {
@ -51,7 +51,7 @@
"@types/jasmine": "~3.6.0", "@types/jasmine": "~3.6.0",
"@types/jasminewd2": "~2.0.3", "@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1", "@types/node": "^12.11.1",
"@types/ckeditor": "^4.9.10", "@types/ckeditor": "^4.9.10",
"codelyzer": "^6.0.0", "codelyzer": "^6.0.0",
"jasmine-core": "~3.8.0", "jasmine-core": "~3.8.0",
"jasmine-spec-reporter": "~5.0.0", "jasmine-spec-reporter": "~5.0.0",
@ -64,4 +64,4 @@
"ts-node": "~7.0.0", "ts-node": "~7.0.0",
"typescript": "~4.6.4" "typescript": "~4.6.4"
} }
} }

View File

@ -2,12 +2,13 @@
<loading [full]="true"></loading> <loading [full]="true"></loading>
</div> </div>
<div *ngIf="loading == false"> <div *ngIf="loading == false">
<div class="sidebar_main_swipe" [class.sidebar_main_active]="open && hasSidebar" [class.sidebar_mini]="!open && hasSidebar"> <div class="sidebar_main_swipe" [class.sidebar_main_active]="open && hasSidebar" [class.sidebar_mini]="!open && hasSidebar"
[class.sidebar_hover]="hover">
<div id="modal-container"></div> <div id="modal-container"></div>
<navbar *ngIf="hasHeader" portal="connect-admin" [header]="menuHeader" [communityId]="community ? community.communityId : null" <navbar *ngIf="hasHeader" portal="connect-admin" [header]="menuHeader" [communityId]="community ? community.communityId : null"
[userMenuItems]=userMenuItems [menuItems]="menuItems" [user]="user" [offCanvasFlip]="true"></navbar> [userMenuItems]=userMenuItems [menuItems]="menuItems" [user]="user"></navbar>
<div> <div>
<dashboard-sidebar *ngIf="hasSidebar" [items]="sideBarItems" [specialMenuItem]="specialSideBarMenuItem"></dashboard-sidebar> <dashboard-sidebar *ngIf="hasSidebar" [items]="sideBarItems" [backItem]="backItem"></dashboard-sidebar>
<main> <main>
<router-outlet></router-outlet> <router-outlet></router-outlet>
</main> </main>

View File

@ -32,7 +32,7 @@ export class AppComponent implements OnInit {
hasAdminMenu: boolean = false; hasAdminMenu: boolean = false;
isFrontPage: boolean = false; isFrontPage: boolean = false;
sideBarItems: MenuItem[] = []; sideBarItems: MenuItem[] = [];
specialSideBarMenuItem: MenuItem = null; backItem: MenuItem = null;
menuItems: MenuItem[] = []; menuItems: MenuItem[] = [];
menuHeader: Header = { menuHeader: Header = {
route: "/", route: "/",
@ -179,6 +179,10 @@ export class AppComponent implements OnInit {
return this.layoutService.open; return this.layoutService.open;
} }
public get hover() {
return this.layoutService.hover;
}
private buildMenu() { private buildMenu() {
this.userMenuItems = []; this.userMenuItems = [];
this.sideBarItems = []; this.sideBarItems = [];
@ -211,14 +215,26 @@ export class AppComponent implements OnInit {
position: 'left', position: 'left',
badge: true badge: true
}; };
this.sideBarItems.push(new MenuItem("community", "Community Info", "", "/" + this.community.communityId, false, [], [], {}, {name: 'badge'}, null, null, "/" + this.community.communityId + "/info")); let communityInfo = new MenuItem("community", "Community Info", "", "/" + this.community.communityId, false, [], [], {}, {name: 'badge'}, null, null, "/" + this.community.communityId + "/info");
communityInfo.items = [
new MenuItem("profile", "Profile", "", "/" + this.community.communityId + "/info/profile", false, [], [], {}, null, null, null, "/" + this.community.communityId + "/info/profile"),
new MenuItem("organizations", "Organizations", "", "/" + this.community.communityId + "/info/organizations", false, [], [], {}, null, null, null, "/" + this.community.communityId + "/info/organizations"),
new MenuItem("projects", OpenaireEntities.PROJECTS, "", "/" + this.community.communityId + "/info/projects", false, [], [], {}, null, null, null, "/" + this.community.communityId + "/info/projects"),
new MenuItem("content-providers", OpenaireEntities.DATASOURCES, "", "/" + this.community.communityId + "/info/content-providers", false, [], [], {}, null, null, null, "/" + this.community.communityId + "/info/content-providers"),
new MenuItem("zenodo-communities", "Zenodo Communities ", "", "/" + this.community.communityId + "/info/zenodo-communities", false, [], [], {}, null, null, null, "/" + this.community.communityId + "/info/zenodo-communities"),
new MenuItem("advanced-criteria", "Advanced Criteria", "", "/" + this.community.communityId + "/info/advanced-criteria", false, [], [], {}, null, null, null, "/" + this.community.communityId + "/info/advanced-criteria")
]
if(this.community.type === 'community') {
communityInfo.items.splice(4, 0, new MenuItem("subjects", "Subjects", "", "/" + this.community.communityId + "/info/subjects", false, [], [], {}, null, null, null, "/" + this.community.communityId + "/info/subjects"))
}
this.sideBarItems.push(communityInfo);
this.sideBarItems.push(new MenuItem("users", "Users", "", "/" + this.community.communityId + "/users", false, [], [], {}, {name: 'group'}, null, null, "/" + this.community.communityId + "/users")); this.sideBarItems.push(new MenuItem("users", "Users", "", "/" + this.community.communityId + "/users", false, [], [], {}, {name: 'group'}, null, null, "/" + this.community.communityId + "/users"));
this.sideBarItems.push(new MenuItem("admin-tools", "Pages & Menus", "", "/" + this.community.communityId + "/admin-tools/pages", false, [], [], {}, {name: 'description'}, null, null, "/" + this.community.communityId + "/admin-tools")); this.sideBarItems.push(new MenuItem("admin-tools", "Pages & Menus", "", "/" + this.community.communityId + "/admin-tools/pages", false, [], [], {}, {name: 'description'}, null, null, "/" + this.community.communityId + "/admin-tools"));
this.sideBarItems.push(new MenuItem("customization", "Customization", "", "/" + this.community.communityId + "/customize-layout", false, [], [], {}, {name: 'brush'})); this.sideBarItems.push(new MenuItem("customization", "Customization", "", "/" + this.community.communityId + "/customize-layout", false, [], [], {}, {name: 'brush'}));
if (this.community.type === 'ri') { if (this.community.type === 'ri') {
this.sideBarItems.push(new MenuItem("mining", "Mining", "", "/" + this.community.communityId + "/mining/manage-profiles", false, [], [], {}, {svg: mining.data}, null, null, "/" + this.community.communityId + "/mining")); this.sideBarItems.push(new MenuItem("mining", "Mining", "", "/" + this.community.communityId + "/mining/manage-profiles", false, [], [], {}, {svg: mining.data}, null, null, "/" + this.community.communityId + "/mining"));
} }
this.specialSideBarMenuItem = new MenuItem("back", "Manage communities", "", "/", false, [], null, {}, {name: 'search', class: 'uk-text-secondary'}); this.backItem = new MenuItem("back", "Manage Communities", "", "/", false, [], null, {}, {name: 'west'});
this.menuItems = []; this.menuItems = [];
this.menuItems.push(new MenuItem("home", "Home", this.menuItems.push(new MenuItem("home", "Home",
@ -306,7 +322,7 @@ export class AppComponent implements OnInit {
this.sideBarItems.push(new MenuItem("connect", "Connect Options", "", "/connect/admin-tools/pages", false, [], [], {}, {name: 'settings'}, null, null, '/connect/admin-tools')); this.sideBarItems.push(new MenuItem("connect", "Connect Options", "", "/connect/admin-tools/pages", false, [], [], {}, {name: 'settings'}, null, null, '/connect/admin-tools'));
this.sideBarItems.push(new MenuItem("explore", "Explore Options", "", "/openaire/admin-tools/pages", false, [], [], {}, {name: 'settings'}, null, null, '/openaire/admin-tools')); this.sideBarItems.push(new MenuItem("explore", "Explore Options", "", "/openaire/admin-tools/pages", false, [], [], {}, {name: 'settings'}, null, null, '/openaire/admin-tools'));
} }
this.specialSideBarMenuItem = null; this.backItem = null;
} }
this.hasSidebar = this.hasSidebar && this.sideBarItems.length > 1; this.hasSidebar = this.hasSidebar && this.sideBarItems.length > 1;
} }

@ -1 +1 @@
Subproject commit faa57d99d193f6904c6a57363718d3269c843c13 Subproject commit d4103354aa0254475df4aa29382999bc2f25bf29

View File

@ -0,0 +1,120 @@
import {ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild} from "@angular/core";
import {CommunityService} from "../../openaireLibrary/connect/community/community.service";
import {AdvancedCriteriaService} from "./advanced-criteria.service";
import {Subscription} from "rxjs";
import {SelectionCriteria} from "../../openaireLibrary/utils/entities/contentProvider";
import {
FullScreenModalComponent
} from "../../openaireLibrary/utils/modal/full-screen-modal/full-screen-modal.component";
import {NotificationHandler} from "../../openaireLibrary/utils/notification-handler";
import {CriteriaComponent} from "../content-providers/criteria/criteria.component";
import {CriteriaUtils} from "../content-providers/criteria-utils";
import {CommunityInfo} from "../../openaireLibrary/connect/community/communityInfo";
@Component({
selector: 'advanced-criteria',
template: `
<div page-content>
<div *ngIf="selectionCriteria" actions>
<div class="uk-section-xsmall uk-margin-top">
<div class="uk-flex uk-flex-right@m uk-flex-center">
<button *ngIf="selectionCriteria.criteria.length === 0" (click)="openCriteria()" class="uk-button uk-button-default uk-flex uk-flex-middle">
<icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left">Add Criteria</span>
</button>
<button *ngIf="selectionCriteria.criteria.length > 0" (click)="openCriteria()" class="uk-button uk-button-default uk-flex uk-flex-middle">
<icon name="edit" [flex]="true"></icon>
<span class="uk-margin-small-left">Edit Criteria</span>
</button>
</div>
</div>
</div>
<div inner>
<div *ngIf="loading" class="uk-position-center">
<loading></loading>
</div>
<div *ngIf="!loading">
<div *ngIf="selectionCriteria?.criteria?.length > 0" class="uk-margin-small-bottom">
<div class="uk-text-meta uk-margin-small-bottom">Criteria</div>
<div [innerHTML]="criteriaUtils.getFiltersAsText(selectionCriteria.criteria)"></div>
</div>
<div *ngIf="selectionCriteria?.criteria?.length === 0" class="message">
<h5 class="uk-margin-small-bottom">No criteria yet</h5>
<i class="uk-display-block">
Add multiple constraints in AND to define a criterion: results that satisfy at least one of the criteria will be included in your community.
</i>
</div>
</div>
</div>
</div>
<fs-modal #filtersModal (okEmitter)="saveCriteria()" (cancelEmitter)="criteria.reset()"
[okButtonDisabled]="criteria && criteria.disabled">
<div *ngIf="selectionCriteria" class="uk-container uk-container-large">
<criteria #criteria [height]="filtersModal.bodyHeight" [entityType]="'criterion'"
[entityTypePlural]="'criteria'" [selectionCriteria]="selectionCriteria">
<div no-criteria>
<h5 class="uk-margin-small-bottom">No Criteria yet</h5>
<i class="uk-display-block">
Add multiple constraints in AND to define a criterion: results that satisfy at least one of the criteria will be included in your community.
</i>
</div>
</criteria>
</div>
</fs-modal>
`
})
export class AdvancedCriteriaComponent implements OnInit, OnDestroy {
public loading = true;
public selectionCriteria: SelectionCriteria;
public community: CommunityInfo;
public criteriaUtils: CriteriaUtils = new CriteriaUtils();
private subscriptions: any[] = [];
@ViewChild('criteria') criteria: CriteriaComponent;
@ViewChild('filtersModal', { static: true }) filtersModal: FullScreenModalComponent;
constructor(private communityService: CommunityService,
private cdr: ChangeDetectorRef,
private advancedCriteriaService: AdvancedCriteriaService) {}
ngOnInit() {
this.loading = true;
this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe(community => {
this.community = community;
this.selectionCriteria = community.selectionCriteria;
this.loading = false;
}));
}
saveCriteria() {
let callback = (selectionCriteria): void => {
this.advancedCriteriaService.saveAdvancedCriteria(this.community.communityId, selectionCriteria).subscribe(() => {
this.criteria.reset();
this.criteria.loading = false;
NotificationHandler.rise('Filters have been <b>successfully updated</b>');
}, error => {
this.criteria.loading = false;
this.criteria.handeError('An error has been occurred. Try again later!', error);
});
}
this.loading = true;
this.criteria.save(callback);
}
public openCriteria() {
this.criteria.reset();
this.filtersModal.title = 'Criteria';
this.filtersModal.okButtonText = "Save";
this.filtersModal.back = true;
this.filtersModal.okButton = true;
this.filtersModal.open();
this.cdr.detectChanges();
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if(subscription instanceof Subscription) {
subscription.unsubscribe();
}
})
}
}

View File

@ -0,0 +1,18 @@
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {RouterModule} from "@angular/router";
import {AdvancedCriteriaComponent} from "./advanced-criteria.component";
import {PageContentModule} from "../../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module";
import {FullScreenModalModule} from "../../openaireLibrary/utils/modal/full-screen-modal/full-screen-modal.module";
import {CriteriaModule} from "../content-providers/criteria/criteria.module";
import {IconsModule} from "../../openaireLibrary/utils/icons/icons.module";
import {LoadingModule} from "../../openaireLibrary/utils/loading/loading.module";
@NgModule({
imports: [CommonModule, RouterModule.forChild([
{path: '', component: AdvancedCriteriaComponent,}
]), PageContentModule, FullScreenModalModule, CriteriaModule, IconsModule, LoadingModule],
declarations: [AdvancedCriteriaComponent],
exports: [AdvancedCriteriaComponent]
})
export class AdvancedCriteriaModule {}

View File

@ -0,0 +1,25 @@
import {Injectable} from "@angular/core";
import {SelectionCriteria} from "../../openaireLibrary/utils/entities/contentProvider";
import {Observable} from "rxjs";
import {CommunityInfo} from "../../openaireLibrary/connect/community/communityInfo";
import {HttpClient} from "@angular/common/http";
import {properties} from "../../../environments/environment";
import {map} from "rxjs/operators";
import {CommunityService} from "../../openaireLibrary/connect/community/community.service";
@Injectable({
providedIn: 'root'
})
export class AdvancedCriteriaService {
constructor(private httpClient: HttpClient,
private communityService: CommunityService) {
}
public saveAdvancedCriteria(communityId, selectionCriteria: SelectionCriteria): Observable<void> {
return this.httpClient.post(properties.communityAPI + communityId + '/advancedConstraint', selectionCriteria).pipe(map(community => {
this.communityService.updateAdvancedCriteria(this.communityService.parseCommunity(community).selectionCriteria);
}));
}
}

View File

@ -1,16 +1,6 @@
<div page-content> <div page-content>
<div header>
<div class="uk-flex uk-flex-middle uk-margin-medium-top info">
<div>
<div class="uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage Organizations
</div>
<h1 class="uk-h6 uk-margin-remove">{{community.shortTitle}}</h1>
</div>
</div>
<community-info tab="organizations"></community-info>
</div>
<div actions> <div actions>
<div class="uk-section-xsmall"> <div class="uk-section-xsmall uk-margin-top">
<div class="uk-flex uk-flex-center uk-flex-right@m"> <div class="uk-flex uk-flex-center uk-flex-right@m">
<button *ngIf="!organizationsEnabled" class="uk-button uk-button-default uk-margin-right" [class.uk-disabled]="loading" <button *ngIf="!organizationsEnabled" class="uk-button uk-button-default uk-margin-right" [class.uk-disabled]="loading"
[disabled]="loading" [disabled]="loading"

View File

@ -11,7 +11,6 @@ import {AlertModalModule} from '../../openaireLibrary/utils/modal/alertModal.mod
import {UtilitiesService} from '../../openaireLibrary/services/utilities.service'; import {UtilitiesService} from '../../openaireLibrary/services/utilities.service';
import {InputModule} from "../../openaireLibrary/sharedComponents/input/input.module"; import {InputModule} from "../../openaireLibrary/sharedComponents/input/input.module";
import {PageContentModule} from "../../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module"; import {PageContentModule} from "../../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module";
import {CommunityInfoModule} from "../community-info/community-info.module";
import {IconsModule} from "../../openaireLibrary/utils/icons/icons.module"; import {IconsModule} from "../../openaireLibrary/utils/icons/icons.module";
import {NoLoadPaging} from "../../openaireLibrary/searchPages/searchUtils/no-load-paging.module"; import {NoLoadPaging} from "../../openaireLibrary/searchPages/searchUtils/no-load-paging.module";
import {LoadingModule} from "../../openaireLibrary/utils/loading/loading.module"; import {LoadingModule} from "../../openaireLibrary/utils/loading/loading.module";
@ -22,7 +21,7 @@ import {PagingModule} from "../../openaireLibrary/utils/paging.module";
@NgModule({ @NgModule({
imports: [ imports: [
AffiliationsRoutingModule, CommonModule, FormsModule, RouterModule, AffiliationsRoutingModule, CommonModule, FormsModule, RouterModule,
AlertModalModule, ReactiveFormsModule, InputModule, PageContentModule, CommunityInfoModule, IconsModule, NoLoadPaging, LoadingModule, UrlPrefixModule, PagingModule AlertModalModule, ReactiveFormsModule, InputModule, PageContentModule, IconsModule, NoLoadPaging, LoadingModule, UrlPrefixModule, PagingModule
], ],
declarations: [ declarations: [
AffiliationsComponent AffiliationsComponent

View File

@ -11,13 +11,6 @@ import {CommunityService} from "../../openaireLibrary/connect/community/communit
template: ` template: `
<div page-content> <div page-content>
<div header> <div header>
<div class="uk-flex uk-flex-middle uk-margin-medium-top info">
<div>
<div class="uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage Links
</div>
<h1 class="uk-h6 uk-margin-remove">{{community.shortTitle}}</h1>
</div>
</div>
<users-tabs tab="claims"></users-tabs> <users-tabs tab="claims"></users-tabs>
</div> </div>
<div inner> <div inner>

View File

@ -11,6 +11,7 @@ import {ConnectCommunityGuard} from "../../openaireLibrary/connect/communityGuar
{path: 'projects', loadChildren: () => import('../projects/communityProjects.module').then(m => m.CommunityProjectsModule)}, {path: 'projects', loadChildren: () => import('../projects/communityProjects.module').then(m => m.CommunityProjectsModule)},
{path: 'content-providers', loadChildren: () => import('../content-providers/communityContentProviders.module').then(m => m.CommunityContentProvidersModule)}, {path: 'content-providers', loadChildren: () => import('../content-providers/communityContentProviders.module').then(m => m.CommunityContentProvidersModule)},
{path: 'zenodo-communities', loadChildren: () => import('../zenodo-communities/zenodo-communities.module').then(m => m.ZenodoCommunitiesModule)}, {path: 'zenodo-communities', loadChildren: () => import('../zenodo-communities/zenodo-communities.module').then(m => m.ZenodoCommunitiesModule)},
{path: 'advanced-criteria', loadChildren: () => import('../advanced-criteria/advanced-criteria.module').then(m => m.AdvancedCriteriaModule)},
{path: 'subjects', canActivateChild: [ConnectCommunityGuard], loadChildren: () => import('../subjects/subjects-edit-form/subjects-edit-form.module').then(m => m.SubjectsEditFormModule)}, {path: 'subjects', canActivateChild: [ConnectCommunityGuard], loadChildren: () => import('../subjects/subjects-edit-form/subjects-edit-form.module').then(m => m.SubjectsEditFormModule)},
]) ])
], ],

View File

@ -1,42 +0,0 @@
import {Component, Input, OnInit} from '@angular/core';
import {CommunityInfo} from '../../openaireLibrary/connect/community/communityInfo';
import {CommunityService} from '../../openaireLibrary/connect/community/community.service';
import {Subscription} from 'rxjs';
import {OpenaireEntities} from "../../openaireLibrary/utils/properties/searchFields";
@Component({
selector: 'community-info',
template: `
<ul *ngIf="community" class="uk-tab uk-margin-remove-bottom uk-margin-medium-top uk-flex uk-flex-center uk-flex-left@m" uk-tab>
<li [class.uk-active]="tab === 'profile'"><a routerLink="../profile">Profile</a></li>
<li [class.uk-active]="tab === 'organizations'"><a routerLink="../organizations">Organizations</a></li>
<li [class.uk-active]="tab === 'projects'"><a routerLink="../projects">{{openAIREEntities.PROJECTS}}</a></li>
<li [class.uk-active]="tab === 'content-providers'"><a routerLink="../content-providers">{{openAIREEntities.DATASOURCES}}</a></li>
<li *ngIf="community.type !='ri'" [class.uk-active]="tab === 'subjects'"><a routerLink="../subjects">Subjects</a></li>
<li [class.uk-active]="tab === 'zenodo-communities'"><a routerLink="../zenodo-communities">Zenodo Communities</a></li>
</ul>
`
})
export class CommunityInfoComponent implements OnInit {
@Input()
public type: string;
@Input()
public tab: "profile"| "organizations" | "projects" | "content-providers" | "subjects" | "zenodo-communities" = 'profile';
public community: CommunityInfo;
public openAIREEntities = OpenaireEntities;
private sub;
constructor(private communityService: CommunityService) {
}
ngOnInit() {
this.sub =this.communityService.getCommunityAsObservable().subscribe(community => {
this.community = community;
});
}
ngOnDestroy() {
if (this.sub instanceof Subscription) {
this.sub.unsubscribe();
}
}
}

View File

@ -1,14 +0,0 @@
import {NgModule} from '@angular/core';
import {RouterModule} from "@angular/router";
import {CommonModule} from "@angular/common";
import {CommunityInfoComponent} from "./community-info.component";
@NgModule({
imports: [
CommonModule, RouterModule
],
declarations: [CommunityInfoComponent],
exports: [CommunityInfoComponent]
})
export class CommunityInfoModule {
}

View File

@ -11,19 +11,8 @@ import {Subscription} from "rxjs";
selector: 'community-profile', selector: 'community-profile',
template: ` template: `
<div page-content> <div page-content>
<div header> <div actions class="uk-section-xsmall uk-margin-top">
<div class="uk-flex uk-flex-middle uk-margin-medium-top info"> <div class="uk-container">
<div>
<div class="uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage Community
Profile
</div>
<h1 class="uk-h6 uk-margin-remove">{{community.shortTitle}}</h1>
</div>
</div>
<community-info tab="profile"></community-info>
</div>
<div actions>
<div class="uk-container uk-section-xsmall">
<div class="uk-flex uk-flex-center uk-flex-right@m"> <div class="uk-flex uk-flex-center uk-flex-right@m">
<button class="uk-button uk-button-default uk-margin-right" <button class="uk-button uk-button-default uk-margin-right"
(click)="reset()" [class.uk-disabled]="loading || !editCommunityComponent.dirty" (click)="reset()" [class.uk-disabled]="loading || !editCommunityComponent.dirty"

View File

@ -5,7 +5,6 @@ import {PageContentModule} from "../../../openaireLibrary/dashboard/sharedCompon
import {ProfileComponent} from "./profile.component"; import {ProfileComponent} from "./profile.component";
import {EditCommunityModule} from "./edit-community/edit-community.module"; import {EditCommunityModule} from "./edit-community/edit-community.module";
import {LoadingModule} from "../../../openaireLibrary/utils/loading/loading.module"; import {LoadingModule} from "../../../openaireLibrary/utils/loading/loading.module";
import {CommunityInfoModule} from "../community-info.module";
@NgModule({ @NgModule({
imports: [ imports: [
@ -17,8 +16,7 @@ import {CommunityInfoModule} from "../community-info.module";
]), ]),
PageContentModule, PageContentModule,
EditCommunityModule, EditCommunityModule,
LoadingModule, LoadingModule
CommunityInfoModule,
], ],
declarations: [ProfileComponent], declarations: [ProfileComponent],
exports: [ProfileComponent] exports: [ProfileComponent]

View File

@ -13,17 +13,8 @@ declare var UIkit;
template: ` template: `
<div page-content> <div page-content>
<div header> <div header>
<div class="uk-flex uk-flex-middle uk-margin-top info">
<img src="assets/common-assets/placeholder.png" class="uk-margin-right">
<div>
<div class="uk-margin-remove uk-text-background uk-text-bold uk-h6">Admin Dashboard - Manage Options</div>
<h1 class="uk-h4 uk-margin-remove">Super Admin</h1>
</div>
</div>
<admin-tabs tab="customization" portal="connect"></admin-tabs> <admin-tabs tab="customization" portal="connect"></admin-tabs>
</div> </div>
<div inner> <div inner>
<div class="uk-alert uk-alert-warning uk-margin-top "> <div class="uk-alert uk-alert-warning uk-margin-top ">
<div class="uk-text-large">Use only after connect deployment. And only if there are css updates!</div> <div class="uk-text-large">Use only after connect deployment. And only if there are css updates!</div>

View File

@ -10,7 +10,6 @@ import {ErrorMessagesModule} from '../../openaireLibrary/utils/errorMessages.mod
import {AlertModalModule} from '../../openaireLibrary/utils/modal/alertModal.module'; import {AlertModalModule} from '../../openaireLibrary/utils/modal/alertModal.module';
import {CommonModule} from '@angular/common'; import {CommonModule} from '@angular/common';
import {PageContentModule} from "../../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module"; import {PageContentModule} from "../../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module";
import {CommunityInfoModule} from "../community-info/community-info.module";
import {InputModule} from "../../openaireLibrary/sharedComponents/input/input.module"; import {InputModule} from "../../openaireLibrary/sharedComponents/input/input.module";
import {SearchInputModule} from "../../openaireLibrary/sharedComponents/search-input/search-input.module"; import {SearchInputModule} from "../../openaireLibrary/sharedComponents/search-input/search-input.module";
import {NoLoadPaging} from "../../openaireLibrary/searchPages/searchUtils/no-load-paging.module"; import {NoLoadPaging} from "../../openaireLibrary/searchPages/searchUtils/no-load-paging.module";
@ -42,7 +41,6 @@ import {CriteriaModule} from "./criteria/criteria.module";
AlertModalModule, AlertModalModule,
SearchDataprovidersServiceModule, SearchDataprovidersServiceModule,
PageContentModule, PageContentModule,
CommunityInfoModule,
InputModule, InputModule,
SearchInputModule, SearchInputModule,
RouterModule.forChild([ RouterModule.forChild([

View File

@ -1,18 +1,37 @@
import {Option} from "../../openaireLibrary/sharedComponents/input/input.component"; import {Option} from "../../openaireLibrary/sharedComponents/input/input.component";
import {Criteria} from "../../openaireLibrary/utils/entities/contentProvider";
export class CriteriaUtils { export class CriteriaUtils {
public static readonly fields: Option[] = [ public readonly fields: Option[] = [
{value: 'title', label: 'Title'},
{value: 'author', label: 'Author\'s name'}, {value: 'author', label: 'Author\'s name'},
{value: 'title', label: 'Title'},
{value: 'orcid', label: 'Author\'s ORCID'}, {value: 'orcid', label: 'Author\'s ORCID'},
{value: 'contributor', label: 'Contributor'}, {value: 'contributor', label: 'Contributor'},
{value: 'description', label: 'Description'} {value: 'description', label: 'Description'},
{value: 'subject', label: 'Subject'},
{value: 'fos', label: 'Field of Science'},
{value: 'sdg', label: 'SDG'}
] ]
public static readonly verbs: Option[] = [ public readonly verbs: Option[] = [
{value: 'contains', label: 'contains'}, {value: 'contains', label: 'contains'},
{value: 'equals', label: 'equals'}, {value: 'equals', label: 'equals'},
{value: 'not_contains', label: 'not contains'}, {value: 'not_contains', label: 'not contains'},
{value: 'not_equals', label: 'not equals'} {value: 'not_equals', label: 'not equals'},
{value: 'starts_with', label: 'starts with'}
] ]
public getFiltersAsText(criteria: Criteria[]): string {
let text = criteria.slice(0, 3).map((criterion, index) => (index + 1) + ". " + criterion.constraint.map(constraint => {
let field = this.fields.find(field => field.value === constraint.field)?.label;
let matchCase = false;
if (!constraint.verb.includes('_caseinsensitive')) {
matchCase = true;
}
let verb = this.verbs.find(verb => verb.value === constraint.verb.replace("_caseinsensitive", "")).label;
let value = '"' + constraint.value + '"' + (matchCase ? " (Match case)" : "");
return field + " " + verb + " " + value;
}).join(" <b>and</b> "));
return text.join("<br>");
}
} }

View File

@ -1,120 +1,115 @@
<div class="uk-section uk-position-relative" style="min-height: 60vh"> <div class="uk-position-relative" style="min-height: 60vh">
<div *ngIf="loading" class="uk-position-center"> <div *ngIf="loading" class="uk-position-center">
<loading></loading> <loading></loading>
</div> </div>
<ng-container *ngIf="!loading"> <ng-container *ngIf="!loading">
<div class="uk-flex uk-flex-center uk-margin-medium-bottom"> <div class="criteria uk-overflow-auto uk-position-relative" [ngStyle]="{'height.px': criteriaHeight?criteriaHeight:null}">
<a (click)="addCriteria()" class="uk-flex uk-flex-middle uk-button uk-button-primary" <div *ngIf="criteria.length == 0" class="uk-text-center uk-position-center">
uk-tooltip="<div>Add filter to limit research results.<br>Results which satisfy any of the selected filters will be included in your community.</div>"> <ng-content select="[no-criteria]"></ng-content>
<icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left">Add filter</span>
</a>
</div>
<div *ngIf="criteria.length == 0" class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div *ngIf="dataProvider">No filters for {{dataProvider.officialname}}.</div>
<div>If no filters are specified, all {{openaireEntities.RESULTS | lowercase}} of this {{openaireEntities.DATASOURCE | lowercase}} will be included in your
{{openaireEntities.COMMUNITY | lowercase}}.
</div> </div>
</div> <form *ngIf="criteria.length > 0" [formGroup]="selectionCriteriaForm">
<form *ngIf="criteria.length > 0" [formGroup]="selectionCriteria"> <div formArrayName="criteria" class="uk-margin-bottom">
<div formArrayName="criteria" class="uk-margin-bottom"> <ul class="uk-list uk-list-xlarge uk-margin-top uk-margin-bottom">
<no-load-paging (pageChange)="updatePage($event)" [page]="page" [totalResults]="criteria.length" <li *ngFor="let criterion of criteria.controls; let i=index">
[pageSize]="pageSize" [type]="'filter' + (criteria.length > 1?'s':'')"> <div [id]="'criterion-' + i.toString()" [formGroupName]="i.toString()" class="uk-flex">
</no-load-paging> <h3 class="uk-padding uk-margin-remove-bottom uk-margin-top">
<ul class="uk-list uk-list-xlarge uk-margin-top uk-margin-bottom"> {{i + 1}}
<li *ngFor="let criterion of currentPage; let i=index"> </h3>
<div [formGroupName]="getIndex(i).toString()" class="uk-flex"> <div class="uk-width-expand uk-padding-small uk-border uk-border-rounded" formArrayName="constraint">
<h3 class="uk-padding uk-margin-remove-bottom uk-margin-top"> <div class="uk-flex-middle uk-grid uk-margin-small-bottom uk-visible@l" uk-grid>
{{getIndex(i) + 1}} <div class="uk-width-1-4">
</h3> <label class="uk-text-uppercase uk-text-bold">Field</label>
<div class="uk-width-expand uk-padding-small criterion" formArrayName="constraint">
<div class="uk-flex-middle uk-grid uk-margin-small-bottom uk-visible@l" uk-grid>
<div class="uk-width-1-4">
<label class="uk-text-uppercase uk-text-bold">Field</label>
</div>
<div class="uk-width-1-4">
<label class="uk-text-uppercase uk-text-bold">Operator</label>
</div>
<div class="uk-width-1-4">
<label class="uk-text-uppercase uk-text-bold">Term</label>
</div>
<div class="uk-width-expand uk-text-truncate">
<label class="uk-text-bold uk-text-uppercase">Match Case</label>
</div>
</div>
<div *ngFor="let constraint of getConstraint(getIndex(i)).controls; let j=index" [formGroupName]="j.toString()"
class="uk-margin-bottom uk-hidden@l">
<div class="uk-flex-middle uk-grid-small uk-margin-medium-bottom" uk-grid>
<div class="uk-flex uk-flex-right uk-width-1-1">
<button class="uk-close uk-icon" (click)="removeConstraint(getIndex(i), j)">
<icon name="close" ratio="1.5" [flex]="true"
[attr.uk-tooltip]="(getConstraint(getIndex(i)).length === 1?'By removing this constraint, the filter will be removed too':null)"></icon>
</button>
</div> </div>
<div class="uk-width-1-1" input type="select" inputClass="border-bottom" [placeholder]="{static: true, label: 'Choose a field'}" <div class="uk-width-1-4">
[options]="fields" [formInput]="constraint.get('field')"> <label class="uk-text-uppercase uk-text-bold">Operator</label>
<label class="uk-text-uppercase uk-text-bold uk-width-1-3 uk-text-truncate">Field:</label>
</div> </div>
<div class="uk-width-1-1" input type="select" inputClass="border-bottom" <div class="uk-width-1-4">
[options]="verbs" [formInput]="constraint.get('verb')"> <label class="uk-text-uppercase uk-text-bold">Term</label>
<label class="uk-text-uppercase uk-text-bold uk-width-1-3 uk-text-truncate">Operator:</label>
</div> </div>
<div class="uk-width-1-1" input [placeholder]="{static: true, label: 'Type a keyword'}" <div class="uk-width-expand uk-text-truncate">
[formInput]="constraint.get('value')"> <label class="uk-text-bold uk-text-uppercase">Match Case</label>
<label class="uk-text-uppercase uk-text-bold uk-width-1-3 uk-text-truncate">Term:</label>
</div> </div>
<div class="uk-width-1-1"> </div>
<div class="uk-grid" uk-grid> <div *ngFor="let constraint of getConstraint(i).controls; let j=index" [formGroupName]="j.toString()"
<label class="uk-text-uppercase uk-text-bold uk-width-1-3 uk-text-truncate">Match Case</label> class="uk-margin-bottom uk-hidden@l">
<div class="uk-width-expand"> <div class="uk-flex-middle uk-grid-small uk-margin-medium-bottom" uk-grid>
<mat-slide-toggle [checked]="constraint.get('verb_suffix').value === ''" <div class="uk-flex uk-flex-right uk-width-1-1">
[attr.uk-tooltip]="(constraint.get('verb_suffix').value === ''?('Only \'\'' + constraint.get('value').value + '\'\' matches'): <button class="uk-close uk-icon" (click)="removeConstraint(i, j)">
<icon name="close" ratio="1.5" [flex]="true"
[attr.uk-tooltip]="(getConstraint(i).length === 1?'By removing this constraint, the ' + entityType + ' will be removed too':null)"></icon>
</button>
</div>
<div class="uk-width-1-1" input type="select" inputClass="border-bottom" [placeholder]="{static: true, label: 'Choose a field'}"
[options]="criteriaUtils.fields" [formInput]="constraint.get('field')">
<label class="uk-text-uppercase uk-text-bold uk-width-1-3 uk-text-truncate">Field:</label>
</div>
<div class="uk-width-1-1" input type="select" inputClass="border-bottom"
[options]="criteriaUtils.verbs" [formInput]="constraint.get('verb')">
<label class="uk-text-uppercase uk-text-bold uk-width-1-3 uk-text-truncate">Operator:</label>
</div>
<div class="uk-width-1-1" input [placeholder]="{static: true, label: 'Type a keyword'}"
[formInput]="constraint.get('value')">
<label class="uk-text-uppercase uk-text-bold uk-width-1-3 uk-text-truncate">Term:</label>
</div>
<div class="uk-width-1-1">
<div class="uk-grid" uk-grid>
<label class="uk-text-uppercase uk-text-bold uk-width-1-3 uk-text-truncate">Match Case</label>
<div class="uk-width-expand">
<mat-slide-toggle [checked]="constraint.get('verb_suffix').value === ''"
[attr.uk-tooltip]="(constraint.get('verb_suffix').value === ''?('Only \'\'' + constraint.get('value').value + '\'\' matches'):
('Both \'\'' + constraint.get('value').value.toUpperCase() + '\'\' and \'\'' + constraint.get('value').value.toLowerCase() + '\'\' match'))" ('Both \'\'' + constraint.get('value').value.toUpperCase() + '\'\' and \'\'' + constraint.get('value').value.toLowerCase() + '\'\' match'))"
(change)="caseSensitive($event, constraint)"></mat-slide-toggle> (change)="caseSensitive($event, constraint)"></mat-slide-toggle>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> <div *ngFor="let constraint of getConstraint(i).controls; let j=index"
<div *ngFor="let constraint of getConstraint(getIndex(i)).controls; let j=index" [formGroupName]="j.toString()" class="uk-margin-bottom uk-visible@l">
[formGroupName]="j.toString()" class="uk-margin-bottom uk-visible@l"> <div class="uk-flex uk-flex-middle uk-grid" uk-grid>
<div class="uk-flex uk-flex-middle uk-grid" uk-grid> <div class="uk-width-1-4" input type="select" inputClass="border-bottom" [placeholder]="{static: true, label: 'Choose a field'}"
<div class="uk-width-1-4" input type="select" inputClass="border-bottom" [placeholder]="{static: true, label: 'Choose a field'}" [options]="criteriaUtils.fields" [formInput]="constraint.get('field')"></div>
[options]="fields" [formInput]="constraint.get('field')"></div> <div class="uk-width-1-4" input type="select" inputClass="border-bottom"
<div class="uk-width-1-4" input type="select" inputClass="border-bottom" [options]="criteriaUtils.verbs" [formInput]="constraint.get('verb')"></div>
[options]="verbs" [formInput]="constraint.get('verb')"></div> <div *ngIf="constraint.get('field').value !== 'fos' && constraint.get('field').value !== 'sdg'" class="uk-width-1-4" inputClass="flat small" input [placeholder]="{static: true, label: 'Type a keyword'}"
<div class="uk-width-1-4" input [placeholder]="{static: true, label: 'Type a keyword'}" [formInput]="constraint.get('value')"></div>
[formInput]="constraint.get('value')"></div> <div *ngIf="constraint.get('field').value === 'fos'" class="uk-width-1-4" inputClass="flat small" input [placeholder]="{static: true, label: 'Choose a FoS'}"
<div class="uk-width-expand"> [formInput]="constraint.get('value')" type="select" [options]="fos"></div>
<mat-slide-toggle [checked]="constraint.get('verb_suffix').value === ''" class="uk-margin-left" <div *ngIf="constraint.get('field').value === 'sdg'" class="uk-width-1-4" inputClass="flat small" input [placeholder]="{static: true, label: 'Choose a FoS'}"
[attr.uk-tooltip]="(constraint.get('verb_suffix').value === ''?('Only \'\'' + constraint.get('value').value + '\'\' matches'): [formInput]="constraint.get('value')" type="select" [options]="sdg"></div>
<div class="uk-width-expand">
<mat-slide-toggle [checked]="constraint.get('verb_suffix').value === ''" class="uk-margin-left"
[attr.uk-tooltip]="(constraint.get('verb_suffix').value === ''?('Only \'\'' + constraint.get('value').value + '\'\' matches'):
('Both \'\'' + constraint.get('value').value.toUpperCase() + '\'\' and \'\'' + constraint.get('value').value.toLowerCase() + '\'\' match'))" ('Both \'\'' + constraint.get('value').value.toUpperCase() + '\'\' and \'\'' + constraint.get('value').value.toLowerCase() + '\'\' match'))"
(change)="caseSensitive($event, constraint)"></mat-slide-toggle> (change)="caseSensitive($event, constraint)"></mat-slide-toggle>
</div> </div>
<div class="uk-flex uk-flex-center"> <div class="uk-flex uk-flex-center">
<button class="uk-close uk-icon" (click)="removeConstraint(getIndex(i), j)"> <button class="uk-close uk-icon" (click)="removeConstraint(i, j)">
<icon name="close" ratio="1.5" [flex]="true" <icon name="close" ratio="1.5" [flex]="true"
[attr.uk-tooltip]="(getConstraint(getIndex(i)).length === 1?'By removing this constraint, the filter will be removed too':null)"></icon> [attr.uk-tooltip]="(getConstraint(i).length === 1?'By removing this constraint, the ' + entityType + ' will be removed too':null)"></icon>
</button> </button>
</div>
</div> </div>
</div> </div>
</div> <div class="uk-margin-top uk-width-1-1 uk-flex uk-flex-center uk-flex-left@l">
<div class="uk-margin-top uk-width-1-1 uk-flex uk-flex-center uk-flex-left@l"> <a (click)="addConstraint(i)" class="uk-flex uk-flex-middle uk-button uk-button-link">
<a (click)="addConstraint(getIndex(i))" class="uk-flex uk-flex-middle uk-button uk-button-link"> <icon name="add" [flex]="true"></icon>
<icon name="add" [flex]="true"></icon> <span class="uk-margin-small-left">Add Constraint</span>
<span class="uk-margin-small-left">Add Constraint</span> </a>
</a> </div>
</div> </div>
</div> </div>
</div> </li>
</li> </ul>
</ul>
<div class="uk-margin-small-top">
<paging-no-load [currentPage]="page" [totalResults]="criteria.length" [size]="pageSize"
(pageChange)="updatePage($event)" customClasses="uk-flex-right@m uk-flex-center">
</paging-no-load>
</div> </div>
</div> </form>
</form> </div>
<div class="uk-flex uk-flex-center uk-margin-top">
<a (click)="addCriteria()" class="uk-flex uk-flex-middle uk-button uk-button-primary"
[attr.uk-tooltip]="'<div>Add a ' + entityType + ' to limit research results.<br>Results which satisfy any of the selected ' + entityTypePlural + ' will be included in your ' + openaireEntities.COMMUNITY + '.</div>'">
<icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left">Add {{entityType}}</span>
</a>
</div>
</ng-container> </ng-container>
</div> </div>

View File

@ -1,8 +1,3 @@
@import (reference) "~src/assets/openaire-theme/less/_import-variables.less"; .criteria {
padding-right: 20px;
.criterion {
border: @global-border solid @global-border-width;
border-radius: @global-border-radius;
max-height: 400px;
overflow: auto;
} }

View File

@ -1,93 +1,118 @@
import {ChangeDetectorRef, Component, Input, OnInit} from '@angular/core';
import {EnvProperties} from '../../../openaireLibrary/utils/properties/env-properties';
import { import {
Constraint, AfterViewInit,
ContentProvider, ChangeDetectorRef,
Criteria, Component,
SelectionCriteria Input,
} from '../../../openaireLibrary/utils/entities/contentProvider'; OnChanges,
OnDestroy,
OnInit,
SimpleChanges
} from '@angular/core';
import {EnvProperties} from '../../../openaireLibrary/utils/properties/env-properties';
import {Constraint, Criteria, SelectionCriteria} from '../../../openaireLibrary/utils/entities/contentProvider';
import {AbstractControl, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms'; import {AbstractControl, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
import {ManageCommunityContentProvidersService} from '../../../services/manageContentProviders.service';
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
import {Option} from "../../../openaireLibrary/sharedComponents/input/input.component";
import {MatSlideToggleChange} from "@angular/material/slide-toggle"; import {MatSlideToggleChange} from "@angular/material/slide-toggle";
import {HelperFunctions} from "../../../openaireLibrary/utils/HelperFunctions.class"; import {HelperFunctions} from "../../../openaireLibrary/utils/HelperFunctions.class";
import {CriteriaUtils} from "../criteria-utils"; import {CriteriaUtils} from "../criteria-utils";
import {NotificationHandler} from "../../../openaireLibrary/utils/notification-handler"; import {NotificationHandler} from "../../../openaireLibrary/utils/notification-handler";
import {OpenaireEntities} from "../../../openaireLibrary/utils/properties/searchFields"; import {OpenaireEntities} from "../../../openaireLibrary/utils/properties/searchFields";
import {ISVocabulariesService} from "../../../openaireLibrary/utils/staticAutoComplete/ISVocabularies.service";
import {Subscription} from "rxjs";
@Component({ @Component({
selector: 'criteria', selector: 'criteria',
templateUrl: 'criteria.component.html', templateUrl: 'criteria.component.html',
styleUrls: ['criteria.component.less'] styleUrls: ['criteria.component.less']
}) })
export class CriteriaComponent implements OnInit { export class CriteriaComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy {
@Input() @Input()
public dataProvider: ContentProvider; public entityType: string = 'filter';
public selectionCriteria: UntypedFormGroup; @Input()
public entityTypePlural: string = 'filters';
@Input()
public selectionCriteria: SelectionCriteria;
@Input()
public height: number = 0;
public criteriaHeight: number = 0;
public selectionCriteriaForm: UntypedFormGroup;
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public fields: Option[] = CriteriaUtils.fields; public criteriaUtils: CriteriaUtils = new CriteriaUtils();
public verbs: Option[] = CriteriaUtils.verbs; public fos: string[] = [];
public sdg: string[] = [];
public loading = true; public loading = true;
/** Paging */
public page: number = 1;
public pageSize: number = 5;
public openaireEntities = OpenaireEntities; public openaireEntities = OpenaireEntities;
private subscriptions: any[] = [];
constructor(private manageCommunityContentProvidersService: ManageCommunityContentProvidersService, constructor(private cdr: ChangeDetectorRef, private vocabulariesService: ISVocabulariesService,
private cdr: ChangeDetectorRef,
private fb: UntypedFormBuilder) { private fb: UntypedFormBuilder) {
} }
ngOnInit() { ngOnInit() {
this.reset(); this.reset();
this.loading = false; this.loading = false;
this.subscriptions.push(this.vocabulariesService.getVocabularyByType('fos', null, properties).subscribe((fos: any[]) => {
this.fos = fos.map(element => element.id);
}));
this.subscriptions.push(this.vocabulariesService.getVocabularyByType('sdg', null, properties).subscribe((sdg: any[]) => {
this.sdg = sdg.map(element => element.id);
}));
} }
reset() { ngOnChanges(changes: SimpleChanges) {
this.page = 1; this.calculateMaxHeight();
if (this.dataProvider) { }
this.selectionCriteria = this.fb.group({
criteria: this.fb.array([]) ngAfterViewInit() {
}); this.calculateMaxHeight();
let selectionCriteria = this.dataProvider.selectioncriteria; }
if (selectionCriteria) {
selectionCriteria.criteria.forEach(criterion => { ngOnDestroy() {
let constraintArray: UntypedFormArray = this.fb.array([]); this.subscriptions.forEach(subscription => {
criterion.constraint.forEach(constraint => { if (subscription instanceof Subscription) {
constraintArray.push(this.fb.group({ subscription.unsubscribe();
field: this.fb.control(constraint.field, Validators.required), }
verb: this.fb.control(this.removeSuffix(constraint.verb), Validators.required), });
value: this.fb.control(constraint.value, Validators.required), }
verb_suffix: this.fb.control(this.getSuffix(constraint.verb))
})); calculateMaxHeight() {
}); if(this.height) {
this.criteria.push(this.fb.group({ if(this.height > 0) {
constraint: constraintArray /* Element height - margins(20 + 20) - button height(42) */
})); this.criteriaHeight = this.height - 40 - 42;
}); this.cdr.detectChanges();
} }
} }
} }
get disabled() { reset() {
return this.loading || !this.dirty || this.selectionCriteria.invalid; if (this.selectionCriteria?.criteria) {
} this.selectionCriteriaForm = this.fb.group({
criteria: this.fb.array([])
get currentPage(): AbstractControl[] { });
if (this.criteria) { this.selectionCriteria.criteria.forEach(criterion => {
return this.criteria.controls.slice((this.page - 1) * this.pageSize, this.page * this.pageSize); let constraintArray: UntypedFormArray = this.fb.array([]);
} else { criterion.constraint.forEach(constraint => {
return []; constraintArray.push(this.fb.group({
field: this.fb.control(constraint.field, Validators.required),
verb: this.fb.control(this.removeSuffix(constraint.verb), Validators.required),
value: this.fb.control(constraint.value, Validators.required),
verb_suffix: this.fb.control(this.getSuffix(constraint.verb))
}));
});
this.criteria.push(this.fb.group({
constraint: constraintArray
}));
});
} }
} }
getIndex(index: number): number { get disabled() {
return (this.page - 1)*this.pageSize + index; return this.loading || !this.dirty || this.selectionCriteriaForm.invalid;
} }
public get criteria(): UntypedFormArray { public get criteria(): UntypedFormArray {
return this.selectionCriteria.get('criteria') as UntypedFormArray; return this.selectionCriteriaForm.get('criteria') as UntypedFormArray;
} }
public getConstraint(i: number): UntypedFormArray { public getConstraint(i: number): UntypedFormArray {
@ -103,11 +128,9 @@ export class CriteriaComponent implements OnInit {
verb_suffix: this.fb.control('_caseinsensitive') verb_suffix: this.fb.control('_caseinsensitive')
}) })
]); ]);
this.criteria.insert(0, this.fb.group({ this.criteria.push(this.fb.group({constraint: constraintArray}));
constraint: constraintArray
}));
this.page = 1;
this.cdr.detectChanges(); this.cdr.detectChanges();
document.getElementById('criterion-' + (this.criteria.length - 1).toString()).scrollIntoView({behavior: 'smooth'});
} }
public addConstraint(i: number) { public addConstraint(i: number) {
@ -126,25 +149,22 @@ export class CriteriaComponent implements OnInit {
constraintArray.removeAt(j); constraintArray.removeAt(j);
if (constraintArray.length === 0) { if (constraintArray.length === 0) {
this.criteria.removeAt(i); this.criteria.removeAt(i);
while(this.currentPage.length === 0 && this.page > 0) {
this.page--;
}
} }
this.cdr.detectChanges(); this.cdr.detectChanges();
} }
get dataProviderCriteria(): Criteria[] { get criteriaArray(): Criteria[] {
return (this.dataProvider && this.dataProvider.selectioncriteria && this.dataProvider.selectioncriteria.criteria)?this.dataProvider.selectioncriteria.criteria:[]; return (this.selectionCriteria?.criteria) ? this.selectionCriteria?.criteria : [];
} }
get dirty() { get dirty() {
if(!this.dataProvider || !this.criteria) { if (!this.selectionCriteria || !this.criteria) {
return false; return false;
} else if(this.criteria.length !== this.dataProviderCriteria.length) { } else if (this.criteria.length !== this.criteriaArray.length) {
return true; return true;
} else { } else {
return this.dataProviderCriteria.filter((criterion, i) => { return this.criteriaArray.filter((criterion, i) => {
if(criterion.constraint.length !== this.getConstraint(i).length) { if (criterion.constraint.length !== this.getConstraint(i).length) {
return true; return true;
} else { } else {
let temp = this.getConstraint(i).value; let temp = this.getConstraint(i).value;
@ -156,23 +176,10 @@ export class CriteriaComponent implements OnInit {
} }
} }
save(callback: Function = null) { save(callback: (selectionCriteria) => void = null) {
if (this.selectionCriteria.valid) { if (this.selectionCriteriaForm.valid) {
this.loading = true; this.loading = true;
this.dataProvider.selectioncriteria = this.parseForm(this.selectionCriteria.value); callback(this.parseForm(this.selectionCriteriaForm.value));
this.manageCommunityContentProvidersService.saveContentProvider(this.properties, this.dataProvider).subscribe(() => {
this.reset();
if(callback) {
callback();
}
this.loading = false;
NotificationHandler.rise('Filters have been <b>successfully updated</b>');
}, error => {
this.loading = false;
this.handeError('An error has been occurred. Try again later!', error);
});
} else {
this.handeError('An error has been occurred. Try again later!');
} }
} }
@ -182,7 +189,7 @@ export class CriteriaComponent implements OnInit {
} }
caseSensitive(event: MatSlideToggleChange, constraint: AbstractControl) { caseSensitive(event: MatSlideToggleChange, constraint: AbstractControl) {
if(event.checked) { if (event.checked) {
constraint.get('verb_suffix').setValue(''); constraint.get('verb_suffix').setValue('');
} else { } else {
constraint.get('verb_suffix').setValue('_caseinsensitive'); constraint.get('verb_suffix').setValue('_caseinsensitive');
@ -194,7 +201,7 @@ export class CriteriaComponent implements OnInit {
} }
getSuffix(verb: string) { getSuffix(verb: string) {
if(verb.includes('_caseinsensitive')) { if (verb.includes('_caseinsensitive')) {
return '_caseinsensitive'; return '_caseinsensitive';
} else { } else {
return ''; return '';
@ -215,9 +222,4 @@ export class CriteriaComponent implements OnInit {
}) })
return selectionCriteria; return selectionCriteria;
} }
public updatePage(event) {
this.page = event.value;
HelperFunctions.scroll();
}
} }

View File

@ -1,4 +1,4 @@
import {Component, OnInit, ViewChild} from '@angular/core'; import {ChangeDetectorRef, Component, OnInit, ViewChild} from '@angular/core';
import {RemoveContentProvidersComponent} from './remove-content-providers.component'; import {RemoveContentProvidersComponent} from './remove-content-providers.component';
import {Title} from '@angular/platform-browser'; import {Title} from '@angular/platform-browser';
import { import {
@ -13,6 +13,8 @@ import {CommunityService} from "../../openaireLibrary/connect/community/communit
import {ContentProvider} from "../../openaireLibrary/utils/entities/contentProvider"; import {ContentProvider} from "../../openaireLibrary/utils/entities/contentProvider";
import {OpenaireEntities} from "../../openaireLibrary/utils/properties/searchFields"; import {OpenaireEntities} from "../../openaireLibrary/utils/properties/searchFields";
import {CriteriaComponent} from "./criteria/criteria.component"; import {CriteriaComponent} from "./criteria/criteria.component";
import {NotificationHandler} from "../../openaireLibrary/utils/notification-handler";
import {ManageCommunityContentProvidersService} from "../../services/manageContentProviders.service";
@Component({ @Component({
selector: 'manage-content-providers', selector: 'manage-content-providers',
@ -24,12 +26,22 @@ import {CriteriaComponent} from "./criteria/criteria.component";
(communityContentProvidersChanged)="communityContentProvidersChanged($event)"> (communityContentProvidersChanged)="communityContentProvidersChanged($event)">
</remove-content-providers> </remove-content-providers>
<fs-modal #addContentProvidersModal> <fs-modal #addContentProvidersModal>
<add-content-providers #addContentProviders [communityContentProviders]="communityContentProviders" [community]="community" <add-content-providers #addContentProviders [communityContentProviders]="communityContentProviders"
[community]="community"
(communityContentProvidersChanged)="communityContentProvidersChanged($event)"></add-content-providers> (communityContentProvidersChanged)="communityContentProvidersChanged($event)"></add-content-providers>
</fs-modal> </fs-modal>
<fs-modal #filtersModal (okEmitter)="saveCriteria()" (cancelEmitter)="criteria.reset()" [okButtonDisabled]="criteria && criteria.disabled"> <fs-modal #filtersModal (okEmitter)="saveCriteria()" (cancelEmitter)="criteria.reset()"
<div class="uk-container"> [okButtonDisabled]="criteria && criteria.disabled">
<criteria #criteria *ngIf="contentProvider" [dataProvider]="contentProvider"></criteria> <div class="uk-container uk-container-large">
<criteria #criteria *ngIf="dataProvider" [height]="filtersModal.bodyHeight"
[selectionCriteria]="dataProvider.selectioncriteria">
<div no-criteria>
<h5 class="uk-margin-small-bottom">No Filters for {{dataProvider.officialname}} yet</h5>
<i class="uk-display-block">If no Filters are specified, all {{openaireEntities.RESULTS | lowercase}} of this {{openaireEntities.DATASOURCE | lowercase}} will be included in your
{{openaireEntities.COMMUNITY | lowercase}}.
</i>
</div>
</criteria>
</div> </div>
</fs-modal> </fs-modal>
` `
@ -45,11 +57,14 @@ export class ManageContentProvidersComponent implements OnInit {
public showLoadingInRemove: boolean = true; public showLoadingInRemove: boolean = true;
public body: string = "Send from page"; public body: string = "Send from page";
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public openaireEntities = OpenaireEntities;
public community: CommunityInfo; public community: CommunityInfo;
public contentProvider: ContentProvider; public dataProvider: ContentProvider;
constructor(private title: Title, constructor(private title: Title,
private communityService: CommunityService) { private cdr: ChangeDetectorRef,
private communityService: CommunityService,
private manageCommunityContentProvidersService: ManageCommunityContentProvidersService) {
} }
ngOnInit() { ngOnInit() {
@ -80,17 +95,27 @@ export class ManageContentProvidersComponent implements OnInit {
} }
public openCriteria(contentProvider: ContentProvider) { public openCriteria(contentProvider: ContentProvider) {
this.contentProvider = contentProvider; this.dataProvider = contentProvider;
this.filtersModal.title = 'Filters'; this.filtersModal.title = 'Filters';
this.filtersModal.okButtonText = "Save"; this.filtersModal.okButtonText = "Save";
this.filtersModal.back = true; this.filtersModal.back = true;
this.filtersModal.okButton = true; this.filtersModal.okButton = true;
this.filtersModal.open(); this.filtersModal.open();
this.cdr.detectChanges();
} }
public saveCriteria() { public saveCriteria() {
let callback: Function = () => { let callback = (selectionCriteria): void => {
this.removeContentProvidersComponent.getCommunityContentProviders(); this.dataProvider.selectioncriteria = selectionCriteria;
this.manageCommunityContentProvidersService.saveContentProvider(this.properties, this.dataProvider).subscribe(() => {
this.criteria.reset();
this.removeContentProvidersComponent.getCommunityContentProviders();
this.criteria.loading = false;
NotificationHandler.rise('Filters have been <b>successfully updated</b>');
}, error => {
this.criteria.loading = false;
this.criteria.handeError('An error has been occurred. Try again later!', error);
});
} }
this.removeContentProvidersComponent.loading = true; this.removeContentProvidersComponent.loading = true;
this.criteria.save(callback); this.criteria.save(callback);

View File

@ -1,16 +1,6 @@
<div page-content> <div page-content>
<div header>
<div class="uk-flex uk-flex-middle uk-margin-medium-top info">
<div>
<div class="uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage <span class="uk-text-capitalize">{{openAIREEntities.DATASOURCES}}</span>
</div>
<h1 class="uk-h6 uk-margin-remove">{{community.shortTitle}}</h1>
</div>
</div>
<community-info tab="content-providers"></community-info>
</div>
<div actions> <div actions>
<div class="uk-section-xsmall"> <div class="uk-section-xsmall uk-margin-top">
<div class="uk-flex uk-flex-right@m uk-flex-center uk-flex-middle uk-grid" uk-grid> <div class="uk-flex uk-flex-right@m uk-flex-center uk-flex-middle uk-grid" uk-grid>
<div search-input [expandable]="true" [searchControl]="filterForm.get('keyword')" searchInputClass="outer" <div search-input [expandable]="true" [searchControl]="filterForm.get('keyword')" searchInputClass="outer"
[placeholder]="'Search ' + openAIREEntities.DATASOURCES" [disabled]="loading" [placeholder]="'Search ' + openAIREEntities.DATASOURCES" [disabled]="loading"
@ -66,7 +56,7 @@
</h6> </h6>
<div *ngIf="item.selectioncriteria?.criteria?.length > 0" class="uk-margin-small-bottom uk-text-small"> <div *ngIf="item.selectioncriteria?.criteria?.length > 0" class="uk-margin-small-bottom uk-text-small">
<div class="uk-text-meta uk-margin-small-bottom">Filters</div> <div class="uk-text-meta uk-margin-small-bottom">Filters</div>
<div [innerHTML]="getFiltersAsText(item.selectioncriteria.criteria)"></div> <div [innerHTML]="criteriaUtils.getFiltersAsText(item.selectioncriteria.criteria)"></div>
<div *ngIf="item.selectioncriteria.criteria.length > 3" class="uk-margin-small-top"> <div *ngIf="item.selectioncriteria.criteria.length > 3" class="uk-margin-small-top">
<a class="uk-link view-more-less-link" (click)="openCriteria(item)">View all {{item.selectioncriteria.criteria.length}} filters</a> <a class="uk-link view-more-less-link" (click)="openCriteria(item)">View all {{item.selectioncriteria.criteria.length}} filters</a>
</div> </div>

View File

@ -38,8 +38,7 @@ export class RemoveContentProvidersComponent implements OnInit {
private selectedCommunityContentProvider: any; private selectedCommunityContentProvider: any;
@ViewChild('deleteModal') deleteModal: AlertModal; @ViewChild('deleteModal') deleteModal: AlertModal;
/** Criteria */ /** Criteria */
private fields = CriteriaUtils.fields; public criteriaUtils: CriteriaUtils = new CriteriaUtils();
private verbs = CriteriaUtils.verbs;
/** Paging */ /** Paging */
page: number = 1; page: number = 1;
resultsPerPage: number = properties.resultsPerPage; resultsPerPage: number = properties.resultsPerPage;
@ -81,20 +80,6 @@ export class RemoveContentProvidersComponent implements OnInit {
}); });
} }
getFiltersAsText(criteria: Criteria[]): string {
let text = criteria.slice(0, 3).map((criterion, index) => (index + 1) + ". " + criterion.constraint.map(constraint => {
let field = this.fields.find(field => field.value === constraint.field)?.label;
let matchCase = false;
if (!constraint.verb.includes('_caseinsensitive')) {
matchCase = true;
}
let verb = this.verbs.find(verb => verb.value === constraint.verb.replace("_caseinsensitive", "")).label;
let value = '"' + constraint.value + '"' + (matchCase ? " (Match case)" : "");
return field + " " + verb + " " + value;
}).join(" <b>and</b> "));
return text.join("<br>");
}
public confirmedDeleteContentProvider() { public confirmedDeleteContentProvider() {
this.subscriptions.push(this._manageCommunityContentProvidersService.removeContentProvider(this.properties, this.community.communityId, this.selectedCommunityContentProvider.id).subscribe( this.subscriptions.push(this._manageCommunityContentProvidersService.removeContentProvider(this.properties, this.community.communityId, this.selectedCommunityContentProvider.id).subscribe(
() => { () => {

View File

@ -9,60 +9,64 @@ declare var UIkit;
selector: 'background-upload', selector: 'background-upload',
template: ` template: `
<input #file id="photo" type="file" class="uk-hidden" (change)="fileChangeEvent($event)"/> <input #file id="photo" type="file" class="uk-hidden" (change)="fileChangeEvent($event)"/>
<div *ngIf="!background.imageFile" class=" upload uk-text-center uk-height-small uk-flex uk-flex-middle uk-flex-center uk-text-uppercase"> <div *ngIf="!background.imageFile"
class=" upload uk-text-center uk-height-small uk-flex uk-flex-middle uk-flex-center uk-text-uppercase">
<span uk-icon="icon: cloud-upload"></span> <span uk-icon="icon: cloud-upload"></span>
<div uk-form-custom> <div uk-form-custom>
<span class="uk-link uk-margin-small-left" (click)="file.click()">upload image</span> <span class="uk-link uk-margin-small-left" (click)="file.click()">upload image</span>
</div> </div>
</div> </div>
<div *ngIf="background.imageFile" class="uk-width-1-1 uk-flex uk-flex-middle "> <div *ngIf="background.imageFile" class="uk-width-1-1 uk-flex uk-flex-middle ">
<div class="uk-width-1-1 uk-height-small" style = "background-size:cover" <div class="uk-width-1-1 uk-height-small" style="background-size:cover"
[style.background-image]=" getUrl()"> [style.background-image]=" getUrl()">
<a (click)="removePhoto()" uk-tooltip="Remove" class="uk-float-right uk-border-rounded uk-margin-top uk-margin-right uk-background-muted uk-button uk-button-link"> <a (click)="removePhoto()" uk-tooltip="Remove"
<icon name="delete" [defaultSize]="true" [flex]="true"></icon> class="uk-float-right uk-border-rounded uk-margin-top uk-margin-right uk-background-muted uk-button uk-button-link">
</a> <icon name="delete" [defaultSize]="true" [flex]="true"></icon>
</div> </a>
</div> </div>
</div>
<div *ngIf="background.imageFile" class="uk-margin-top"> <div *ngIf="background.imageFile" class="uk-margin-top">
<div class="uk-text-bold uk-text-uppercase uk-text-meta uk-margin-small-bottom uk-margin-large-top">position</div> <div class="uk-text-bold uk-text-uppercase uk-text-meta uk-margin-small-bottom uk-margin-large-top">position</div>
<div class="uk-width-expand uk-padding-remove-left" input type="select" inputClass="flat x-small" [(value)]="background.position" <div class="uk-width-expand uk-padding-remove-left" input type="select" inputClass="flat x-small"
[options]="['top','center','bottom']" > [(value)]="background.position"
</div> [options]="['top','center','bottom']">
</div>
</div> </div>
`, `,
styles:[` styles: [`
.upload{ .upload {
border: 1px dotted grey; border: 1px dotted grey;
} }
`] `]
}) })
export class BackgroundUploadComponent implements OnInit { export class BackgroundUploadComponent implements OnInit {
@Input() label:string = ""; @Input() label: string = "";
@Input() background; @Input() background;
@Input() oldBackground; @Input() oldBackground;
// @Input() light:boolean; // @Input() light:boolean;
@Input() communityId:string = ""; @Input() communityId: string = "";
public file: File; public file: File;
// public photo: string | ArrayBuffer; // public photo: string | ArrayBuffer;
private maxsize: number = 2000 * 1024; private maxsize: number = 2000 * 1024;
properties; properties;
private subscriptions: any[] = []; private subscriptions: any[] = [];
constructor(private utilsService: UtilitiesService) { constructor(private utilsService: UtilitiesService) {
} }
ngOnInit() { ngOnInit() {
this.properties = properties; this.properties = properties;
} }
ngOnDestroy() { ngOnDestroy() {
this.subscriptions.forEach(subscription => { this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscription) { if (subscription instanceof Subscription) {
@ -70,30 +74,29 @@ export class BackgroundUploadComponent implements OnInit {
} }
}); });
} }
removePhoto() { removePhoto() {
if (typeof document != 'undefined') { if (typeof document != 'undefined') {
(<HTMLInputElement>document.getElementById("photo")).value = ""; (<HTMLInputElement>document.getElementById("photo")).value = "";
} }
// this.initPhoto(); // this.initPhoto();
console.log(this.background.imageFile + " " + this.oldBackground.imageFile) console.log(this.background.imageFile + " " + this.oldBackground.imageFile)
if(this.background.imageFile != this.oldBackground.imageFile){ if (this.background.imageFile != this.oldBackground.imageFile) {
this.deletePhoto(); this.deletePhoto();
} }
this.background.imageFile = null; this.background.imageFile = null;
this.file = null; this.file = null;
} }
public deletePhoto() { public deletePhoto() {
if (this.background.imageFile) { if (this.background.imageFile) {
this.subscriptions.push(this.utilsService.deletePhoto(properties.utilsService + '/delete/community/' + this.communityId + "/" +this.background.imageFile).subscribe()); this.subscriptions.push(this.utilsService.deletePhoto(properties.utilsService + '/delete/community/' + this.communityId + "/" + this.background.imageFile).subscribe());
} }
} }
fileChangeEvent(event) { fileChangeEvent(event) {
if (event.target.files && event.target.files[0]) { if (event.target.files && event.target.files[0]) {
this.file = event.target.files[0]; this.file = event.target.files[0];
@ -105,7 +108,7 @@ export class BackgroundUploadComponent implements OnInit {
}); });
this.removePhoto(); this.removePhoto();
} else if (this.file.size > this.maxsize) { } else if (this.file.size > this.maxsize) {
UIkit.notification('File exceeds size\'s limit ('+this.maxsize/1024+'KB)! ', { UIkit.notification('File exceeds size\'s limit (' + this.maxsize / 1024 + 'KB)! ', {
status: 'danger', status: 'danger',
timeout: 6000, timeout: 6000,
pos: 'bottom-right' pos: 'bottom-right'
@ -122,27 +125,34 @@ export class BackgroundUploadComponent implements OnInit {
} }
} }
} }
public save() { public save() {
if (this.file) { if (this.file) {
this.subscriptions.push(this.utilsService.uploadPhoto(this.properties.utilsService + "/upload/community/"+ this.communityId + "/" + encodeURIComponent(this.communityId+"-"+this.label)+"?big=1", this.file).subscribe(res => { this.subscriptions.push(this.utilsService.uploadPhoto(this.properties.utilsService + "/upload/community/" + this.communityId + "/" + encodeURIComponent(this.communityId + "-" + this.label) + "?big=1", this.file).subscribe(res => {
this.deletePhoto(); this.deletePhoto();
this.removePhoto(); this.removePhoto();
this.background.imageFile = res.filename; this.background.imageFile = res.filename;
}, error => { }, error => {
UIkit.notification("An error has been occurred during upload your image. Try again later", { if (error.error.message) {
status: 'danger', UIkit.notification('The maximum size of an image is 1MB, please check if your file exceeds this limit.', {
timeout: 6000, status: 'danger',
pos: 'bottom-right' timeout: 6000,
}); pos: 'bottom-right'
});
} else {
UIkit.notification("An error has been occurred during upload your image. Try again later", {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
}
})); }));
} }
} }
getUrl() getUrl() {
{ return "url('" + (this.background.imageFile.indexOf('data:') == -1 ? (this.properties.utilsService +
return "url('" +(this.background.imageFile.indexOf('data:')==-1?(this.properties.utilsService + '/download/' + this.background.imageFile) : this.background.imageFile) + "')";
'/download/'+this.background.imageFile):this.background.imageFile) +"')";
} }
} }

View File

@ -1,16 +1,14 @@
<aside *ngIf="draftCustomizationOptions" id="sidebar_main"> <aside *ngIf="draftCustomizationOptions" id="sidebar_main">
<div id="sidebar_content"> <div id="sidebar_content">
<div class="menu_section uk-margin-large-top"> <div class="back">
<a (click)="close()" class="uk-button uk-button-link uk-margin-left"> <a (click)="close()" class="uk-flex uk-flex-middle uk-flex-center">
<h6 class="uk-margin-remove-bottom uk-flex uk-flex-middle uk-flex-center"> <div class="uk-width-auto">
<div class="uk-width-auto"> <icon *ngIf="menuSelected.id != 'home'" name="west" ratio="1.3"
<icon *ngIf="menuSelected.id != 'home'" class="menu-icon" name="west" ratio="1.5" [flex]="true"></icon>
[flex]="true"></icon> <icon *ngIf="menuSelected.id == 'home'" name="close" ratio="1.3"
<icon *ngIf="menuSelected.id == 'home'" class="menu-icon" name="close" ratio="2" [flex]="true"></icon>
[flex]="true"></icon> </div>
</div> <span class="uk-width-expand uk-text-truncate uk-margin-left hide-on-close">{{menuSelected.name}}</span>
<span class="uk-width-expand uk-text-truncate uk-margin-small-left">{{menuSelected.name}}</span>
</h6>
</a> </a>
</div> </div>
<div class="menu_section uk-margin-large-top uk-overflow-auto" style="max-height: 75vh"> <div class="menu_section uk-margin-large-top uk-overflow-auto" style="max-height: 75vh">
@ -23,20 +21,15 @@
<div *ngIf="item.icon" class="uk-width-auto"> <div *ngIf="item.icon" class="uk-width-auto">
<icon class="menu-icon" [name]="item.icon" [flex]="true"></icon> <icon class="menu-icon" [name]="item.icon" [flex]="true"></icon>
</div> </div>
<span <span class="uk-width-expand uk-text-truncate uk-margin-small-left hide-on-close">
class="uk-width-expand uk-text-truncate uk-margin-small-left">
{{item.name}} {{item.name}}
</span> </span>
<span uk-icon="triangle-right"></span> <span uk-icon="triangle-right"></span>
</div> </div>
</a> </a>
</li> </li>
</ng-template> </ng-template>
</ul> </ul>
<ng-container *ngIf="menuSelected.id == 'identity'"> <ng-container *ngIf="menuSelected.id == 'identity'">
<ng-container <ng-container
*ngTemplateOutlet="identityOptions ; context: { }"></ng-container> *ngTemplateOutlet="identityOptions ; context: { }"></ng-container>

View File

@ -20,14 +20,6 @@ type Tab = 'all' | 'communities' | 'ris';
template: ` template: `
<div page-content [id]="tab"> <div page-content [id]="tab">
<div header> <div header>
<div class="uk-flex uk-flex-middle uk-margin-medium-top info">
<div>
<div class="uk-text-background uk-text-bold uk-text-small">
Admin Dashboard - Manage Communities
</div>
<h1 class="uk-h6 uk-margin-remove">Research Communities & Initiatives</h1>
</div>
</div>
<ul class="uk-tab uk-margin-medium-top" uk-tab> <ul class="uk-tab uk-margin-medium-top" uk-tab>
<li [class.uk-active]="tab === 'all'"><a (click)="tab = 'all'"><span class="title">All</span></a></li> <li [class.uk-active]="tab === 'all'"><a (click)="tab = 'all'"><span class="title">All</span></a></li>
<li [class.uk-active]="tab === 'communities'"><a (click)="tab = 'communities'"><span class="title">Research Communities</span></a> <li [class.uk-active]="tab === 'communities'"><a (click)="tab = 'communities'"><span class="title">Research Communities</span></a>

View File

@ -10,7 +10,7 @@ import {UrlPrefixModule} from '../../openaireLibrary/utils/pipes/url-prefix.modu
import {CommunitiesService} from '../../openaireLibrary/connect/communities/communities.service'; import {CommunitiesService} from '../../openaireLibrary/connect/communities/communities.service';
import {IconsModule} from '../../openaireLibrary/utils/icons/icons.module'; import {IconsModule} from '../../openaireLibrary/utils/icons/icons.module';
import {IconsService} from '../../openaireLibrary/utils/icons/icons.service'; import {IconsService} from '../../openaireLibrary/utils/icons/icons.service';
import {earth} from '../../openaireLibrary/utils/icons/icons'; import {earth, incognito, restricted} from '../../openaireLibrary/utils/icons/icons';
import {LogoUrlPipeModule} from "../../openaireLibrary/utils/pipes/logoUrlPipe.module"; import {LogoUrlPipeModule} from "../../openaireLibrary/utils/pipes/logoUrlPipe.module";
import {SearchInputModule} from '../../openaireLibrary/sharedComponents/search-input/search-input.module'; import {SearchInputModule} from '../../openaireLibrary/sharedComponents/search-input/search-input.module';
@ -24,6 +24,6 @@ import {SearchInputModule} from '../../openaireLibrary/sharedComponents/search-i
}) })
export class ManageCommunitiesModule { export class ManageCommunitiesModule {
constructor(private iconsService: IconsService) { constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([earth]); this.iconsService.registerIcons([earth, restricted, incognito]);
} }
} }

View File

@ -14,7 +14,6 @@ import {SearchPagingModule} from '../../openaireLibrary/searchPages/searchUtils/
import {AlertModalModule} from '../../openaireLibrary/utils/modal/alertModal.module'; import {AlertModalModule} from '../../openaireLibrary/utils/modal/alertModal.module';
import {CommonModule} from '@angular/common'; import {CommonModule} from '@angular/common';
import {PageContentModule} from "../../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module"; import {PageContentModule} from "../../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module";
import {CommunityInfoModule} from "../community-info/community-info.module";
import {InputModule} from "../../openaireLibrary/sharedComponents/input/input.module"; import {InputModule} from "../../openaireLibrary/sharedComponents/input/input.module";
import {SearchInputModule} from "../../openaireLibrary/sharedComponents/search-input/search-input.module"; import {SearchInputModule} from "../../openaireLibrary/sharedComponents/search-input/search-input.module";
import {NoLoadPaging} from "../../openaireLibrary/searchPages/searchUtils/no-load-paging.module"; import {NoLoadPaging} from "../../openaireLibrary/searchPages/searchUtils/no-load-paging.module";
@ -38,7 +37,6 @@ import {SearchFilterModule} from "../../openaireLibrary/searchPages/searchUtils/
AlertModalModule, AlertModalModule,
SearchProjectsServiceModule, SearchProjectsServiceModule,
PageContentModule, PageContentModule,
CommunityInfoModule,
InputModule, InputModule,
SearchInputModule, SearchInputModule,
RouterModule.forChild([ RouterModule.forChild([

View File

@ -1,16 +1,6 @@
<div page-content> <div page-content>
<div header>
<div class="uk-flex uk-flex-middle uk-margin-medium-top info">
<div>
<div class="uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage {{openaireEntiites.PROJECTS}}
</div>
<h1 class="uk-h6 uk-margin-remove">{{community.shortTitle}}</h1>
</div>
</div>
<community-info tab="projects"></community-info>
</div>
<div actions> <div actions>
<div class="uk-section-xsmall"> <div class="uk-section-xsmall uk-margin-top">
<div class="uk-flex uk-flex-middle"> <div class="uk-flex uk-flex-middle">
<div class="uk-width-expand@m uk-width-1-1 uk-grid uk-flex-middle uk-flex-right@m uk-flex-center uk-margin-remove-left" uk-grid> <div class="uk-width-expand@m uk-width-1-1 uk-grid uk-flex-middle uk-flex-right@m uk-flex-center uk-margin-remove-left" uk-grid>
<div search-input [expandable]="true" [searchControl]="filterForm.get('keyword')" searchInputClass="outer" <div search-input [expandable]="true" [searchControl]="filterForm.get('keyword')" searchInputClass="outer"

View File

@ -1,128 +1,316 @@
<div page-content> <div page-content>
<div header> <div actions>
<div class="uk-flex uk-flex-middle uk-margin-medium-top info"> <div class="uk-section-xsmall uk-margin-top">
<div> <div class="uk-flex uk-flex-right@m uk-flex-center uk-flex-middle uk-grid" uk-grid>
<div class="uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage Subjects <div [disabled]="loading" search-input class="uk-width-1-3@xl uk-width-2-5@l uk-width-1-2@m uk-width-1-1"
[searchControl]="filterForm" [expandable]="true" placeholder="Search Subjects" searchInputClass="outer">
</div>
<div>
<button class="uk-button uk-button-default uk-flex uk-flex-middle"
[disabled]="loading" [class.uk-disabled]="loading"
(click)="editAllSubjects()"
uk-tooltip="title:<div><div class='uk-margin-small-bottom uk-text-bold'>Add or edit subjects</div> All the research results associated to the subjects specified here will be automatically linked to the community dashboard in the next run of OpenAIRE workflows.</div>">
<span>Add/Edit Subjects</span>
</button>
</div> </div>
<h1 class="uk-h6 uk-margin-remove">{{community.shortTitle}}</h1>
</div> </div>
</div> </div>
<community-info tab="subjects"></community-info>
</div> </div>
<div actions>
<div class="uk-section-xsmall">
<div class="uk-flex uk-flex-right@m uk-flex-center uk-flex-middle uk-grid uk-margin-top" uk-grid>
<div [disabled]="showLoading" search-input class="uk-width-1-3@xl uk-width-2-5@l uk-width-1-2@m uk-width-1-1"
[searchControl]="filterForm" [expandable]="true" placeholder="Search Subjects" searchInputClass="outer">
</div>
<!-- <a *ngIf="!subjectsEnabled" (click)="enablePage()" class="uk-link-heading uk-text-small uk-text-uppercase"
uk-tooltip="title:<div class='uk-padding-small'>This information will be visible in <b>Subjects page</b> of Research Community Dashboard, which is <b>disabled</b>. <br> Click to enable id.</div>">
<span class="uk-text-secondary"><icon name="check_circle_outlined"></icon></span>
Enable page
</a>-->
<div>
<button class="uk-button uk-button-default uk-flex uk-flex-middle"
[disabled]="showLoading" [class.uk-disabled]="showLoading"
(click)="newSubject()"
uk-tooltip="title:<div><div class='uk-margin-small-bottom uk-text-bold'>Add new subjects</div> All the research results associated to the subjects specified here will be automatically linked to the community dashboard in the next run of OpenAIRE workflows.</div>">
<icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left">New Subject</span>
</button>
</div>
</div>
</div>
</div>
<div inner> <div inner>
<div class="uk-section uk-section-small uk-position-relative" style="min-height: 60vh"> <div class="uk-section uk-section-small uk-position-relative" style="min-height: 60vh">
<div *ngIf="showLoading" class="uk-position-center"> <div *ngIf="loading" class="uk-position-center">
<loading></loading> <loading></loading>
</div> </div>
<div *ngIf="!showLoading"> <div *ngIf="!loading">
<div *ngIf="community.subjects.length == 0" <div *ngIf="displayedSubjects?.length == 0 && displayedSdg?.length == 0 && displayedFos?.length == 0"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold"> class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div>No subjects <div>No subjects</div>
<span *ngIf="originalSubjects.length == 0; else: notFound">for {{community.shortTitle}}</span> </div>
<ng-template #notFound>found</ng-template> <div *ngIf="displayedSubjects?.length > 0 || displayedSdg?.length > 0 || displayedFos?.length > 0">
</div> <ul uk-tab class="uk-tab uk-margin-bottom uk-flex uk-flex-center uk-flex-left@m">
</div> <li class="uk-active" *ngIf="displayedAllSubjects?.length" (click)="groupSubjects(displayedAllSubjects, 'all')">
<div *ngIf="community.subjects.length > 0"> <a>All ({{displayedAllSubjects.length}})</a>
<no-load-paging *ngIf="community.subjects.length > 0" [type]="'Subjects'" </li>
[page]="page" [pageSize]="size" (pageChange)="updatePage($event)" <li *ngIf="displayedSubjects?.length" (click)="groupSubjects(displayedSubjects, 'freeText')">
[totalResults]="community.subjects.length"> <a>Free Text ({{displayedSubjects.length}})</a>
</no-load-paging> </li>
<div class="uk-grid uk-grid-large uk-grid-match uk-child-width-1-1 uk-child-width-1-2@m uk-margin-top uk-margin-bottom" uk-grid> <li *ngIf="displayedSdg?.length" (click)="groupSubjects(displayedSdg, 'sdg')">
<div *ngFor='let subject of currentPage; let i = index;'> <a>SDGs ({{displayedSdg.length}})</a>
<div class="uk-card uk-card-default"> </li>
<div class="uk-card-body"> <li *ngIf="displayedFos?.length" (click)="groupSubjects(displayedFos, 'fos')">
<h6 uk-tooltip="title:All the research results associated to this subjects will be automatically linked to the community dashboard." <a>Fields of Science ({{displayedFos.length}})</a>
class="uk-display-inline-block"> </li>
{{subject}} </ul>
</h6> <ul class="uk-switcher">
</div> <li *ngIf="displayedAllSubjects?.length">
<div class="uk-card-footer uk-padding-remove-vertical"> <ng-container *ngIf="groupedAllSubjects?.length">
<div class="uk-grid uk-grid-small uk-flex-nowrap uk-grid-divider uk-flex-right" uk-grid> <div>
<ul class="uk-nav uk-nav-default uk-flex uk-flex-wrap">
<li *ngFor="let item of groupedAllSubjects; let i = index;" class="uk-margin-right" [class.uk-margin-left]="i != 0"
[class]="indexAll == i ? 'uk-active':''" (click)="changeDisplayedSubjects(i, item)">
<a class="uk-padding-remove">{{item.group}}</a>
</li>
</ul>
</div>
<!-- View for 'All' -->
<div *ngIf="indexAll == 0 && groupedAllSubjects.length > 1" class="uk-margin-large-top uk-grid uk-child-width-1-4@m" uk-grid>
<div *ngFor="let item of groupedAllSubjects.slice(1); let i = index;">
<div> <div>
<div class="uk-padding-small uk-padding-remove-horizontal"> <h6>{{item.group}}</h6>
<a (click)="editSubject(subject)" <div *ngFor="let subItem of item.data.slice(0, subjectsLimit)" class="uk-margin-small-bottom">
class="uk-button uk-button-link uk-flex uk-flex-middle"> <span [attr.uk-tooltip]="subItem.length > maxCharacters ? 'cls: uk-active' : 'cls: uk-invisible'" [title]="subItem">
<icon name="edit" [flex]="true"></icon> {{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}
<span class="uk-margin-xsmall-left">Edit</span> </span>
</div>
<div *ngIf="item.data.length > subjectsLimit">
<a (click)="changeDisplayedSubjects(i+1, item)" class="view-more-less-link">
View all
</a> </a>
</div> </div>
</div> </div>
</div>
</div>
<!-- View for a single group -->
<div *ngIf="indexAll != 0 || groupedAllSubjects.length == 1" class="uk-margin-large-top">
<div>
<div> <div>
<div class="uk-padding-small uk-padding-remove-horizontal"> <h6>{{groupedAllSubjects[indexAll].group}}</h6>
<button class="uk-button uk-button-link uk-flex uk-flex-middle" <ng-container *ngIf="subjectsColumns?.length == 0; else elseBlock">
(click)="removeModalOpen(subject, i)"> <div *ngFor="let subItem of groupedAllSubjects[indexAll].data" class="uk-margin-small-bottom">
<icon name="delete" [flex]="true"></icon> <span [attr.uk-tooltip]="subItem.length > maxCharacters ? 'cls: uk-active' : 'cls: uk-invisible'" [title]="subItem">
<span class="uk-margin-xsmall-left">Delete</span> {{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}
</button> </span>
</div>
</ng-container>
<ng-template #elseBlock>
<div class="uk-grid uk-child-width-1-4@m" uk-grid>
<div *ngFor="let group of subjectsColumns">
<div *ngFor="let subItem of group" class="uk-margin-small-bottom">
<span [attr.uk-tooltip]="subItem.length > maxCharacters ? 'cls: uk-active' : 'cls: uk-invisible'" [title]="subItem">
{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}
</span>
</div>
</div>
</div>
</ng-template>
</div>
</div>
</div>
</ng-container>
</li>
<li *ngIf="displayedSubjects?.length">
<ng-container *ngIf="groupedSubjects?.length">
<div>
<ul class="uk-nav uk-nav-default uk-flex uk-flex-wrap">
<li *ngFor="let item of groupedSubjects; let i = index;" class="uk-margin-right" [class.uk-margin-left]="i != 0"
[class]="indexSubjects == i ? 'uk-active':''" (click)="changeDisplayedSubjects(i, item)">
<a class="uk-padding-remove">{{item.group}}</a>
</li>
</ul>
</div>
<!-- View for 'All' -->
<div *ngIf="indexSubjects == 0 && groupedSubjects.length > 1" class="uk-margin-large-top uk-grid uk-child-width-1-4@m" uk-grid>
<div *ngFor="let item of groupedSubjects.slice(1); let i = index;">
<div>
<h6>{{item.group}}</h6>
<div *ngFor="let subItem of item.data.slice(0, subjectsLimit)" class="uk-margin-small-bottom">
<span [attr.uk-tooltip]="subItem.length > maxCharacters ? 'cls: uk-active' : 'cls: uk-invisible'" [title]="subItem">
{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}
</span>
</div>
<div *ngIf="item.data.length > subjectsLimit">
<a (click)="changeDisplayedSubjects(i+1, item)" class="view-more-less-link">
View all
</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> <!-- View for a single group -->
</div> <div *ngIf="indexSubjects != 0 || groupedSubjects.length == 1" class="uk-margin-large-top">
</div> <div>
<div class="uk-margin-small-top"> <div>
<paging-no-load [currentPage]="page" [totalResults]="community.subjects.length" [size]="size" <h6>{{groupedSubjects[indexSubjects]?.group}}</h6>
(pageChange)="updatePage($event)" customClasses="uk-flex-right@m uk-flex-center"> <ng-container *ngIf="subjectsColumns?.length == 0; else elseBlock">
</paging-no-load> <div *ngFor="let subItem of groupedSubjects[indexSubjects]?.data" class="uk-margin-small-bottom">
</div> <span [attr.uk-tooltip]="subItem.length > maxCharacters ? 'cls: uk-active' : 'cls: uk-invisible'" [title]="subItem">
</div> {{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}
</div> </span>
</div> </div>
</ng-container>
<ng-template #elseBlock>
<div class="uk-grid uk-child-width-1-4@m" uk-grid>
<div *ngFor="let group of subjectsColumns">
<div *ngFor="let subItem of group" class="uk-margin-small-bottom">
<span [attr.uk-tooltip]="subItem.length > maxCharacters ? 'cls: uk-active' : 'cls: uk-invisible'" [title]="subItem">
{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}
</span>
</div>
</div>
</div>
</ng-template>
</div>
</div>
</div>
</ng-container>
</li>
<li *ngIf="displayedSdg?.length">
<ng-container *ngIf="groupedSdg?.length">
<div>
<ul class="uk-nav uk-nav-default uk-flex uk-flex-wrap">
<li *ngFor="let item of groupedSdg; let i = index;" class="uk-margin-right" [class.uk-margin-left]="i != 0"
[class]="indexSdg == i ? 'uk-active':''" (click)="changeDisplayedSubjects(i, item)">
<a class="uk-padding-remove">{{item.group}}</a>
</li>
</ul>
</div>
<!-- View for 'All' -->
<div *ngIf="indexSdg == 0 && groupedSdg.length > 1" class="uk-margin-large-top uk-grid uk-child-width-1-4@m" uk-grid>
<div *ngFor="let item of groupedSdg.slice(1); let i = index;">
<div>
<h6>{{item.group}}</h6>
<div *ngFor="let subItem of item.data.slice(0, subjectsLimit)" class="uk-margin-small-bottom">
<span [attr.uk-tooltip]="subItem.length > maxCharacters ? 'cls: uk-active' : 'cls: uk-invisible'" [title]="subItem">
{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}
</span>
</div>
<div *ngIf="item.data.length > subjectsLimit">
<a (click)="changeDisplayedSubjects(i+1, item)" class="view-more-less-link">
View all
</a>
</div>
</div>
</div>
</div>
<!-- View for a single group -->
<div *ngIf="indexSdg != 0 || groupedSdg.length == 1" class="uk-margin-large-top">
<div>
<div>
<h6>{{groupedSdg[indexSdg].group}}</h6>
<ng-container *ngIf="subjectsColumns?.length == 0; else elseBlock">
<div *ngFor="let subItem of groupedSdg[indexSdg].data" class="uk-margin-small-bottom">
<span [attr.uk-tooltip]="subItem.length > maxCharacters ? 'cls: uk-active' : 'cls: uk-invisible'" [title]="subItem">
{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}
</span>
</div>
</ng-container>
<ng-template #elseBlock>
<div class="uk-grid uk-child-width-1-4@m" uk-grid>
<div *ngFor="let group of subjectsColumns">
<div *ngFor="let subItem of group" class="uk-margin-small-bottom">
<span [attr.uk-tooltip]="subItem.length > maxCharacters ? 'cls: uk-active' : 'cls: uk-invisible'" [title]="subItem">
{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}
</span>
</div>
</div>
</div>
</ng-template>
</div>
</div>
</div>
</ng-container>
</li>
<li *ngIf="displayedFos?.length">
<ng-container *ngIf="groupedFos?.length">
<div>
<ul class="uk-nav uk-nav-default uk-flex uk-flex-wrap">
<li *ngFor="let item of groupedFos; let i = index;" class="uk-margin-right" [class.uk-margin-left]="i != 0"
[class]="indexFos == i ? 'uk-active':''" (click)="changeDisplayedSubjects(i, item)">
<a class="uk-padding-remove">{{item.group}}</a>
</li>
</ul>
</div>
<!-- View for 'All' -->
<div *ngIf="indexFos == 0 && groupedFos.length > 1" class="uk-margin-large-top uk-grid uk-child-width-1-4@m" uk-grid>
<div *ngFor="let item of groupedFos.slice(1); let i = index;">
<div>
<h6>{{item.group}}</h6>
<div *ngFor="let subItem of item.data.slice(0, subjectsLimit)" class="uk-margin-small-bottom">
<span [attr.uk-tooltip]="subItem.length > maxCharacters ? 'cls: uk-active' : 'cls: uk-invisible'" [title]="subItem">
{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}
</span>
</div>
<div *ngIf="item.data.length > subjectsLimit">
<a (click)="changeDisplayedSubjects(i+1, item)" class="view-more-less-link">
View all
</a>
</div>
</div>
</div>
</div>
<!-- View for a single group -->
<div *ngIf="indexFos != 0 || groupedFos.length == 1" class="uk-margin-large-top">
<div>
<div>
<h6>{{groupedFos[indexFos].group}}</h6>
<ng-container *ngIf="subjectsColumns?.length == 0; else elseBlock">
<div *ngFor="let subItem of groupedFos[indexFos].data" class="uk-margin-small-bottom">
<span [attr.uk-tooltip]="subItem.length > maxCharacters ? 'cls: uk-active' : 'cls: uk-invisible'" [title]="subItem">
{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}
</span>
</div>
</ng-container>
<ng-template #elseBlock>
<div class="uk-grid uk-child-width-1-4@m" uk-grid>
<div *ngFor="let group of subjectsColumns">
<div *ngFor="let subItem of group" class="uk-margin-small-bottom">
<span [attr.uk-tooltip]="subItem.length > maxCharacters ? 'cls: uk-active' : 'cls: uk-invisible'" [title]="subItem">
{{subItem.length > maxCharacters ? subItem.substring(0,maxCharacters)+'...' : subItem}}
</span>
</div>
</div>
</div>
</ng-template>
</div>
</div>
</div>
</ng-container>
</li>
</ul>
</div>
</div>
</div>
</div> </div>
</div> </div>
<modal-alert #deleteModal (alertOutput)="saveSubjects()" [overflowBody]="false" classTitle="uk-background-primary uk-light"></modal-alert> <fs-modal #fsModal classBody="uk-container-large" (okEmitter)="saveAllSubjects()" [okButtonDisabled]="!hasChanges && !sdgSelection.hasChanges && !fosSelection.hasChanges">
<fs-modal #fsModal classBody="uk-container-small" (okEmitter)="saveSubjects()" [okButtonDisabled]="myForm && (myForm.invalid || !myForm.dirty)"> <div>
<form *ngIf="myForm"> <ul uk-tab #modalTabs class="uk-tab uk-margin-top uk-margin-large-bottom uk-flex uk-flex-center uk-flex-left@m">
<div class="uk-margin-top uk-flex-center uk-flex uk-margin-medium-bottom"> <li class="uk-active">
<a *ngIf="!isEditModal" (click)="addSubjectInForm()"> <a>Free Text ({{displayedSubjects.length}})</a>
<button class="uk-button uk-button-primary uk-flex uk-flex-middle"> </li>
<icon name="add" [flex]="true"></icon> <li>
<span class="uk-margin-xsmall-left">Add Subject</span> <a>SDGs ({{sdgSelection.getSelectedSubjects().length}})<span *ngIf="sdgSelection.hasChanges">*</span></a>
</button> </li>
</a> <li>
</div> <a>Fields of Science ({{fosSelection.getSelectedSubjects().length}})<span *ngIf="fosSelection.hasChanges">*</span></a>
<div class="uk-grid uk-child-width-1-1" uk-grid> </li>
<div *ngFor=" let control of myForm.controls; index as i" class="uk-flex uk-flex-middle"> </ul>
<div input [formInput]="myForm.controls[i]" type="text" <ul class="uk-switcher">
placeholder="Type subjects as free text keywords" class="uk-width-expand"></div> <li *ngIf="subjectsForm">
<div *ngIf="!isEditModal" class="uk-width-auto uk-flex uk-flex-center uk-margin-left"> <div #addSubjectsInput input [type]="'chips'" [formInput]="subjectsForm" [inputClass]="'flat small'" [extendEnter]="onEnter"
<button class="uk-close uk-icon" [class.uk-invisible]="myForm.length === 1" [separators]="[',', 'enter']" [visibleChips]="3" class="uk-width-1-1 uk-width-xlarge@m"
(click)="removeSubjectInForm(i)"> [placeholder]="{static: true, label: 'Type subjects as free text keywords'}">
<icon name="close" [flex]="true" [ratio]="1.5"></icon> <div tools class="uk-flex uk-flex-right">
</button> <button (click)="addSubjectsIntoList()" class="uk-button uk-button-link uk-margin-xsmall-left uk-margin-right">add</button>
</div> </div>
</div> <div note class="uk-text-xsmall">Separate subjects with commas</div>
</div> </div>
</form> <div class="uk-margin-large-top">
</fs-modal> <span *ngFor="let subject of displayedSubjects; let i = index;"
<!--<modal-alert #enablePageModal (alertOutput)="enablePage()"> class="uk-label uk-label-primary uk-flex-inline uk-flex-middle uk-margin-right uk-margin-bottom">
<div class="uk-padding uk-padding-remove-horizontal"> <span class="uk-margin-small-right uk-text-truncate">{{subject}}</span>
This information will be visible in <span class="uk-text-bold">Subjects page</span> of Research Community <button (click)="removeSubjectFromList(i)" class="uk-close uk-icon">
Dashboard, which is <span class="uk-text-bold">disabled</span>. <icon name="close" flex="true" ratio="0.7"></icon>
Do you want to <span class="uk-text-bold">enable</span> it now? </button>
</span>
</div>
</li>
<li>
<sdg-selection #sdgSelection [subjects]="displayedSdg" [isFeedback]="false"></sdg-selection>
</li>
<li>
<fos-selection #fosSelection [subjects]="displayedFos" [inModal]="true"></fos-selection>
</li>
</ul>
</div> </div>
</modal-alert>--> </fs-modal>

View File

@ -1,6 +1,6 @@
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {UntypedFormArray, UntypedFormBuilder, UntypedFormControl} from '@angular/forms'; import {UntypedFormArray, UntypedFormBuilder, UntypedFormControl} from '@angular/forms';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute} from '@angular/router';
import {CommunityService} from '../../../openaireLibrary/connect/community/community.service'; import {CommunityService} from '../../../openaireLibrary/connect/community/community.service';
import {SubjectsService} from '../subjects.service'; import {SubjectsService} from '../subjects.service';
import {EnvProperties} from '../../../openaireLibrary/utils/properties/env-properties'; import {EnvProperties} from '../../../openaireLibrary/utils/properties/env-properties';
@ -8,67 +8,104 @@ import {Title} from '@angular/platform-browser';
import {properties} from '../../../../environments/environment'; import {properties} from '../../../../environments/environment';
import {AlertModal} from '../../../openaireLibrary/utils/modal/alert'; import {AlertModal} from '../../../openaireLibrary/utils/modal/alert';
import {SearchInputComponent} from '../../../openaireLibrary/sharedComponents/search-input/search-input.component'; import {SearchInputComponent} from '../../../openaireLibrary/sharedComponents/search-input/search-input.component';
import {Subscription} from 'rxjs'; import {forkJoin, Subscription} from 'rxjs';
import {CommunityInfo} from '../../../openaireLibrary/connect/community/communityInfo'; import {CommunityInfo} from '../../../openaireLibrary/connect/community/communityInfo';
import {FullScreenModalComponent} from 'src/app/openaireLibrary/utils/modal/full-screen-modal/full-screen-modal.component'; import {FullScreenModalComponent} from 'src/app/openaireLibrary/utils/modal/full-screen-modal/full-screen-modal.component';
import {HelperFunctions} from 'src/app/openaireLibrary/utils/HelperFunctions.class'; import {HelperFunctions} from 'src/app/openaireLibrary/utils/HelperFunctions.class';
import {NotificationHandler} from "../../../openaireLibrary/utils/notification-handler"; import {NotificationHandler} from "../../../openaireLibrary/utils/notification-handler";
import {ClearCacheService} from "../../../openaireLibrary/services/clear-cache.service"; import {ClearCacheService} from "../../../openaireLibrary/services/clear-cache.service";
import {SdgSelectionComponent} from '../../../openaireLibrary/sdg/sdg-selection/sdg-selection.component';
import {FosSelectionComponent} from '../../../openaireLibrary/fos/fos-selection/fos-selection.component';
import {InputComponent} from "../../../openaireLibrary/sharedComponents/input/input.component";
declare var UIkit: any;
@Component({ @Component({
selector: 'subjects-edit-form', selector: 'subjects-edit-form',
templateUrl: './subjects-edit-form.component.html', templateUrl: './subjects-edit-form.component.html',
}) })
export class SubjectsEditFormComponent implements OnInit { export class SubjectsEditFormComponent implements OnInit {
myForm = new UntypedFormArray([new UntypedFormControl({subject: ''})]); properties: EnvProperties = properties;
public showLoading = true; communityId: string = null;
public res = []; community: CommunityInfo = null;
loading = true;
params: any; params: any;
public communityId: string = null; private subscriptions: any[] = [];
public community: CommunityInfo = null;
public properties: EnvProperties = properties; filterForm: UntypedFormControl;
public edit = null; subjectsForm = new UntypedFormArray([]);
public originalSubjects = []; hasChanges: boolean = false;
originalAllSubjects = [];
originalSubjects = [];
originalSdg = [];
originalFos = [];
displayedAllSubjects = [];
displayedSubjects = [];
displayedSdg = [];
displayedFos = [];
groupedAllSubjects = [];
groupedSubjects = [];
groupedSdg = [];
groupedFos = [];
subjectsColumns = [];
subjectsLimit: number = 6;
maxCharacters: number = 25;
activeTab: 'all' | 'freeText' | 'sdg' | 'fos' = 'all';
indexAll: number = 0;
indexSubjects: number = 0;
indexSdg: number = 0;
indexFos: number = 0;
@ViewChild('addSubjectsInput') addSubjectsInput: InputComponent;
@ViewChild('editModal') editModal: AlertModal; @ViewChild('editModal') editModal: AlertModal;
@ViewChild('deleteModal') deleteModal: AlertModal; @ViewChild('deleteModal') deleteModal: AlertModal;
@ViewChild('fsModal', {static: true}) fullscreen: FullScreenModalComponent; @ViewChild('fsModal', {static: true}) fullscreen: FullScreenModalComponent;
page = 1; @ViewChild('modalTabs') modalTabs: ElementRef;
size = 10; @ViewChild('sdgSelection') sdgSelection: SdgSelectionComponent;
selectedSubjects = []; @ViewChild('fosSelection') fosSelection: FosSelectionComponent;
isEditModal: boolean = false;
public selectedKeyword: string; onEnter: () => void = () => {
@ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent; this.addSubjectsIntoList();
public filterForm: UntypedFormControl; }
private subscriptions: any[] = [];
/*//Check again functionality to enable page constructor(private route: ActivatedRoute,
subjectsPage;
@ViewChild('enablePageModal') enablePageModal: AlertModal;*/
constructor(private element: ElementRef,
private route: ActivatedRoute,
private _router: Router,
public _fb: UntypedFormBuilder, public _fb: UntypedFormBuilder,
private title: Title, private title: Title,
// private _helpContentService: HelpContentService,
private _communityService: CommunityService, private _communityService: CommunityService,
private _subjectsService: SubjectsService, private _subjectsService: SubjectsService,
private _clearCacheService: ClearCacheService private _clearCacheService: ClearCacheService) {
) { }
}
ngOnInit() { ngOnInit() {
this.filterForm = this._fb.control(''); this.filterForm = this._fb.control('');
this.subscriptions.push(this.filterForm.valueChanges.subscribe(value => { this.subscriptions.push(this.filterForm.valueChanges.subscribe(value => {
this.page = 1; this.displayedAllSubjects = this.originalAllSubjects.filter(subject => {
this.community.subjects = this.originalSubjects.filter(subject => {
return !value || subject.toLowerCase().indexOf(value.toLowerCase()) != -1 return !value || subject.toLowerCase().indexOf(value.toLowerCase()) != -1
}); });
this.displayedSubjects = this.originalSubjects.filter(subject => {
return !value || subject.toLowerCase().indexOf(value.toLowerCase()) != -1
});
this.displayedSdg = this.originalSdg.filter(subject => {
return !value || subject.toLowerCase().indexOf(value.toLowerCase()) != -1
});
this.displayedFos = this.originalFos.filter(subject => {
return !value || subject.toLowerCase().indexOf(value.toLowerCase()) != -1
});
if(this.activeTab === 'all') {
this.groupSubjects(this.displayedAllSubjects, 'all');
} else if(this.activeTab === 'freeText') {
this.groupSubjects(this.displayedSubjects, 'freeText');
} else if(this.activeTab === 'sdg') {
this.groupSubjects(this.displayedSdg, 'sdg');
} else if(this.activeTab === 'fos') {
this.groupSubjects(this.displayedFos, 'fos');
}
})); }));
this.subscriptions.push(this.route.params.subscribe( this.subscriptions.push(this.route.params.subscribe(
params => { params => {
this.communityId = params['community']; this.communityId = params['community'];
this.title.setTitle(this.communityId.toUpperCase() + ' | Subjects'); this.title.setTitle(this.communityId.toUpperCase() + ' | Subjects');
this.showLoading = true; this.loading = true;
this.subscriptions.push(this._communityService.getCommunityAsObservable().subscribe( this.subscriptions.push(this._communityService.getCommunityAsObservable().subscribe(
community => { community => {
this.community = community; this.community = community;
@ -85,19 +122,19 @@ export class SubjectsEditFormComponent implements OnInit {
} }
return 0; return 0;
}); });
this.displayedSubjects = HelperFunctions.copy(this.community.subjects);
this.originalSubjects = []; this.displayedSdg = this.community.sdg;
for (let i = 0; i < this.community.subjects.length; i++) { this.displayedFos = this.community.fos;
this.originalSubjects.push(this.community.subjects[i]); this.displayedAllSubjects = [...this.displayedSubjects, ...this.displayedSdg, ...this.displayedFos];
} this.groupSubjects(this.displayedAllSubjects, 'all');
if (this.community.subjects.length === 0) { this.originalAllSubjects = HelperFunctions.copy(this.displayedAllSubjects);
this.community.subjects.push(''); this.originalSubjects = HelperFunctions.copy(this.displayedSubjects);
} this.originalSdg = HelperFunctions.copy(this.displayedSdg);
this.showLoading = false; this.originalFos = HelperFunctions.copy(this.displayedFos);
this.loading = false;
}, },
error => this.handleUpdateError('System error retrieving community profile', error) error => this.handleUpdateError('System error retrieving community profile', error)
)); ));
// this.getSubjectsPageStatus();
})); }));
} }
@ -109,19 +146,109 @@ export class SubjectsEditFormComponent implements OnInit {
} }
}); });
} }
private removeModalOpen(subject: string, i: any) { public groupSubjects(subjects: string[], type: string) {
this.selectedSubjects = [subject]; if(subjects.length === 0) {
this.reset(['']); return [];
this.deleteModal.cancelButton = true; }
this.deleteModal.okButton = true; subjects.sort((a, b) => a.localeCompare(b));
this.deleteModal.alertTitle = 'Delete Subject'; if(type === 'all') {
this.deleteModal.message = 'Are you sure you want to delete this subject?'; this.indexAll = 0;
this.deleteModal.okButtonText = 'Yes'; this.activeTab = 'all';
this.deleteModal.cancelButtonText = 'No'; this.groupedAllSubjects = Object.values(
this.deleteModal.open(); subjects.reduce((acc, subject) => {
} let firstLetter = subject[0].toLocaleUpperCase();
if(!acc[firstLetter]) {
acc[firstLetter] = {group: firstLetter, data: [subject]};
} else {
acc[firstLetter].data.push(subject);
}
return acc;
},{})
)
if(subjects.length > 1) {
this.groupedAllSubjects.unshift({group: 'All', data: subjects});
}
}
if(type === 'freeText') {
this.indexSubjects = 0;
this.activeTab = 'freeText';
this.groupedSubjects = Object.values(
subjects.reduce((acc, subject) => {
let firstLetter = subject[0].toLocaleUpperCase();
if(!acc[firstLetter]) {
acc[firstLetter] = {group: firstLetter, data: [subject]};
} else {
acc[firstLetter].data.push(subject);
}
return acc;
},{})
)
if(subjects.length > 1) {
this.groupedSubjects.unshift({group: 'All', data: subjects});
}
}
if(type === 'sdg') {
this.indexSdg = 0;
this.activeTab = 'sdg';
this.groupedSdg = Object.values(
subjects.reduce((acc, subject) => {
let firstLetter = subject[0].toLocaleUpperCase();
if(!acc[firstLetter]) {
acc[firstLetter] = {group: firstLetter, data: [subject]};
} else {
acc[firstLetter].data.push(subject);
}
return acc;
},{})
)
if(subjects.length > 1) {
this.groupedSdg.unshift({group: 'All', data: subjects});
}
}
if(type === 'fos') {
this.indexFos = 0;
this.activeTab = 'fos';
this.groupedFos = Object.values(
subjects.reduce((acc, subject) => {
let key = subject.substring(0,2).toLocaleUpperCase();
if(!acc[key]) {
acc[key] = {group: key, data: [subject]};
} else {
acc[key].data.push(subject);
}
return acc;
},{})
)
if(subjects.length > 1) {
this.groupedFos.unshift({group: 'All', data: subjects});
}
}
}
public changeDisplayedSubjects(i, group) {
this.subjectsColumns = [];
if(this.activeTab === 'all') {
this.indexAll = i;
} else if(this.activeTab === 'freeText') {
this.indexSubjects = i;
} else if(this.activeTab === 'sdg') {
this.indexSdg = i;
} else if(this.activeTab === 'fos') {
this.indexFos = i;
}
if(group.data.length > this.subjectsLimit && group.group != 'All') {
this.divideSubjects(group);
}
}
public divideSubjects(group) {
let columns = [];
for(let i = 0; i < (group.data.length / this.subjectsLimit); i++) {
columns.push(group.data.slice(i * this.subjectsLimit, ((i + 1) * this.subjectsLimit)));
}
this.subjectsColumns = columns;
}
public getSubjectsExistOnlyInFirst(firstArray: string[], secondArray: string[]): string[] { public getSubjectsExistOnlyInFirst(firstArray: string[], secondArray: string[]): string[] {
const difference = []; const difference = [];
@ -129,41 +256,70 @@ export class SubjectsEditFormComponent implements OnInit {
if (secondArray.indexOf(firstArray[i]) === -1) { if (secondArray.indexOf(firstArray[i]) === -1) {
difference.push(firstArray[i]); difference.push(firstArray[i]);
} }
} }
return difference; return difference;
} }
public editAllSubjects() {
UIkit.tab(this.modalTabs.nativeElement).show(0);
this.displayedSubjects = HelperFunctions.copy(this.community.subjects);
this.sdgSelection.reset();
this.sdgSelection.sdgs.markAsPristine();
this.fosSelection.reset();
this.fosSelection.fosOptions.markAsPristine();
this.fullscreen.title = "Add/Edit Subjects";
this.fullscreen.okButtonText = "Save";
this.fullscreen.back = true;
this.fullscreen.okButton = true;
this.fullscreen.open();
}
public addSubjectsIntoList() {
if(this.addSubjectsInput.searchControl.getRawValue()) {
this.addSubjectsInput.add(null, true);
}
this.subjectsForm.getRawValue().forEach(element => {
this.displayedSubjects.unshift(element);
});
this.subjectsForm.clear();
this.hasChanges = true;
}
public removeSubjectFromList(i) {
this.displayedSubjects.splice(i, 1);
this.hasChanges = true;
}
public saveAllSubjects() {
let selectedSdg = this.sdgSelection.getSelectedSubjects().map(a => a.id);
let selectedFos = this.fosSelection.getSelectedSubjects().map(a => a.id);
let requests = [
...this.saveSubjects(this.community.subjects, this.displayedSubjects, 'subjects'),
...this.saveSubjects(this.community.sdg, selectedSdg, 'sdg'),
...this.saveSubjects(this.community.fos, selectedFos, 'fos')
];
this.subscriptions.push(forkJoin(requests).subscribe(res => {
this.afterUpdateActions(res, "updated");
}));
}
public saveSubjects() { public saveSubjects(subjects, displayedSubjects, type: string) {
if (this.communityId != null && this.communityId !== '') { if (this.communityId != null && this.communityId !== '') {
this.showLoading = true; this.loading = true;
const subjectsToDeleteAr = this.getSubjectsExistOnlyInFirst(this.selectedSubjects, this.myForm.getRawValue()); const subjectsToDeleteAr = this.getSubjectsExistOnlyInFirst(subjects, displayedSubjects);
const subjectsToAddAr = this.getSubjectsExistOnlyInFirst(this.myForm.getRawValue(), this.selectedSubjects); const subjectsToAddAr = this.getSubjectsExistOnlyInFirst(displayedSubjects, subjects);
const subjectsToDelete = this.getNonEmptyItems(subjectsToDeleteAr); const subjectsToDelete = this.getNonEmptyItems(subjectsToDeleteAr);
const subjectsToAdd = this.getNonEmptyItems(subjectsToAddAr); const subjectsToAdd = this.getNonEmptyItems(subjectsToAddAr);
if (subjectsToAdd.length > 0 && subjectsToDelete.length > 0) { let requests = [];
this.subscriptions.push(this._subjectsService.removeSubjects( if (subjectsToDelete.length > 0) {
this.properties.communityAPI + this.communityId + '/subjects', subjectsToDelete).subscribe(res =>{ requests.push(this._subjectsService.removeSubjects(
this.subscriptions.push(this._subjectsService.addSubjects( this.properties.communityAPI + this.communityId + '/' + type, subjectsToDelete))
this.properties.communityAPI + this.communityId + '/subjects', subjectsToAdd).subscribe(res => {
this.afterUpdateActions(res, "added");
}));
}));
} else if (subjectsToAdd.length > 0) {
this.subscriptions.push(this._subjectsService.addSubjects(
this.properties.communityAPI + this.communityId + '/subjects', subjectsToAdd).subscribe(res => {
this.afterUpdateActions(res, "added");
},
error => this.handleUpdateError('System error updating subjects', error)
));
} else if (subjectsToDelete.length > 0) {
this.subscriptions.push(this._subjectsService.removeSubjects(
this.properties.communityAPI + this.communityId + '/subjects', subjectsToDelete).subscribe(res => {
this.afterUpdateActions(res, "deleted");
},
error => this.handleUpdateError('System error updating subjects', error)
));
} }
if (subjectsToAdd.length > 0) {
requests.push(this._subjectsService.addSubjects(
this.properties.communityAPI + this.communityId + '/' + type, subjectsToAdd))
}
return requests;
} }
} }
@ -172,32 +328,23 @@ export class SubjectsEditFormComponent implements OnInit {
console.error(error) console.error(error)
} }
NotificationHandler.rise(message, 'danger'); NotificationHandler.rise(message, 'danger');
this.showLoading = false; this.loading = false;
} }
afterUpdateActions(res, message: string) { afterUpdateActions(response, message: string) {
this._communityService.setCommunity(this._communityService.parseCommunity(res)); response.forEach(res => {
this.community.subjects = res['subjects']; if (res.subjects) {
this.originalSubjects = []; this.community.subjects = res.subjects;
for (let i = 0; i < this.community.subjects.length; i++) { } else if (res.sdg) {
this.originalSubjects.push(this.community.subjects[i]); this.community.sdg = res.sdg;
} } else if (res.fos) {
this.originalSubjects.sort((n1,n2)=> { this.community.fos = res.fos;
if (n1.toLowerCase() > n2.toLowerCase()) { }
return 1; });
} this._communityService.updateSubjects(this.community.subjects, this.community.fos, this.community.sdg);
if (n1.toLowerCase() < n2.toLowerCase()) { this._clearCacheService.purgeBrowserCache("Subjects "+message, this.communityId);
return -1; NotificationHandler.rise('Subjects successfully ' + message + '!')
} this.loading = false;
return 0;
});
this.page = 1;
this.community.subjects = this.originalSubjects.filter(subject => {
return !this.filterForm.value || subject.toLowerCase().indexOf(this.filterForm.value.toLowerCase()) != -1
}).sort();
this._clearCacheService.purgeBrowserCache("Subject "+message, this.communityId);
NotificationHandler.rise('Subject successfully ' + message + '!')
this.showLoading = false;
} }
@ -231,111 +378,4 @@ export class SubjectsEditFormComponent implements OnInit {
return false; return false;
} }
} }
public addSubjectInForm() {
this.myForm.push(new UntypedFormControl(''));
}
public removeSubjectInForm(i: number) {
this.myForm.removeAt(i);
}
public reset(subjects: string[]) {
this.myForm = new UntypedFormArray([]);
for (let subject in subjects) {
this.myForm.push(new UntypedFormControl(''));
}
this.myForm.patchValue(subjects);
}
newSubject() {
this.isEditModal = false;
this.selectedSubjects = [];
this.reset([""]);
this.fullscreen.title = "Add Subject";
this.fullscreen.okButtonText = "Save";
this.fullscreen.back = true;
this.fullscreen.okButton = true;
this.fullscreen.open();
}
get currentPage() {
if(this.community.subjects) {
return this.community.subjects.slice((this.page - 1) * this.size, this.page * this.size);
} else {
return [];
}
}
public updatePage(event) {
this.page = event.value;
HelperFunctions.scroll();
}
public editSubject(subject: string) {
this.isEditModal = true;
this.selectedSubjects = [subject];
this.reset([subject]);
this.fullscreen.title = "Edit Subject";
this.fullscreen.okButtonText = "Save";
this.fullscreen.back = true;
this.fullscreen.okButton = true;
this.fullscreen.open();
}
private formModalOpen(title: string, yesBtn: string) {
this.editModal.okButtonLeft = false;
this.editModal.cancelButton = true;
this.editModal.okButton = true;
this.editModal.alertTitle = title;
this.editModal.okButtonText = yesBtn;
this.editModal.open();
}
public onSearchClose() {
this.selectedKeyword = this.filterForm.value;
}
public resetInput() {
this.selectedKeyword = null;
this.searchInputComponent.reset()
}
/*
//Check again functionality to enable page
private getSubjectsPageStatus() {
this._helpContentService.getCommunityPagesByRoute(this.communityId, '/subjects', this.properties.adminToolsAPIURL).subscribe((page) => {
this.subjectsPage = page;
});
}
public get subjectsEnabled(): boolean {
return !this.subjectsPage || this.subjectsPage.isEnabled;
}
enablePage() {
this._helpContentService.togglePages(this.communityId, [this.subjectsPage._id], true, this.properties.adminToolsAPIURL).subscribe(() => {
this.subjectsPage.isEnabled = true;
UIkit.notification('Curators Page has been <b>enabled successfully</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
},error => {
this.subjectsPage.isEnabled = false;
UIkit.notification('An error occured', {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
});
}
private curatorsEnabledOpen() {
this.enablePageModal.okButtonLeft = false;
this.enablePageModal.alertTitle = 'Enable Subjects Page';
this.enablePageModal.okButtonText = 'Yes';
this.enablePageModal.cancelButtonText = 'No';
this.enablePageModal.open();
}*/
} }

View File

@ -13,14 +13,17 @@ import {AlertModalModule} from '../../../openaireLibrary/utils/modal/alertModal.
import {NoLoadPaging} from '../../../openaireLibrary/searchPages/searchUtils/no-load-paging.module'; import {NoLoadPaging} from '../../../openaireLibrary/searchPages/searchUtils/no-load-paging.module';
import {LoadingModule} from '../../../openaireLibrary/utils/loading/loading.module'; import {LoadingModule} from '../../../openaireLibrary/utils/loading/loading.module';
import {InputModule} from '../../../openaireLibrary/sharedComponents/input/input.module'; import {InputModule} from '../../../openaireLibrary/sharedComponents/input/input.module';
import {CommunityInfoModule} from '../../community-info/community-info.module';
import {SearchInputModule} from '../../../openaireLibrary/sharedComponents/search-input/search-input.module'; import {SearchInputModule} from '../../../openaireLibrary/sharedComponents/search-input/search-input.module';
import {FullScreenModalModule} from 'src/app/openaireLibrary/utils/modal/full-screen-modal/full-screen-modal.module'; import {FullScreenModalModule} from 'src/app/openaireLibrary/utils/modal/full-screen-modal/full-screen-modal.module';
import {PagingModule} from "../../../openaireLibrary/utils/paging.module"; import {PagingModule} from "../../../openaireLibrary/utils/paging.module";
import {SdgSelectionModule} from '../../../openaireLibrary/sdg/sdg-selection/sdg-selection.module';
import {FosSelectionModule} from '../../../openaireLibrary/fos/fos-selection/fos-selection.module';
@NgModule({ @NgModule({
imports: [ imports: [
SubjectsEditFormRoutingModule, CommonModule, FormsModule, RouterModule, PageContentModule, IconsModule, AlertModalModule, NoLoadPaging, LoadingModule, InputModule, CommunityInfoModule, SearchInputModule, FullScreenModalModule, PagingModule SubjectsEditFormRoutingModule, CommonModule, FormsModule, RouterModule,
PageContentModule, IconsModule, AlertModalModule, NoLoadPaging, LoadingModule, InputModule,
SearchInputModule, FullScreenModalModule, PagingModule, SdgSelectionModule, FosSelectionModule
], ],
declarations: [ declarations: [
SubjectsEditFormComponent SubjectsEditFormComponent

View File

@ -1,11 +1,5 @@
<div page-content> <div page-content>
<div header> <div header>
<div class="uk-flex uk-flex-middle uk-margin-medium-top info">
<div>
<div class="uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage Notification Settings</div>
<h1 class="uk-h6 uk-margin-remove">{{community.shortTitle}}</h1>
</div>
</div>
<users-tabs tab="notifications"></users-tabs> <users-tabs tab="notifications"></users-tabs>
</div> </div>
<div actions> <div actions>

View File

@ -25,18 +25,10 @@ declare var UIkit;
template: ` template: `
<div page-content> <div page-content>
<div header> <div header>
<div class="uk-flex uk-flex-middle uk-margin-medium-top info">
<div>
<div class="uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage Personal Info &
Affiliations
</div>
<h1 class="uk-h6 uk-margin-remove">{{community.shortTitle}}</h1>
</div>
</div>
<users-tabs tab="personal"></users-tabs> <users-tabs tab="personal"></users-tabs>
</div> </div>
<div actions> <div actions>
<div class="uk-container uk-section-xsmall"> <div class="uk-container uk-section-xsmall uk-margin-top">
<div class="uk-flex uk-flex-middle uk-flex-center uk-flex-right@m"> <div class="uk-flex uk-flex-middle uk-flex-center uk-flex-right@m">
<button class="uk-button uk-button-secondary" [class.uk-disabled]="!hasChanged || loading" <button class="uk-button uk-button-secondary" [class.uk-disabled]="!hasChanged || loading"
[disabled]="!hasChanged || loading" [disabled]="!hasChanged || loading"

View File

@ -12,13 +12,8 @@ import {CommunityInfo} from "../../../openaireLibrary/connect/community/communit
selector: 'users-managers', selector: 'users-managers',
template: ` template: `
<role-users [id]="community.communityId" [type]="community.type" [name]="community.shortTitle" [inviteDisableMessage]="inviteDisableMessage" <role-users [id]="community.communityId" [type]="community.type" [name]="community.shortTitle" [inviteDisableMessage]="inviteDisableMessage"
[link]="link" [role]="'manager'" [message]="message" [emailComposer]="emailComposer"> [link]="link" [role]="'manager'" [deleteAuthorizationLevel]="'manager'"
<div class="uk-flex uk-flex-middle uk-margin-medium-top info"> [message]="message" [emailComposer]="emailComposer">
<div>
<div class="uk-margin-remove uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage Users</div>
<h1 class="uk-h6 uk-margin-remove">{{community.shortTitle}}</h1>
</div>
</div>
<users-tabs tab="manager"></users-tabs> <users-tabs tab="manager"></users-tabs>
</role-users> </role-users>
` `

View File

@ -10,12 +10,6 @@ import {CommunityInfo} from "../../../openaireLibrary/connect/community/communit
template: ` template: `
<subscribers [id]="community.communityId" [type]="'community'" [name]="community.shortTitle" <subscribers [id]="community.communityId" [type]="'community'" [name]="community.shortTitle"
[inviteDisableMessage]="inviteDisableMessage"> [inviteDisableMessage]="inviteDisableMessage">
<div class="uk-flex uk-flex-middle uk-margin-medium-top info">
<div>
<div class="uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage Users</div>
<h1 class="uk-h6 uk-margin-remove">{{community.shortTitle}}</h1>
</div>
</div>
<users-tabs tab="member"></users-tabs> <users-tabs tab="member"></users-tabs>
</subscribers> </subscribers>
` `

View File

@ -1,16 +1,6 @@
<div page-content> <div page-content>
<div header>
<div class="uk-flex uk-flex-middle uk-margin-medium-top info">
<div>
<div class="uk-text-background uk-text-bold uk-text-small">Admin Dashboard - Manage Zenodo Communities
</div>
<h1 class="uk-h6 uk-margin-remove">{{community.shortTitle}}</h1>
</div>
</div>
<community-info tab="zenodo-communities"></community-info>
</div>
<div actions> <div actions>
<div class="uk-section-xsmall"> <div class="uk-section-xsmall uk-margin-top">
<div class="uk-flex uk-flex-right@m uk-flex-center uk-flex-middle uk-grid" uk-grid> <div class="uk-flex uk-flex-right@m uk-flex-center uk-flex-middle uk-grid" uk-grid>
<div search-input [expandable]="true" [searchControl]="filterForm" searchInputClass="outer" <div search-input [expandable]="true" [searchControl]="filterForm" searchInputClass="outer"
placeholder="Search Zenodo Community" [disabled]="searchUtils.status === errorCodes.LOADING" placeholder="Search Zenodo Community" [disabled]="searchUtils.status === errorCodes.LOADING"

View File

@ -10,7 +10,6 @@ import {ManageZenodoCommunitiesService} from '../../services/manageZenodoCommuni
import {ZenodoCommunitiesServiceModule} from '../../openaireLibrary/connect/zenodoCommunities/zenodo-communitiesService.module'; import {ZenodoCommunitiesServiceModule} from '../../openaireLibrary/connect/zenodoCommunities/zenodo-communitiesService.module';
import {AlertModalModule} from '../../openaireLibrary/utils/modal/alertModal.module'; import {AlertModalModule} from '../../openaireLibrary/utils/modal/alertModal.module';
import {ZenodoCommunitiesRoutingModule} from './zenodo-communities-routing.module'; import {ZenodoCommunitiesRoutingModule} from './zenodo-communities-routing.module';
import {CommunityInfoModule} from '../community-info/community-info.module';
import {SearchInputModule} from '../../openaireLibrary/sharedComponents/search-input/search-input.module'; import {SearchInputModule} from '../../openaireLibrary/sharedComponents/search-input/search-input.module';
import {IconsModule} from '../../openaireLibrary/utils/icons/icons.module'; import {IconsModule} from '../../openaireLibrary/utils/icons/icons.module';
import {NoLoadPaging} from '../../openaireLibrary/searchPages/searchUtils/no-load-paging.module'; import {NoLoadPaging} from '../../openaireLibrary/searchPages/searchUtils/no-load-paging.module';
@ -24,7 +23,7 @@ import {PagingModule} from "../../openaireLibrary/utils/paging.module";
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, FormsModule, RouterModule, SearchZenodoCommunitiesServiceModule, ZenodoCommunitiesServiceModule, CommonModule, FormsModule, RouterModule, SearchZenodoCommunitiesServiceModule, ZenodoCommunitiesServiceModule,
AlertModalModule, ZenodoCommunitiesRoutingModule, CommunityInfoModule, PageContentModule, SearchInputModule, IconsModule, NoLoadPaging, LoadingModule, FullScreenModalModule, HTMLToStringPipeModule, PagingModule AlertModalModule, ZenodoCommunitiesRoutingModule, PageContentModule, SearchInputModule, IconsModule, NoLoadPaging, LoadingModule, FullScreenModalModule, HTMLToStringPipeModule, PagingModule
], ],
declarations: [ declarations: [
ManageZenodoCommunitiesComponent, ZenodoCommunitiesComponent, AddZenodoCommunitiesComponent, PreviewZenodoCommunityComponent ManageZenodoCommunitiesComponent, ZenodoCommunitiesComponent, AddZenodoCommunitiesComponent, PreviewZenodoCommunityComponent

@ -1 +1 @@
Subproject commit d772dbd4b2f2d8af9e26d98eed7417f2fbf15c3a Subproject commit d8e7e5439fbd606301b51fdd5ed5115d9ad75c22

@ -1 +1 @@
Subproject commit 2882ccde4eb93bd01b4cdb480790cc04b394794d Subproject commit a5b03a914c98c4478d758f58a8ceacc8f3c0611a