Merge branch 'new-theme' of code-repo.d4science.org:MaDgIK/connect-admin into new-theme

This commit is contained in:
argirok 2022-07-04 12:59:38 +03:00
commit 048f159f5d
21 changed files with 468 additions and 773 deletions

View File

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

View File

@ -14,6 +14,7 @@ import {SmoothScroll} from "./openaireLibrary/utils/smooth-scroll";
import {ConnectHelper} from './openaireLibrary/connect/connectHelper';
import {ConfigurationService} from './openaireLibrary/utils/configuration/configuration.service';
import {StringUtils} from "./openaireLibrary/utils/string-utils.class";
import {OpenaireEntities} from "./openaireLibrary/utils/properties/searchFields";
@Component({
selector: 'app-root',
@ -26,7 +27,7 @@ export class AppComponent implements OnInit {
params: BehaviorSubject<Params> = new BehaviorSubject<Params>(null);
data: BehaviorSubject<Data> = new BehaviorSubject<Data>(null);
hasSidebar: boolean = false;
hasHeader: boolean = false;
hasHeader: boolean = true;
hasAdminMenu: boolean = false;
isFrontPage: boolean = false;
sideBarItems: MenuItem[] = [];
@ -50,7 +51,7 @@ export class AppComponent implements OnInit {
private subscriptions: any[] = [];
headerLogoUrl: string;
headerUrl: string;
constructor(private route: ActivatedRoute,
private communityService: CommunityService,
private router: Router,
@ -112,12 +113,10 @@ export class AppComponent implements OnInit {
}
}));
} else {
this.buildMenu();
this.loading = false;
}
} else {
this.communityService.setCommunity(null);
this.layoutService.setOpen(!(this.innerWidth && this.innerWidth < 1219));
this.community = null;
this.buildMenu();
this.loading = false;
@ -192,7 +191,11 @@ export class AppComponent implements OnInit {
this.userMenuItems.push(new MenuItem("exploreOptions", "Explore portal options", "", "/openaire/admin-tools/pages", false, [], [], {}));
}
this.userMenuItems.push(new MenuItem("", "User information", "", "/user-info", false, [], [], {}));
if (this.community) {
this.userMenuItems.push(new MenuItem("", "User information", "", "/"+this.community.communityId+"/user-info", false, [], [], {}));
} else {
this.userMenuItems.push(new MenuItem("", "User information", "", "/user-info", false, [], [], {}));
}
}
if (this.community) {
this.headerLogoUrl = StringUtils.getLogoUrl(this.community);
@ -200,35 +203,87 @@ export class AppComponent implements OnInit {
this.menuHeader = {
route: "/" + this.community.communityId,
url: null,
title: 'Admin - ' + this.community.shortTitle,
logoUrl: null,
logoSmallUrl: null,
position: 'center',
title: this.community.shortTitle,
logoUrl: this.headerLogoUrl,
logoSmallUrl: this.headerLogoUrl,
position: 'left',
badge: false,
stickyAnimation: false
};
this.sideBarItems.push(new MenuItem("community", "Community Info", "", "/" + this.community.communityId, false, [], [], {}, null, null, null, "/" + this.community.communityId + "/info"));
this.sideBarItems.push(new MenuItem("users", "Users", "", "/" + this.community.communityId + "/users", false, [], [], {}, null, null, null, "/" + this.community.communityId + "/users"));
this.sideBarItems.push(new MenuItem("admin-tools", "Pages & Entities", "", "/" + this.community.communityId + "/admin-tools/pages", false, [], [], {}, null, null, null, "/" + this.community.communityId + "/admin-tools"));
this.sideBarItems.push(new MenuItem("customization", "Customization", "", "/" + this.community.communityId + "/customize-layout", false, [], [], {}));
this.sideBarItems.push(new MenuItem("community", "Community Info", "", "/" + this.community.communityId, false, [], [], {}, {name: 'badge'}, null, null, "/" + this.community.communityId + "/info"));
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 & Entities", "", "/" + 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'}));
if (this.community.type === 'ri') {
this.sideBarItems.push(new MenuItem("mining", "Mining", "", "/" + this.community.communityId + "/mining/manage-profiles", false, [], [], {}, null, null, null, "/" + this.community.communityId + "/mining"));
this.sideBarItems.push(new MenuItem("mining", "Mining", "", "/" + this.community.communityId + "/mining/manage-profiles", false, [], [], {}, {name: 'architecture'}, null, null, "/" + this.community.communityId + "/mining"));
}
this.specialSideBarMenuItem = new MenuItem("back", "Manage communities", "", "/", false, [], null, {}, {name: 'search', class: 'uk-text-secondary'});
this.menuItems = [];
this.menuItems.push({
rootItem: new MenuItem("dashboard", "Dashboard",
"https://"+(properties.environment == "beta" ? "beta." : "")+this.community.communityId+".openaire.eu/", "", false, [], null, null
, null, null, null, null, "_self"), items: []
});
this.menuItems.push({
rootItem: new MenuItem("deposit", "Deposit", "https://"+(properties.environment == "beta" ? "beta." : "")+this.community.communityId+".openaire.eu/participate/participate/deposit/learn-how", "", false, [], ['/participate/deposit/learn-how'], null, null, null, null, null, "_self"),
items: []
});
this.menuItems.push(
{
rootItem: new MenuItem("link", "Link", "https://"+(properties.environment == "beta" ? "beta." : "")+this.community.communityId+".openaire.eu/participate/claim", "", false, [], ['/participate/claim'], null, null, null, null, null, "_self"),
items: [
new MenuItem("", "Start linking", "https://"+(properties.environment == "beta" ? "beta." : "")+this.community.communityId+".openaire.eu/participate/claim", "", false, [], ['/participate/claim'], null, null, null, null, null, "_self"),
new MenuItem("", "Learn more", this.properties.claimsInformationLink, "", false, [], [], null),
]
});
this.menuItems.push(
{
rootItem: new MenuItem("search", "Search", "https://"+(properties.environment == "beta" ? "beta." : "")+this.community.communityId+".openaire.eu/search/find", "", false, [], ["/search/find"], null, null, null, null, null, "_self"),
items: [
new MenuItem("", OpenaireEntities.RESULTS, "https://"+(properties.environment == "beta" ? "beta." : "")+this.community.communityId+".openaire.eu/search/find/research-outcomes?resultbestaccessright=\"" + encodeURIComponent("Open Access") + '"', "", false, [], ["/search/find/research-outcomes"], null, null, null, null, null, "_self"),
new MenuItem("", OpenaireEntities.PROJECTS, "https://"+(properties.environment == "beta" ? "beta." : "")+this.community.communityId+".openaire.eu/search/find/projects", "", false, [], ["/search/find/projects"], null, null, null, null, null, "_self"),
new MenuItem("", OpenaireEntities.DATASOURCES, "https://"+(properties.environment == "beta" ? "beta." : "")+this.community.communityId+".openaire.eu/search/find/dataproviders", "", false, [], ["/search/find/dataproviders"], null, null, null, null, null, "_self")
]
});
this.menuItems.push(
{
rootItem: new MenuItem("about", "About", "", "", false, [], [], {}),
items: [
new MenuItem("", "Supporting organizations", "https://"+(properties.environment == "beta" ? "beta." : "")+this.community.communityId+".openaire.eu/organizations", "", false, [], ["/organizations"], null, null, null, null, null, "_self"),
new MenuItem("", "Curators", "https://"+(properties.environment == "beta" ? "beta." : "")+this.community.communityId+".openaire.eu/curators", "", false, [], ["/organizations"], null, null, null, null, null, "_self"),
new MenuItem("", "Sources and methodology", "https://"+(properties.environment == "beta" ? "beta." : "")+this.community.communityId+".openaire.eu/content", "", false, [], ["/content"], null, null, null, null, null, "_self"),
new MenuItem("", "National Bulletins", "https://"+(properties.environment == "beta" ? "beta." : "")+this.community.communityId+".openaire.eu/national-bulletins", "", false, [], ["/national-bulletins"], null, null, null, null, null, "_self"),
new MenuItem("", "Subjects", "https://"+(properties.environment == "beta" ? "beta." : "")+this.community.communityId+".openaire.eu/subjects", "", false, [], ["/subjects"], null, null, null, null, null, "_self"),
new MenuItem("", "Projects and funding Opportunities", "https://"+(properties.environment == "beta" ? "beta." : "")+this.community.communityId+".openaire.eu/projects", "", false, [], ["/projects"], null, null, null, null, null, "_self")
]
});
// if (this.isManager) {
this.menuItems.push(
{
// rootItem: new MenuItem("manage", "Manage", "", "/"+this.community.communityId, false, [], [], {}),
// items: []
rootItem: new MenuItem("manage", "Manage",
"", "/"+this.community.communityId, false, [], null, {}
, null, null, null, "/"+this.community.communityId), items: []
});
// }
} else {
this.headerLogoUrl = null;
this.headerUrl = 'https://' + ((properties.environment !== 'production')?'beta.':'') + 'connect.openaire.eu';
this.menuHeader = {
route: null,
url: null,
title: 'Admin - Research Community Dashboard',
title: 'Research Community Dashboard',
logoUrl: null,
logoSmallUrl: null,
position: 'center',
badge: false,
stickyAnimation: false
};
this.sideBarItems.push(new MenuItem("communities", "Manage Communities", "", "/", false, [], [], {}, {name: 'settings'}));
if(this.isCurator()) {
this.sideBarItems.push(new MenuItem("communities", "Manage Communities", "", "/", false, [], [], {}, {name: 'settings'}));
}
if (Session.isPortalAdministrator(this.user)) {
this.sideBarItems.push(new MenuItem("super_admin", "Super Admin Options", "", "/admin-tools/portals", false, [], [], {}, {name: 'settings'}, null, null, '/admin-tools'));
this.sideBarItems.push(new MenuItem("connect", "Connect Options", "", "/connect/admin-tools/pages", false, [], [], {}, {name: 'settings'}, null, null, '/connect/admin-tools'));
@ -236,6 +291,7 @@ export class AppComponent implements OnInit {
}
this.specialSideBarMenuItem = null;
}
this.hasSidebar = this.hasSidebar && this.sideBarItems.length > 0;
}
private isCurator() {

View File

@ -1,5 +1,5 @@
import {NgModule} from '@angular/core';
import {PreloadAllModules, RouterModule, Routes} from '@angular/router';
import {RouterModule, Routes} from '@angular/router';
import {IsCommunity} from './openaireLibrary/connect/communityGuard/isCommunity.guard';
import {ConnectAdminLoginGuard} from './openaireLibrary/connect/communityGuard/connectAdminLoginGuard.guard';
import {AdminErrorPageComponent} from './pages/error/errorPage.component';
@ -20,7 +20,7 @@ const routes: Routes = [
{
path: 'user-info',
loadChildren: () => import('./login/libUser.module').then(m => m.LibUserModule),
data: {hasSidebar: false}
data: {hasSidebar: true}
},
{ path: 'error',
pathMatch: 'full',
@ -60,10 +60,7 @@ const routes: Routes = [
];
@NgModule({
imports: [RouterModule.forRoot(routes, {
preloadingStrategy: PreloadAllModules,
onSameUrlNavigation: "reload"
})],
imports: [RouterModule.forRoot(routes)],
exports: [ RouterModule ]
})
export class AppRoutingModule {}

@ -1 +1 @@
Subproject commit 936c870abcb48b632f3a1433130e8701c813fa65
Subproject commit de493c84923348f8289d4e507c04cfec80c30d69

View File

@ -35,13 +35,13 @@
<no-load-paging (pageChange)="updatePage($event)" [page]="page" [totalResults]="affiliations.length"
[pageSize]="pageSize" [type]="'supporting organization' + (affiliations.length > 1?'s':'')">
</no-load-paging>
<div class="uk-grid uk-grid-large uk-child-width-1-1 uk-child-width-1-2@m uk-margin-top uk-margin-bottom">
<div class="uk-grid uk-grid-large uk-child-width-1-1 uk-child-width-1-2@m uk-margin-top uk-margin-bottom" uk-height-match="target: .uk-card-body; row: false" uk-grid>
<div *ngFor="let affiliation of currentPage; let i=index">
<div class="uk-card uk-card-default uk-margin-bottom">
<div class="uk-card uk-card-default">
<div class="uk-card-body">
<div class="uk-flex uk-flex-middle uk-flex-column">
<div class="uk-width-small uk-height-max-small">
<img [src]="affiliation.logo_url | urlPrefix">
<div class="uk-flex uk-flex-center">
<img class="uk-height-xsmall uk-blend-multiply" [src]="affiliation.logo_url | urlPrefix">
</div>
<h5>{{affiliation.name}}</h5>
<div class="uk-text-truncate uk-text-small">

View File

@ -189,7 +189,6 @@ export class EditCommunityComponent {
public save(callback: Function, errorCallback: Function = null) {
if (this.file) {
this.communityFb.get('shortName').enable();
this.subscriptions.push(this.utilsService.uploadPhoto(this.properties.utilsService + "/upload/community/" + encodeURIComponent(this.community.communityId), this.file).subscribe(res => {
this.deletePhoto();
this.communityFb.get('logoUrl').setValue(res.filename);
@ -211,7 +210,7 @@ export class EditCommunityComponent {
if (this.isNew) {
this.removePhoto();
this.subscriptions.push(this.communityService.updateCommunity(
this.properties.communityAPI + this.community.communityId, this.communityFb.value).subscribe(() => {
this.properties.communityAPI + this.community.communityId, this.communityFb.getRawValue()).subscribe(() => {
this.communityService.getCommunity(this.community.communityId, true).subscribe(community => {
UIkit.notification(community.shortTitle + ' has been <b>successfully created</b>', {
status: 'success',
@ -231,7 +230,7 @@ export class EditCommunityComponent {
}
}));
} else {
this.subscriptions.push(this.communityService.updateCommunity(this.properties.communityAPI + this.community.communityId, this.communityFb.value).subscribe(() => {
this.subscriptions.push(this.communityService.updateCommunity(this.properties.communityAPI + this.community.communityId, this.communityFb.getRawValue()).subscribe(() => {
this.communityService.getCommunity(this.community.communityId, true).subscribe(community => {
UIkit.notification(community.shortTitle + ' has been <b>successfully saved</b>', {
status: 'success',

View File

@ -31,7 +31,11 @@ import {ConnectRIGuard} from "../openaireLibrary/connect/communityGuard/connectR
{
path: 'customize-layout',
loadChildren: () => import('./customization/customization.module').then(m => m.CustomizationModule),
}
},
{
path: 'user-info',
loadChildren: () => import('../login/libUser.module').then(m => m.LibUserModule),
},
])]
})
export class CommunityRoutingModule {}

View File

@ -1,60 +1,59 @@
<div class="uk-width-1-1 uk-flex uk-flex-right@m uk-flex-center uk-flex-wrap uk-flex-middle uk-grid uk-margin-medium-bottom" uk-grid>
<div #searchInputComponent search-input [control]="filterForm.controls.keyword" [showSearch]="false"
placeholder="Search Content Providers"
[selected]="openaireSearchUtils.keyword" (closeEmitter)="onSearchClose()" (resetEmitter)="resetInput()"
[bordered]="true" colorClass="uk-text-secondary"
class="uk-width-1-2@l uk-width-1-2@m uk-width-1-1"></div>
</div>
<div id="manage-content-providers">
<div *ngIf="openaireSearchUtils.status == errorCodes.LOADING" class="uk-position-large-top">
<loading></loading>
</div>
<div *ngIf="openaireSearchUtils.totalResults == 0"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div>
<div *ngIf="openaireSearchUtils.status == errorCodes.NONE">No OpenAIRE content providers available</div>
<div *ngIf="openaireSearchUtils.status == errorCodes.ERROR">An Error Occurred. No OpenAIRE content providers found</div>
<div *ngIf="openaireSearchUtils.status == errorCodes.NOT_AVAILABLE">Service temporarily unavailable. Please try again later.</div>
<div *ngIf="openaireSearchUtils.status == errorCodes.NOT_FOUND">No OpenAIRE content providers found</div>
<div class="uk-section uk-flex uk-flex-center uk-flex uk-flex-middle">
<div class="uk-width-auto uk-margin-right">
<a uk-icon="icon: info; ratio: 1.3"></a>
<div *ngIf="community" class="uk-dropdown uk-padding-small uk-width-medium" uk-dropdown="mode: hover">
If you cannot find a content provider relevant to your community, probably it is not OpenAIRE compliant.
Feel free to contact us
(<a
[href]="'mailto:' + properties.feedbackmailForMissingEntities +'?Subject=[OpenAIRE Connect - '+ community.shortTitle + '] report missing Funder' + '&body=' + body"
target="_top">{{properties.feedbackmailForMissingEntities}}</a>)
to let us know and we'll try to get the provider on board!
</div>
</div>
<!-- <errorMessages [status]="[openaireSearchUtils.status]" [type]="'OpenAIRE content providers'"></errorMessages>-->
<ng-container *ngIf="openaireSearchUtils.totalResults > 0">
<no-load-paging [type]="'Content Providers'"
[page]="openaireSearchUtils.page" [pageSize]="resultsPerPage" (pageChange)="goTo($event.value)"
[totalResults]="openaireSearchUtils.totalResults">
</no-load-paging>
<ul class="uk-list search-results uk-margin-medium-top uk-margin-medium-bottom">
<li *ngFor="let result of openaireContentProviders" class="uk-animation-fade">
<div class="uk-card uk-card-default uk-card-hover uk-text-small uk-margin-bottom">
<div class="uk-grid uk-grid-divider uk-padding-small" uk-grid>
<div class="uk-width-expand@m uk-width-1-1">
<div search-input class="uk-width-xlarge@l uk-width-large" [searchControl]="filterForm.get('keyword')" searchInputClass="outer"
placeholder="Search Content Providers" [disabled]="loading"></div>
</div>
<div class="uk-section uk-section-small uk-position-relative">
<div *ngIf="openaireSearchUtils.status == errorCodes.LOADING" class="uk-position-center">
<loading></loading>
</div>
<div *ngIf="openaireSearchUtils.status !== errorCodes.LOADING">
<div *ngIf="openaireSearchUtils.totalResults == 0"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div>No content providers found</div>
</div>
<ng-container *ngIf="openaireSearchUtils.totalResults > 0">
<no-load-paging [type]="'content Providers'"
[page]="openaireSearchUtils.page" [pageSize]="resultsPerPage" (pageChange)="goTo($event.value)"
[totalResults]="openaireSearchUtils.totalResults">
</no-load-paging>
<div class="uk-grid uk-child-width-1-1 uk-margin-top uk-margin-bottom" uk-grid>
<div *ngFor="let result of openaireContentProviders">
<div class="uk-card uk-card-default">
<div class="uk-card-body">
<result-preview [properties]="properties" [showOrganizations]="true"
[showSubjects]="true" [result]="getResultPreview(result)"
[externalUrl]="contentProviderUrl">
</result-preview>
</div>
<div class="uk-width-auto@m uk-width-1-1">
<div class="uk-flex uk-flex-middle uk-flex-center uk-flex-column uk-height-1-1">
<div class="uk-padding-small uk-padding-remove-horizontal">
<div [class.hide-element]="!getCommunityContentProvider(result)">
<a (click)="removeContentProvider(result)" class="uk-button action uk-flex uk-flex-middle">
<icon name="remove_circle_outline"></icon>
<span class="uk-margin-small-left">Remove content provider</span>
<div class="uk-card-footer uk-padding-remove-vertical">
<div class="uk-grid uk-grid-small uk-flex-nowrap uk-grid-divider uk-flex-right" uk-grid>
<div *ngIf="!getCommunityContentProvider(result)">
<div class="uk-padding-small uk-padding-remove-horizontal">
<a (click)="addContentProvider(result)" class="uk-button uk-button-link uk-flex uk-flex-middle">
<icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left">
Add
</span>
</a>
</div>
<div [class.hide-element]="getCommunityContentProvider(result)">
<a (click)="addContentProvider(result)" class="uk-button action uk-flex uk-flex-middle"
uk-tooltip="title:<div class='uk-padding-small'><div class='uk-margin-bottom uk-text-bold'>Add new content provider </div><div>Newly added content providers will be linked to your community on the next run of our algorithms.</div></div>">
<div class="uk-text-success">
<icon name="add"></icon>
</div>
<span class="uk-margin-small-left">Add content provider</span>
</div>
<div *ngIf="getCommunityContentProvider(result)">
<div class="uk-padding-small uk-padding-remove-horizontal">
<a (click)="removeContentProvider(result)"
class="uk-button uk-button-link uk-flex uk-flex-middle">
<icon name="remove" [flex]="true"></icon>
<span class="uk-margin-small-left">Remove</span>
</a>
</div>
</div>
@ -62,17 +61,13 @@
</div>
</div>
</div>
</li>
</ul>
<!-- <div [class]="openaireSearchUtils.page > pagingLimit ? 'search-results' : ''"-->
<!-- *ngIf="(openaireSearchUtils.page >= pagingLimit) && (openaireSearchUtils.totalResults > resultsPerPage*pagingLimit)">-->
<!-- <p class="uk-alert-warning" uk-alert>For more results please try a new, more specific query</p>-->
<!-- </div>-->
<no-load-paging [type]="'Content Providers'"
[page]="openaireSearchUtils.page" [pageSize]="resultsPerPage" (pageChange)="goTo($event.value)"
[totalResults]="openaireSearchUtils.totalResults">
</no-load-paging>
</ng-container>
</div>
<div class="uk-margin-small-top">
<paging-no-load [currentPage]="openaireSearchUtils.page"
[totalResults]="openaireSearchUtils.totalResults" [size]="resultsPerPage"
(pageChange)="goTo($event)" customClasses="uk-flex-right@m uk-flex-center">
</paging-no-load>
</div>
</ng-container>
</div>
</div>

View File

@ -1,8 +1,8 @@
import {Component, OnInit, Input, Output, EventEmitter, ViewChild} from '@angular/core';
import { ActivatedRoute, Router } from "@angular/router";
import {SearchResult} from '../../openaireLibrary/utils/entities/searchResult';
import {ActivatedRoute, Router} from "@angular/router";
import {SearchResult} from '../../openaireLibrary/utils/entities/searchResult';
import {ErrorCodes} from '../../openaireLibrary/utils/properties/errorCodes';
import {SearchUtilsClass } from '../../openaireLibrary/searchPages/searchUtils/searchUtils.class';
import {SearchUtilsClass} from '../../openaireLibrary/searchPages/searchUtils/searchUtils.class';
import {EnvProperties} from '../../openaireLibrary/utils/properties/env-properties';
import {SearchDataprovidersService} from '../../openaireLibrary/services/searchDataproviders.service';
import {RouterHelper} from '../../openaireLibrary/utils/routerHelper.class';
@ -16,20 +16,17 @@ import {SearchInputComponent} from "../../openaireLibrary/sharedComponents/searc
import {Subscriber} from "rxjs";
import {debounceTime, distinctUntilChanged} from "rxjs/operators";
import {ResultPreview} from "../../openaireLibrary/utils/result-preview/result-preview";
declare var UIkit;
import {NotificationHandler} from "../../openaireLibrary/utils/notification-handler";
import {CommunityInfo} from "../../openaireLibrary/connect/community/communityInfo";
@Component({
selector: 'add-content-providers',
templateUrl: './add-content-providers.component.html',
selector: 'add-content-providers',
templateUrl: './add-content-providers.component.html',
})
export class AddContentProvidersComponent implements OnInit {
private subscriptions: any[] = [];
public subResults: any;
private community: string = '';
@Input() public community: CommunityInfo;
public routerHelper: RouterHelper = new RouterHelper();
public properties: EnvProperties = properties;
public errorCodes: ErrorCodes;
@ -38,46 +35,33 @@ export class AddContentProvidersComponent implements OnInit {
@Input() communityContentProviders = [];
public openaireContentProviders = [];
public queryParameters: string = "";
// public pagingLimit: number = properties.pagingLimit;
public resultsPerPage: number = properties.resultsPerPage;
filterForm: FormGroup;
@ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent;
private contentProviderUrl: string = "https://" + ((properties.environment == "beta" || properties.environment == "development") ? "beta." : "") + "explore.openaire.eu" + properties.searchLinkToDataProvider;
public contentProviderUrl: string = "https://" + ((properties.environment == "beta" || properties.environment == "development") ? "beta." : "") + "explore.openaire.eu" + properties.searchLinkToDataProvider;
public body: string = "Send from page";
@Output() toggleView: EventEmitter<any> = new EventEmitter();
constructor(private route: ActivatedRoute, private _router: Router,
private _searchContentProvidersService: SearchDataprovidersService,
private _manageCommunityContentProvidersService: ManageCommunityContentProvidersService,
private _fb: FormBuilder) {
constructor(private route: ActivatedRoute, private router: Router,
private searchDataprovidersService: SearchDataprovidersService,
private manageCommunityContentProvidersService: ManageCommunityContentProvidersService,
private fb: FormBuilder) {
this.errorCodes = new ErrorCodes();
this.openaireSearchUtils.status = this.errorCodes.LOADING;
}
ngOnInit() {
this.subscriptions.push(this.route.params.subscribe(params => {
this.openaireSearchUtils.status = this.errorCodes.LOADING;
this.community = params['community'];
// this.contentProviderUrl = "https://" + ((this.properties.environment == "beta" || this.properties.environment == "development") ? "beta." : "")
// + this.community + ".openaire.eu" + this.properties.searchLinkToDataProvider;
this._getOpenaireContentProviders("", 1, this.resultsPerPage);
this.body = "[Please write your message here]";
this.body = StringUtils.URIEncode(this.body);
}));
this.openaireSearchUtils.keyword = "";
this.filterForm = this._fb.group({
this.filterForm = this.fb.group({
keyword: [''],
});
this.subscriptions.push(this.filterForm.get('keyword').valueChanges
.pipe(debounceTime(1000), distinctUntilChanged())
.subscribe(value => {
@ -85,81 +69,57 @@ export class AddContentProvidersComponent implements OnInit {
})
);
}
public ngOnDestroy() {
this.subscriptions.forEach(sub => {
if (sub instanceof Subscriber) {
sub.unsubscribe();
}
});
if(this.subResults){
if (this.subResults) {
this.subResults.unsubscribe();
}
}
get loading() {
return this.openaireSearchUtils.status == this.errorCodes.LOADING
}
public addContentProvider(contenProvider: SearchResult) {
if (!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
this.subscriptions.push(this._manageCommunityContentProvidersService.addContentProvider(this.properties, this.community, contenProvider).subscribe(
data => {
this.communityContentProviders.push(data);
UIkit.notification('Content Provider successfully added!', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
this.communityContentProvidersChanged.emit({
value: this.communityContentProviders,
});
},
err => {
this.handleError('An error has been occurred. Try again later!');
console.error(err.status);
}
));
}
this.subscriptions.push(this.manageCommunityContentProvidersService.addContentProvider(this.properties, this.community.communityId, contenProvider).subscribe(
data => {
this.communityContentProviders.push(data);
NotificationHandler.rise('Content Provider successfully added!')
this.communityContentProvidersChanged.emit({
value: this.communityContentProviders,
});
},
error => {
this.handleError('An error has been occurred. Try again later!', error);
}
));
}
public removeContentProvider(contentProvider) {
if (!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
let communityContentProvider = this.getCommunityContentProvider(contentProvider);
let contentProviderId: string = communityContentProvider['id'];
this.subscriptions.push(this._manageCommunityContentProvidersService.removeContentProvider(this.properties, this.community, contentProviderId).subscribe(
data => {
let index = this.communityContentProviders.indexOf(communityContentProvider);
this.communityContentProviders.splice(index, 1);
UIkit.notification('Content Provider successfully removed!', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
this.communityContentProvidersChanged.emit({
value: this.communityContentProviders,
});
},
err => {
this.handleError('An error has been occurred. Try again later!');
console.error(err);
}
));
}
let communityContentProvider = this.getCommunityContentProvider(contentProvider);
let contentProviderId: string = communityContentProvider['id'];
this.subscriptions.push(this.manageCommunityContentProvidersService.removeContentProvider(this.properties, this.community.communityId, contentProviderId).subscribe(
data => {
let index = this.communityContentProviders.indexOf(communityContentProvider);
this.communityContentProviders.splice(index, 1);
NotificationHandler.rise('Content Provider successfully removed!')
this.communityContentProvidersChanged.emit({
value: this.communityContentProviders,
});
},
error => {
this.handleError('An error has been occurred. Try again later!', error);
}
));
}
public getCommunityContentProvider(contentProvider: any): string {
public getCommunityContentProvider(contentProvider: any): any {
let index: number = 0;
for (let communityContentProvider of this.communityContentProviders) {
if (communityContentProvider.openaireId == contentProvider.id) {
@ -167,133 +127,69 @@ export class AddContentProvidersComponent implements OnInit {
}
index++;
}
return "";
return null;
}
public getResultPreview(result: SearchResult): ResultPreview {
return ResultPreview.searchResultConvert(result, "dataprovider");
}
// public inCommunity(contentProvider: any): any {
// for(let communityContentProvider of this.communityContentProviders) {
// if(communityContentProvider.openaireId == contentProvider.id) {
// return true;
// }
// }
//
// if(this.undo[contentProvider.id]) {
// return true;
// }
// return false;
// }
private _getOpenaireContentProviders(parameters: string, page: number, size: number) {
if (!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
// if (page > this.pagingLimit) {
// size = 0;
// }
if (this.openaireSearchUtils.status == this.errorCodes.LOADING) {
this.openaireSearchUtils.status = this.errorCodes.LOADING;
this.openaireContentProviders = [];
this.openaireSearchUtils.totalResults = 0;
if(this.subResults){
this.subResults.unsubscribe();
}
this.subResults = this._searchContentProvidersService.searchDataproviders(parameters, null, page, size, [], this.properties).subscribe(
data => {
this.openaireSearchUtils.totalResults = data[0];
this.openaireContentProviders = data[1];
//this.searchPage.checkSelectedFilters(this.filters);
this.openaireSearchUtils.status = this.errorCodes.DONE;
if (this.openaireSearchUtils.totalResults == 0) {
this.openaireSearchUtils.status = this.errorCodes.NONE;
}
// if (this.openaireSearchUtils.status == this.errorCodes.DONE) {
// // Page out of limit!!!
// let totalPages: any = this.openaireSearchUtils.totalResults / (this.openaireSearchUtils.size);
// if (!(Number.isInteger(totalPages))) {
// totalPages = (parseInt(totalPages, 10) + 1);
// }
// if (totalPages < page) {
// this.openaireSearchUtils.totalResults = 0;
// this.openaireSearchUtils.status = this.errorCodes.OUT_OF_BOUND;
// }
// }
},
err => {
console.error(err);
//TODO check erros (service not available, bad request)
if (err.status == '404') {
this.openaireSearchUtils.status = this.errorCodes.NOT_FOUND;
} else if (err.status == '500') {
this.openaireSearchUtils.status = this.errorCodes.ERROR;
} else {
this.openaireSearchUtils.status = this.errorCodes.NOT_AVAILABLE;
}
}
);
if (this.openaireSearchUtils.status == this.errorCodes.LOADING) {
this.openaireSearchUtils.status = this.errorCodes.LOADING;
this.openaireContentProviders = [];
this.openaireSearchUtils.totalResults = 0;
if (this.subResults) {
this.subResults.unsubscribe();
}
this.subResults = this.searchDataprovidersService.searchDataproviders(parameters, null, page, size, [], this.properties).subscribe(
data => {
this.openaireSearchUtils.totalResults = data[0];
this.openaireContentProviders = data[1];
this.openaireSearchUtils.status = this.errorCodes.DONE;
if (this.openaireSearchUtils.totalResults == 0) {
this.openaireSearchUtils.status = this.errorCodes.NONE;
}
},
error => {
if (error.status == '404') {
this.handleError('No OpenAIRE content providers found.', error);
this.openaireSearchUtils.status = this.errorCodes.NOT_FOUND;
} else if (error.status == '500') {
this.handleError('An Error Occurred. No OpenAIRE content providers found.', error);
this.openaireSearchUtils.status = this.errorCodes.ERROR;
} else {
this.handleError('Service temporarily unavailable. Please try again later.', error);
this.openaireSearchUtils.status = this.errorCodes.NOT_AVAILABLE;
}
}
);
}
}
totalPages(): number {
let totalPages: any = this.openaireSearchUtils.totalResults / (this.resultsPerPage);
if (!(Number.isInteger(totalPages))) {
totalPages = (parseInt(totalPages, 10) + 1);
}
return totalPages;
}
keywordChanged(keyword) {
this.openaireSearchUtils.keyword = keyword;
this.buildQueryParameters();
this.goTo(1);
}
buildQueryParameters() {
this.queryParameters = "";
if (this.openaireSearchUtils.keyword) {
this.queryParameters = "q=" + StringUtils.URIEncode(this.openaireSearchUtils.keyword);
}
}
goTo(page: number = 1) {
this.openaireSearchUtils.page = page;
this.openaireSearchUtils.status = this.errorCodes.LOADING;
this._getOpenaireContentProviders(this.queryParameters, page, this.resultsPerPage);
}
back() {
this.toggleView.emit(null);
}
public onSearchClose() {
this.openaireSearchUtils.keyword = this.filterForm.get('keyword').value;
}
public resetInput() {
this.openaireSearchUtils.keyword = null;
this.searchInputComponent.reset()
}
handleError(message: string) {
UIkit.notification(message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
handleError(message: string, error = null) {
console.error(error);
NotificationHandler.rise(message, 'danger');
}
}

View File

@ -17,7 +17,7 @@ import {NoLoadPaging} from "../../openaireLibrary/searchPages/searchUtils/no-loa
import {LoadingModule} from "../../openaireLibrary/utils/loading/loading.module";
import {IconsModule} from "../../openaireLibrary/utils/icons/icons.module";
import {IconsService} from "../../openaireLibrary/utils/icons/icons.service";
import {add, arrow_left, close, edit, remove_circle_outline} from "../../openaireLibrary/utils/icons/icons";
import {add, arrow_left, close, edit, filters, remove_circle_outline} from "../../openaireLibrary/utils/icons/icons";
import {FullScreenModalModule} from "../../openaireLibrary/utils/modal/full-screen-modal/full-screen-modal.module";
import {ResultPreviewModule} from "../../openaireLibrary/utils/result-preview/result-preview.module";
import {SearchDataprovidersServiceModule} from "../../openaireLibrary/connect/contentProviders/searchDataprovidersService.module";
@ -63,6 +63,6 @@ import {SearchDataprovidersService} from "../../openaireLibrary/services/searchD
export class CommunityContentProvidersModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([remove_circle_outline, add, edit, close, arrow_left]);
this.iconsService.registerIcons([filters]);
}
}

View File

@ -1,42 +1,27 @@
import {Component, ElementRef, Input, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from "@angular/router";
import {Router} from "@angular/router";
import {RemoveContentProvidersComponent} from './remove-content-providers.component';
import {Session} from '../../openaireLibrary/login/utils/helper.class';
import {LoginErrorCodes} from '../../openaireLibrary/login/utils/guardHelper.class';
import {HelperFunctions} from "../../openaireLibrary/utils/HelperFunctions.class";
import {Title} from '@angular/platform-browser';
import {FullScreenModalComponent} from "../../openaireLibrary/utils/modal/full-screen-modal/full-screen-modal.component";
import {
FullScreenModalComponent
} from "../../openaireLibrary/utils/modal/full-screen-modal/full-screen-modal.component";
import {StringUtils} from "../../openaireLibrary/utils/string-utils.class";
import {EnvProperties} from "../../openaireLibrary/utils/properties/env-properties";
import {properties} from "../../../environments/environment";
import {Subscriber} from "rxjs";
import {CommunityInfo} from "../../openaireLibrary/connect/community/communityInfo";
import {CommunityService} from "../../openaireLibrary/connect/community/community.service";
@Component({
selector: 'manage-content-providers',
template: `
<remove-content-providers (toggleView)="toggleAction()" [communityContentProviders]="communityContentProviders"
[showLoading]="showLoadingInRemove"
(communityContentProvidersChanged)="communityContentProvidersChanged($event)" [toggle]="toggle">
<remove-content-providers #removeContentProvidersComponent (addContentProviders)="openAddContentProviders()" [communityContentProviders]="communityContentProviders"
[loading]="showLoadingInRemove" [community]="community" [disableAdd]="add.loading"
(communityContentProvidersChanged)="communityContentProvidersChanged($event)">
</remove-content-providers>
<fs-modal #fsModal (cancelEmitter)="toggleAction()">
<div actions class="uk-flex uk-flex-middle uk-height-1-1">
<span class="uk-button uk-text-secondary" uk-icon="icon: info; ratio: 1.3"></span>
<div *ngIf="communityId" uk-drop="mode: hover">
<div class="uk-card uk-card-body uk-card-default">
If you cannot find a content provider relevant to your community, probably it is not OpenAIRE compliant.
Feel free to contact us
(<a
[href]="'mailto:' + properties.feedbackmailForMissingEntities +'?Subject=[OpenAIRE Connect - '+ communityId + '] report missing Funder' + '&body=' + body"
target="_top">{{properties.feedbackmailForMissingEntities}}</a>)
to let us know and we'll try to get the provider on board!
</div>
</div>
</div>
<add-content-providers [communityContentProviders]="communityContentProviders"
(communityContentProvidersChanged)="communityContentProvidersChanged($event)"></add-content-providers>
<fs-modal #fsModal>
<add-content-providers #add [communityContentProviders]="communityContentProviders" [community]="community"
(communityContentProvidersChanged)="communityContentProvidersChanged($event)"></add-content-providers>
</fs-modal>
`
})
@ -45,36 +30,26 @@ export class ManageContentProvidersComponent implements OnInit {
@Input() communityContentProviders = [];
@ViewChild(RemoveContentProvidersComponent) removeContentProvidersComponent: RemoveContentProvidersComponent;
@ViewChild('fsModal', { static: true }) fullscreen: FullScreenModalComponent;
public toggle: boolean = false;
private subscriptions: any[] = [];
public showLoadingInRemove: boolean = true;
public body: string = "Send from page";
public properties: EnvProperties = properties;
public communityId: string = "";
public community: CommunityInfo;
constructor(private element: ElementRef,
private title: Title,
private route: ActivatedRoute, private _router: Router) {
private communityService: CommunityService, private _router: Router) {
}
ngOnInit() {
this.subscriptions.push(this.route.params.subscribe(params => {
this.communityId = params['community'];
if (this.communityId) {
this.title.setTitle(this.communityId.toUpperCase() + ' | Content Providers');
this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe(community => {
this.community = community;
if (this.community) {
this.title.setTitle(this.community.shortTitle.toUpperCase() + ' | Content Providers');
this.body = "[Please write your message here]";
this.body = StringUtils.URIEncode(this.body);
}
}));
this.fullscreen.title = "Search and Add Content Providers";
this.fullscreen.okButtonText = "Done";
this.fullscreen.okButton = true;
}
public ngOnDestroy() {
@ -84,27 +59,20 @@ export class ManageContentProvidersComponent implements OnInit {
}
});
}
public toggleAction() {
if (!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], {
queryParams: {'errorCode': LoginErrorCodes.NOT_VALID, 'redirectUrl': this._router.url}
});
} else {
HelperFunctions.scroll();
this.toggle = !this.toggle;
if (this.toggle) {
this.fullscreen.open();
}
}
public openAddContentProviders() {
this.fullscreen.title = "Search and Add Content Providers";
this.fullscreen.okButtonText = "Done";
this.fullscreen.back = true;
this.fullscreen.okButton = true;
this.fullscreen.open();
}
public communityContentProvidersChanged($event) {
this.communityContentProviders = $event.value;
this.showLoadingInRemove = false;
if (this.toggle) {
if (this.fullscreen.isOpen) {
this.removeContentProvidersComponent.applyFilters();
}
}

View File

@ -1,150 +1,111 @@
<div page-content>
<div page-content (stickyEmitter)="stickyPageHeader = $event">
<div header>
<community-info tab="content-providers"></community-info>
<div [class.uk-invisible]="showLoading"
class="uk-width-1-1 uk-flex uk-flex-right@m uk-flex-center uk-flex-wrap uk-flex-middle uk-grid" uk-grid>
<div class="uk-flex-last@m">
<a class="uk-text-uppercase uk-flex uk-flex-middle" (click)="addNew()"
[attr.uk-tooltip]="(toggle? 'cls: uk-invisible; ' : 'cls: uk-active; ') +
'title: <div class=\'uk-padding-small\'><div class=\'uk-margin-bottom uk-text-bold\'> Search and add more Content Providers</div><div>The research results collected from the content providers specified here will be automatically linked to your community dashboard.</div></div>'">
<button class="uk-icon-button large uk-button-secondary">
<icon name="add"></icon>
</button>
<button class="uk-button uk-button-link uk-margin-small-left uk-text-secondary">Add new content provider
</button>
</a>
<div class="uk-flex uk-flex-middle uk-margin-top info" [class.uk-active]="stickyPageHeader">
<div>
<div class="uk-margin-remove uk-text-background uk-text-bold uk-h6">Admin Dashboard - Manage Content Providers
</div>
<h1 class="uk-h4 uk-margin-remove">{{community.shortTitle}}</h1>
</div>
<div #searchInputComponent search-input [control]="filterForm.controls.keyword" [showSearch]="false"
placeholder="Search Content Providers"
[selected]="communitySearchUtils.keyword" (closeEmitter)="onSearchClose()" (resetEmitter)="resetInput()"
[bordered]="true" colorClass="uk-text-secondary"
class="uk-width-1-3@xl uk-width-2-5@l uk-width-1-2@m uk-width-1-1"></div>
</div>
<community-info tab="content-providers"></community-info>
</div>
<div inner>
<div *ngIf="showLoading" class="uk-margin-large-top">
<loading></loading>
</div>
<div *ngIf="!showLoading">
<div class="uk-flex uk-flex-right@m uk-flex-center uk-flex-middle uk-grid uk-margin-top" uk-grid>
<div search-input [expandable]="true" [searchControl]="filterForm.get('keyword')" searchInputClass="outer"
placeholder="Search Content Providers" [disabled]="loading"
class="uk-width-1-3@xl uk-width-2-5@l uk-width-1-2@m uk-width-1-1"></div>
<div>
<!-- <div class="uk-grid uk-flex uk-flex-middle uk-margin-medium-bottom" uk-grid>-->
<!-- <div *ngIf="previewCommunityContentProviders.length > 0"-->
<!-- class="uk-width-expand@m uk-width-1-1">-->
<!-- <div class="uk-flex-middle uk-flex-right@m uk-flex-center uk-grid">-->
<!-- <span class="">Sort by: </span>-->
<!-- <div class="uk-width-medium uk-padding-remove uk-margin-small-left" dashboard-input-->
<!-- [formInput]="filterForm.get('sort')"-->
<!-- type="select"-->
<!-- [options]="sortOptions">-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<no-load-paging *ngIf="previewCommunityContentProviders.length > 0" [type]="'content providers'"
(pageChange)="updatePage($event)"
[page]="page" [pageSize]="resultsPerPage"
[totalResults]="previewCommunityContentProviders.length">
</no-load-paging>
<div class="uk-margin-medium-top uk-margin-medium-bottom">
<div *ngIf="previewCommunityContentProviders.length == 0"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div>No content providers for {{name}}</div>
</div>
<div class="uk-card uk-card-default uk-text-small uk-margin-bottom"
*ngFor="let item of previewCommunityContentProviders.slice((page - 1)*resultsPerPage, page*resultsPerPage)">
<div class="uk-grid uk-grid-divider uk-padding" uk-grid>
<div class="uk-width-expand@m uk-width-1-1">
<div class="uk-padding-small uk-padding-remove-horizontal">
<!-- <h6 *ngIf="item.name || item.officialname || item.openaireId || item.selectioncriteria"-->
<!-- class="uk-margin-small-bottom">-->
<!-- <a *ngIf="item.openaireId"-->
<!-- target="_blank"-->
<!-- [href]="contentProviderUrl+item.openaireId">-->
<!-- <span *ngIf="item.name">{{item.name}}</span>-->
<!-- <span *ngIf="!item.name && item.officialname">{{item.officialname}}</span>-->
<!-- <span *ngIf="!item.name && !item.officialname">[no title available]</span>-->
<!-- <span class="custom-external custom-icon space"></span>-->
<!-- </a>-->
<!-- <span *ngIf="!item.openaireId">-->
<!-- <span *ngIf="item.name">{{item.name}}</span>-->
<!-- <span *ngIf="!item.name && item.officialname">{{item.officialname}}</span>-->
<!-- <span *ngIf="!item.name && !item.officialname">[no title available]</span>-->
<!-- </span>-->
<!-- </h6>-->
<!-- <h6 *ngIf="item.name || item.officialname || item.openaireId || item.selectioncriteria"-->
<!-- class="uk-margin-small-bottom">-->
<!-- <a *ngIf="item.openaireId"-->
<!-- target="_blank"-->
<!-- [href]="contentProviderUrl+item.openaireId">-->
<!-- <span *ngIf="item.name">{{item.name}}</span>-->
<!-- <span *ngIf="!item.name">[no title available]</span>-->
<!-- <span class="custom-external custom-icon space"></span>-->
<!-- </a>-->
<!-- <span *ngIf="!item.openaireId">-->
<!-- <span *ngIf="item.name">{{item.name}}</span>-->
<!-- <span *ngIf="!item.name">[no title available]</span>-->
<!-- </span>-->
<!-- </h6>-->
<h6 class="uk-margin-small-bottom">
<button class="uk-button uk-button-default uk-flex uk-flex-middle" (click)="addNew()"
[attr.uk-tooltip]="(toggle? 'cls: uk-invisible; ' : 'cls: uk-active; ') +
'title: <div><div class=\'uk-margin-bottom uk-text-bold\'> Search and add more Content Providers</div><div>The research results collected from the content providers specified here will be automatically linked to your community dashboard.</div></div>'"
[disabled]="loading || disableAdd" [class.uk-disabled]="loading || disableAdd">
<icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left uk-text-bold uk-text-uppercase">New content provider</span>
</button>
</div>
</div>
<div class="uk-section uk-section-small uk-position-relative" style="min-height: 60vh">
<div *ngIf="loading" class="uk-position-center">
<loading></loading>
</div>
<div *ngIf="!loading">
<div *ngIf="previewCommunityContentProviders.length == 0"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div>No content providers found</div>
</div>
<div *ngIf="previewCommunityContentProviders.length > 0">
<no-load-paging [type]="'content providers'"
(pageChange)="updatePage($event)"
[page]="page" [pageSize]="resultsPerPage"
[totalResults]="previewCommunityContentProviders.length">
</no-load-paging>
<div class="uk-grid uk-grid-large uk-child-width-1-1 uk-child-width-1-2@m uk-margin-top uk-margin-bottom"
uk-height-match="target: .uk-card-body; row: false;" uk-grid>
<div *ngFor="let item of currentPage; let i=index">
<div class="uk-card uk-card-default">
<div class="uk-card-body">
<h6 class="uk-margin-bottom">
<a *ngIf="item.openaireId"
target="_blank"
target="_blank" class="custom-external uk-link-text"
[href]="contentProviderUrl+item.openaireId">
<span *ngIf="item.officialname">{{item.officialname}}</span>
<span *ngIf="!item.officialname && item.name">{{item.name}}</span>
<span *ngIf="!item.officialname && !item.name">[no title available]</span>
<span class="custom-external custom-icon space"></span>
</a>
<span *ngIf="!item.openaireId">
<span *ngIf="item.officialname">{{item.officialname}}</span>
<span *ngIf="!item.officialname && item.name">{{item.name}}</span>
<span *ngIf="!item.officialname && !item.name">[no title available]</span>
</span>
<span *ngIf="item.officialname">{{item.officialname}}</span>
<span *ngIf="!item.officialname && item.name">{{item.name}}</span>
<span *ngIf="!item.officialname && !item.name">[no title available]</span>
</span>
</h6>
<!-- <div *ngIf="item.name && item.officialname" class="uk-margin-small-bottom">-->
<!-- <div *ngIf="item.officialname" class="uk-margin-small-bottom">-->
<!-- <span class="title">Official Name: </span>-->
<!-- <span>{{item.officialname}}</span>-->
<!-- </div>-->
<div *ngIf="item.selectioncriteria?.criteria?.length > 0" class="uk-margin-small-bottom">
<div class="title uk-margin-small-bottom">Filters</div>
<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 [innerHTML]="getFiltersAsText(item.selectioncriteria.criteria)"></div>
<a *ngIf="item.selectioncriteria.criteria.length > 3" class="uk-link uk-margin-top" [routerLink]="'./' + item.openaireId">View all {{item.selectioncriteria.criteria.length}} filters</a>
<div *ngIf="item.selectioncriteria.criteria.length > 3" class="uk-margin-small-top">
<a class="uk-link view-more-less-link" [routerLink]="'./' + item.openaireId">View all {{item.selectioncriteria.criteria.length}} filters</a>
</div>
</div>
</div>
</div>
<div class="uk-width-auto@m uk-width-1-1">
<div class="uk-flex uk-flex-middle uk-flex-center uk-flex-column uk-height-1-1">
<div class="uk-padding-small uk-padding-remove-horizontal">
<a (click)="goToCriteria(item.openaireId)" class="uk-button action uk-flex uk-flex-middle">
<icon name="edit"></icon>
<span *ngIf="item.selectioncriteria?.criteria?.length > 0" class="uk-margin-small-left"
uk-tooltip="<div class='uk-padding-small'>Edit filters to limit research results.<br>Results which satisfy any of the selected filters will be included in your community.</div>">
Edit filters
</span>
<span *ngIf="!(item.selectioncriteria?.criteria?.length > 0)" class="uk-margin-small-left"
uk-tooltip="<div class='uk-padding-small'>Add filter to limit research results.<br>Results which satisfy any of the selected filters will be included in your community.</div>">
Add filters
</span>
</a>
<a (click)="removeContentProvider(item)"
class="uk-button action uk-flex uk-flex-middle uk-margin-small-top">
<icon name="remove_circle_outline"></icon>
<span class="uk-margin-small-left">Remove content provider</span>
</a>
<div class="uk-card-footer uk-padding-remove-vertical">
<div class="uk-grid uk-grid-small uk-flex-nowrap uk-grid-divider uk-flex-right" uk-grid>
<div>
<div class="uk-padding-small uk-padding-remove-horizontal">
<a (click)="goToCriteria(item.openaireId)" class="uk-button uk-button-link uk-flex uk-flex-middle">
<icon name="filters" [flex]="true"></icon>
<span *ngIf="item.selectioncriteria?.criteria?.length > 0" class="uk-margin-small-left"
uk-tooltip="<div>Edit filters to limit research results.<br>Results which satisfy any of the selected filters will be included in your community.</div>">
Edit filters
</span>
<span *ngIf="!(item.selectioncriteria?.criteria?.length > 0)" class="uk-margin-small-left"
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>">
Add filters
</span>
</a>
</div>
</div>
<div>
<div class="uk-padding-small uk-padding-remove-horizontal">
<a (click)="removeContentProvider(item)"
class="uk-button uk-button-link uk-flex uk-flex-middle">
<icon name="remove" [flex]="true"></icon>
<span class="uk-margin-small-left">Remove</span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="uk-margin-small-top">
<paging-no-load [currentPage]="page"
[totalResults]="previewCommunityContentProviders.length" [size]="resultsPerPage"
(pageChange)="updatePage($event)" customClasses="uk-flex-right@m uk-flex-center">
</paging-no-load>
</div>
</div>
<no-load-paging *ngIf="previewCommunityContentProviders.length > 0" [type]="'content providers'"
(pageChange)="updatePage($event)"
[page]="page" [pageSize]="resultsPerPage"
[totalResults]="previewCommunityContentProviders.length">
</no-load-paging>
</div>
</div>
<modal-alert #AlertModalDeleteCommunity (alertOutput)="confirmedDeleteContentProvider($event)"></modal-alert>
</div>
</div>
<modal-alert #deleteModal [overflowBody]="false" (alertOutput)="confirmedDeleteContentProvider()"></modal-alert>

View File

@ -3,43 +3,40 @@ import {ActivatedRoute, Router} from "@angular/router";
import {Subscriber} from 'rxjs';
import {ErrorCodes} from '../../openaireLibrary/utils/properties/errorCodes';
import {SearchUtilsClass} from '../../openaireLibrary/searchPages/searchUtils/searchUtils.class';
import {EnvProperties} from '../../openaireLibrary/utils/properties/env-properties';
import {ManageCommunityContentProvidersService} from '../../services/manageContentProviders.service';
import {SearchCommunityDataprovidersService} from '../../openaireLibrary/connect/contentProviders/searchDataproviders.service';
import {
SearchCommunityDataprovidersService
} from '../../openaireLibrary/connect/contentProviders/searchDataproviders.service';
import {RouterHelper} from '../../openaireLibrary/utils/routerHelper.class';
import {Session} from '../../openaireLibrary/login/utils/helper.class';
import {LoginErrorCodes} from '../../openaireLibrary/login/utils/guardHelper.class';
import {Criteria, SelectionCriteria} from '../../openaireLibrary/utils/entities/contentProvider';
import {Criteria} from '../../openaireLibrary/utils/entities/contentProvider';
import {properties} from "../../../environments/environment";
import {SearchInputComponent} from "../../openaireLibrary/sharedComponents/search-input/search-input.component";
import {FormBuilder, FormGroup} from "@angular/forms";
import {Option} from "../../openaireLibrary/sharedComponents/input/input.component";
import {CommunityService} from "../../openaireLibrary/connect/community/community.service";
import {CriteriaUtils} from "./criteria-utils";
declare var UIkit;
import {CommunityInfo} from "../../openaireLibrary/connect/community/communityInfo";
import {NotificationHandler} from "../../openaireLibrary/utils/notification-handler";
import {AlertModal} from "../../openaireLibrary/utils/modal/alert";
@Component({
selector: 'remove-content-providers',
templateUrl: './remove-content-providers.component.html'
})
export class RemoveContentProvidersComponent implements OnInit {
public portal: string;
public name: string;
public routerHelper: RouterHelper = new RouterHelper();
public contentProviderUrl = "https://" + ((properties.environment == "beta" || properties.environment == "development") ? "beta." : "") + "explore.openaire.eu" + properties.searchLinkToDataProvider;
public previewCommunityContentProviders = [];
public communitySearchUtils: SearchUtilsClass = new SearchUtilsClass();
public errorCodes: ErrorCodes;
@Input() public showLoading: boolean = true;
@Input() public loading: boolean = true;
@Input() public disableAdd: boolean = false;
@Input() public community: CommunityInfo;
@Input() public communityContentProviders = [];
@Output() communityContentProvidersChanged = new EventEmitter();
private properties: EnvProperties = properties;
private subscriptions: any[] = [];
private selectedCommunityContentProvider: any;
@ViewChild('AlertModalDeleteCommunity') alertModalDeleteCommunity;
public stickyPageHeader: boolean = false;
@ViewChild('deleteModal') deleteModal: AlertModal;
/** Criteria */
private fields = CriteriaUtils.fields;
private verbs = CriteriaUtils.verbs;
@ -51,55 +48,30 @@ export class RemoveContentProvidersComponent implements OnInit {
filterForm: FormGroup;
private searchText: RegExp = new RegExp('');
public keyword: string = '';
sortOptions: Option[] = [
{label: "Name ", value: {sort: "name", descending: false}},
{label: "Official Name ", value: {sort: "officialname", descending: false}}
];
@Output() toggleView: EventEmitter<any> = new EventEmitter();
@Output() addContentProviders: EventEmitter<void> = new EventEmitter();
@Input() public toggle: boolean = true;
constructor(private route: ActivatedRoute, private _router: Router,
private _fb: FormBuilder, private communityService: CommunityService,
private _fb: FormBuilder,
private _manageCommunityContentProvidersService: ManageCommunityContentProvidersService,
private _searchCommunityContentProvidersService: SearchCommunityDataprovidersService) {
this.errorCodes = new ErrorCodes();
this.communitySearchUtils.status = this.errorCodes.LOADING;
}
ngOnInit() {
this.communitySearchUtils.keyword = "";
this.filterForm = this._fb.group({
keyword: [''],
// sort: this._fb.control(this.sortOptions[0].value)
});
this.subscriptions.push(this.filterForm.get('keyword').valueChanges.subscribe(value => {
this.searchText = new RegExp(value, 'i');
this.page = 1;
this.applyFilters();
}));
// this.subscriptions.push(this.filterForm.get('sort').valueChanges.subscribe(value => {
// this.page = 1;
// this.sort();
// }));
this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe(community => {
if (community) {
this.portal = community.communityId;
this.name = community.shortTitle;
this.contentProviderUrl = "https://"
+ ((this.properties.environment == "beta" || this.properties.environment == "development") ? "beta." : "")
+ this.portal + ".openaire.eu" + this.properties.searchLinkToDataProvider;
this.keyword = '';
this._getCommunityContentProviders();
}
}));
this.contentProviderUrl = "https://"
+ ((this.properties.environment == "beta" || this.properties.environment == "development") ? "beta." : "")
+ this.community.communityId + ".openaire.eu" + this.properties.searchLinkToDataProvider;
this.getCommunityContentProviders();
}
public ngOnDestroy() {
this.subscriptions.forEach(sub => {
if (sub instanceof Subscriber) {
@ -107,273 +79,117 @@ export class RemoveContentProvidersComponent implements OnInit {
}
});
}
public getCriteriaLabel(selectionCriteria: SelectionCriteria): string {
if (selectionCriteria && selectionCriteria.criteria.length > 0) {
return (selectionCriteria.criteria.length === 1) ? '1 criterion' : (selectionCriteria.criteria.length + ' criteria')
} else {
return 'no criteria';
}
}
// filterData(row: any, query: string) {
// let returnValue: boolean = false;
//
// if(query) {
// for(var i=0; i <2; i++){
// var r= this.filterQuery(row[i], query);
// if(r) {
// returnValue = true;
// break;
// }
// }
//
// if(!returnValue) {
// return false;
// }
// }
//
// return true;
// }
//
// filterQuery(data, query){
// if(data.toLowerCase().indexOf(query.toLowerCase()) > -1){
// return true;
// }else{
// return false;
// }
// }
public inCommunity(result: any): any {
let found = false;
for (let contentProvider of this.communityContentProviders) {
if (contentProvider.opeaireId == result.id) {
return true;
}
}
return found;
}
totalPages(): number {
let totalPages: any = this.communitySearchUtils.totalResults / (this.resultsPerPage);
if (!(Number.isInteger(totalPages))) {
totalPages = (parseInt(totalPages, 10) + 1);
}
return totalPages;
}
getFiltersAsText(criteria: Criteria[]): string {
let text = criteria.slice(0,3).map((criterion, index) => (index + 1) + ". " + criterion.constraint.map(constraint => {
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')) {
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)":"");
let value = '"' + constraint.value + '"' + (matchCase ? " (Match case)" : "");
return field + " " + verb + " " + value;
}).join(" <b>and</b> "));
return text.join("<br>");
}
// goTo(page:number = 1){
// this.communitySearchUtils.page=page;
//
// var table = $('#dpTable').DataTable();
// table.page( page - 1 ).draw( false );
//
// var info = table.page.info();
// this.communitySearchUtils.totalResults = info.recordsDisplay;
// }
public confirmedDeleteContentProvider(data: any) {
if (!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
this.subscriptions.push(this._manageCommunityContentProvidersService.removeContentProvider(this.properties, this.portal, this.selectedCommunityContentProvider.id).subscribe(
data => {
let index = this.communityContentProviders.indexOf(this.selectedCommunityContentProvider);
this.communityContentProviders.splice(index, 1);
this.applyFilters();
UIkit.notification('Content Provider successfully removed!', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
this.communityContentProvidersChanged.emit({
value: this.communityContentProviders,
});
this.communitySearchUtils.totalResults--;
this.communitySearchUtils.page = 1;
},
err => {
this.handleError('An error has been occurred. Try again later!');
console.error(err);
}
));
}
public confirmedDeleteContentProvider() {
this.subscriptions.push(this._manageCommunityContentProvidersService.removeContentProvider(this.properties, this.community.communityId, this.selectedCommunityContentProvider.id).subscribe(
() => {
let index = this.communityContentProviders.indexOf(this.selectedCommunityContentProvider);
this.communityContentProviders.splice(index, 1);
this.applyFilters();
this.handleSuccess('Content Provider successfully removed!')
this.communityContentProvidersChanged.emit({
value: this.communityContentProviders,
});
},
err => {
this.handleError('An error has been occurred. Try again later!');
console.error(err);
}
));
}
public removeContentProvider(communityContentProvider: any) {
if (!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
this.selectedCommunityContentProvider = communityContentProvider;
this.alertModalDeleteCommunity.cancelButton = true;
this.alertModalDeleteCommunity.okButton = true;
this.alertModalDeleteCommunity.alertTitle = "Remove content provider?";
let title = "";
if (communityContentProvider.name) {
title = communityContentProvider.name;
}
if (communityContentProvider.name && communityContentProvider.acronym) {
title += " (";
}
if (communityContentProvider.acronym) {
title += communityContentProvider.acronym;
}
if (communityContentProvider.name && communityContentProvider.acronym) {
title += ")";
}
this.alertModalDeleteCommunity.message = "Content Provider";
if (title) {
this.alertModalDeleteCommunity.message += " '" + title + "' ";
}
this.alertModalDeleteCommunity.message += "will be removed from your community. Are you sure?";
this.alertModalDeleteCommunity.okButtonText = "Yes";
this.alertModalDeleteCommunity.open();
this.selectedCommunityContentProvider = communityContentProvider;
this.deleteModal.alertTitle = "Remove content provider";
let title = "";
if (communityContentProvider.name) {
title = communityContentProvider.name;
}
}
public _getCommunityContentProviders() {
if (!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
this.communitySearchUtils.status = this.errorCodes.LOADING;
this.communityContentProviders = [];
this.communitySearchUtils.totalResults = 0;
this.communitySearchUtils.page = 1;
this.communitySearchUtils.keyword = "";
this.subscriptions.push(this._searchCommunityContentProvidersService.searchDataproviders(this.properties, this.portal).subscribe(
data => {
this.communityContentProviders = data;
this.previewCommunityContentProviders = this.communityContentProviders;
// this.sort();
this.communitySearchUtils.totalResults = data.length;
this.communitySearchUtils.status = this.errorCodes.DONE;
this.communityContentProvidersChanged.emit({
value: this.communityContentProviders,
});
this.showLoading = false;
},
err => {
console.error(err);
//TODO check erros (service not available, bad request)
if (err.status == '404') {
this.communitySearchUtils.status = this.errorCodes.NOT_FOUND;
} else if (err.status == '500') {
this.communitySearchUtils.status = this.errorCodes.ERROR;
} else {
this.communitySearchUtils.status = this.errorCodes.NOT_AVAILABLE;
}
this.showLoading = false;
}
));
if (communityContentProvider.name && communityContentProvider.acronym) {
title += " (";
}
if (communityContentProvider.acronym) {
title += communityContentProvider.acronym;
}
if (communityContentProvider.name && communityContentProvider.acronym) {
title += ")";
}
this.deleteModal.message = "Content Provider";
if (title) {
this.deleteModal.message += " '" + title + "' ";
}
this.deleteModal.message += "will be removed from your community. Are you sure?";
this.deleteModal.okButtonText = "Yes";
this.deleteModal.cancelButtonText = "No";
this.deleteModal.open();
}
public getCommunityContentProviders() {
this.communityContentProviders = [];
this.subscriptions.push(this._searchCommunityContentProvidersService.searchDataproviders(this.properties, this.community.communityId).subscribe(
data => {
this.communityContentProviders = data;
this.previewCommunityContentProviders = this.communityContentProviders;
this.communityContentProvidersChanged.emit({
value: this.communityContentProviders,
});
this.loading = false;
},
err => {
this.handleError('An error has been occurred. Try again later!', err)
this.loading = false;
}
));
}
public updatePage($event) {
this.page = $event.value;
}
addNew() {
this.toggleView.emit(null);
get currentPage(): any[] {
return this.previewCommunityContentProviders.slice((this.page - 1)*this.resultsPerPage, this.page*this.resultsPerPage);
}
addNew() {
this.addContentProviders.emit();
}
public applyFilters() {
this.previewCommunityContentProviders = this.communityContentProviders.filter(contentProvider => {
return this.filterCommunityContentProviderByKeyword(contentProvider);
});
// check paging here!!!
if (this.previewCommunityContentProviders.slice((this.page - 1) * this.resultsPerPage, this.page * this.resultsPerPage).length == 0) {
this.page = 1;
}
// this.sort();
}
public filterCommunityContentProviderByKeyword(contentProvider): boolean {
const textFlag = this.searchText.toString() === ''
return this.searchText.toString() === ''
|| (contentProvider.name + " " + contentProvider.officialname).match(this.searchText) != null;
return textFlag;
}
private sort() {
let sortOption: { sort: string, descending: boolean } = this.filterForm.get('sort').value;
this.previewCommunityContentProviders.sort((left, right): number => {
if (sortOption.sort == "name") {
if (left.name > right.name) {
return sortOption.descending ? -1 : 1;
} else if (left.name < right.name) {
return sortOption.descending ? 1 : -1;
}
} else if (sortOption.sort == "officialname") {
if (left.officialname > right.officialname) {
return sortOption.descending ? -1 : 1;
} else if (left.officialname < right.officialname) {
return sortOption.descending ? 1 : -1;
}
}
return 0;
});
handleSuccess(message) {
NotificationHandler.rise(message);
}
public onSearchClose() {
this.communitySearchUtils.keyword = this.filterForm.get('keyword').value;
handleError(message: string, error = null) {
if (error) {
console.error(error);
}
NotificationHandler.rise(message, 'danger');
}
public resetInput() {
this.communitySearchUtils.keyword = null;
this.searchInputComponent.reset()
}
handleError(message: string) {
UIkit.notification(message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
}
goToCriteria(openaireId: string) {
this._router.navigate([openaireId], {
queryParams: {

View File

@ -3,7 +3,7 @@ import {Component} from '@angular/core';
@Component({
selector: 'openaire-error',
template: `
<div class="uk-margin-large-top">
<div class="uk-section">
<error></error>
</div>
`

View File

@ -85,13 +85,13 @@ declare var UIkit;
<span class="uk-margin-small-left">Add New Affiliation</span>
</button>
</div>
<div class="uk-margin-medium uk-grid uk-child-width-1-2@m uk-child-width-1-1" uk-grid>
<div class="uk-margin-medium uk-grid uk-child-width-1-2@m uk-child-width-1-1" uk-height-match="target: .uk-card-body; row: false" uk-grid>
<div *ngFor="let affiliation of affiliations.controls; let i=index">
<div class="uk-card uk-card-default uk-margin-bottom">
<div class="uk-card-body">
<div class="uk-flex uk-flex-middle uk-flex-column">
<div class="uk-width-small uk-height-max-small">
<img [src]="affiliation.value.logo_url | urlPrefix">
<div class="uk-flex uk-flex-center">
<img class="uk-height-xsmall uk-blend-multiply" [src]="affiliation.value.logo_url | urlPrefix">
</div>
<h5>{{affiliation.value.name}}</h5>
<div class="uk-text-truncate uk-text-small">

@ -1 +1 @@
Subproject commit 65cbf342bc890aff15a8831711f69d9b35e6f85d
Subproject commit 052d94e27ce698a119755973e0b7285d2b64370b

@ -1 +1 @@
Subproject commit 8818983564cb9e9232979af27fa568c18fa4eba8
Subproject commit 319eff1cc355ffc4148cf20c4ba23e15fbc6a6f6

@ -1 +1 @@
Subproject commit 25f7f7dd34fae80d1e2e25935c2f2772c5800e70
Subproject commit 35bca0f68bf19337413167ecf770f1027902964f

View File

@ -85,5 +85,6 @@ export let properties: EnvProperties = {
lastIndexUpdate: "2020-05-06",
indexInfoAPI: "https://beta.services.openaire.eu/openaire/info/",
admins: ["rcd@openaire.eu"],
adminPortalURL: "https://beta.admin.connect.openaire.eu"
adminPortalURL: "https://beta.admin.connect.openaire.eu",
errorLink: '/error'
};

View File

@ -85,5 +85,6 @@ export let properties: EnvProperties = {
lastIndexUpdate: "2020-12-17",
indexInfoAPI: "https://services.openaire.eu/openaire/info/",
admins: ["rcd@openaire.eu"],
adminPortalURL: "https://admin.connect.openaire.eu"
adminPortalURL: "https://admin.connect.openaire.eu",
errorLink: '/error'
};

View File

@ -90,5 +90,6 @@ export let properties: EnvProperties = {
lastIndexUpdate: '2019-05-16',
indexInfoAPI: 'http://beta.services.openaire.eu/openaire/info/',
admins: ['kostis30fylloy@gmail.com'],
adminPortalURL: 'https://beta.admin.connect.openaire.eu'
adminPortalURL: 'https://beta.admin.connect.openaire.eu',
errorLink: '/error'
};