Compare commits

..

13 Commits

Author SHA1 Message Date
Konstantina Galouni 8672fb6359 [deprecated-angular-upgrade | DONE | FIXED]: number-utils.class.ts: avoid rounding numbers < 1000 (3-digit) | refineFieldResults.service.ts: Added method "getAllRefineFieldResultsByFieldName()" to get all values of a specific refine field (not just first 100) | numbers.component.ts: Updated method called in refine query to get funders of projects from "getRefineFieldsResultsByEntityName()" to "getAllRefineFieldResultsByFieldName()" to be able to get more than 100 funders each time. 2023-11-24 13:53:46 +02:00
Konstantinos Triantafyllou 93cdc71cf0 Update angular to version 16 2023-08-24 16:31:24 +03:00
Alex Martzios 145cd1dd94 Rename of 'content provider', 'dataset', 'software' 2023-03-21 10:52:57 +02:00
Alex Martzios 4dfe5f989a update OpenAIRE Graph name 2023-02-23 14:28:02 +02:00
Alex Martzios 8f2fce6a19 new menu entries for Graph 2022-12-20 14:19:26 +02:00
Alex Martzios e837d55e27 progress on changing the graph menu items 2022-12-20 10:04:16 +02:00
Alex Martzios 825e29b5af changes for FormGroup and FormBuilder 2022-12-15 13:00:31 +02:00
Alex Martzios b93dff4f1b Fix all Promises with type <any> to type <void> 2022-12-15 12:44:38 +02:00
Konstantina Galouni b90c7a4ebf [Library | Deprecated]: navigationBar.component.html: Added class="uk-position-top-right" to fix navbar - do not become sticky, stay on top fixed. 2022-09-27 15:23:04 +03:00
Alex Martzios 3c1429f6b7 update url for newsletter in the footer 2022-08-02 13:04:57 +03:00
argirok ad60292049 add [Beta] indication for FOS/SDGs 2022-04-18 16:26:56 +03:00
argirok 45be028336 remove b2note components, dependencies, properties and remove from landing 2022-04-15 17:01:32 +03:00
argirok 14b80fb1c3 update query for datasources (registries, journals, etc) 2022-04-15 16:59:41 +03:00
631 changed files with 23196 additions and 47736 deletions

View File

@ -1,200 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,5 +1,6 @@
import {Injectable, Inject, PLATFORM_ID, TransferState} from '@angular/core';
import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';
import { TransferState } from '@angular/core';
import { properties } from "../../environments/environment";
@Injectable({
@ -8,39 +9,29 @@ import { properties } from "../../environments/environment";
export class CacheInterceptorService implements HttpInterceptor {
cachingRequests = [
// Remove 2 following lines when bug with hidden refine filters is solved.
"/resources2/?format=json&refine=true&fields=instancetypename&fields=foslabel&fields=relfunder&fields=relfundinglevel0_id&fields=relproject&fields=sdg&fields=country&fields=resultlanguagename&fields=resulthostingdatasource&fields=community&&fq=resultbestaccessright exact \"Open Access\"&type=results&page=0&size=0",
"/resources2/?format=json&refine=true&fields=funder&fields=fundinglevel0_id&fields=projectstartyear&fields=projectendyear&fields=projectoamandatepublications&&type=projects&page=0&size=0",
"/resources2/?format=json&refine=true&fields=resultbestaccessright&fields=relfunder&fields=relfundinglevel0_id&fields=relproject&fields=instancetypename&fields=resultlanguagename&fields=community&fields=resulthostingdatasource&fields=country&&fq=resultbestaccessright exact \"Open Access\"&type=results&page=0&size=0",
"/resources2/?format=json&refine=true&fields=funder&fields=fundinglevel0_id&fields=projectstartyear&fields=projectendyear&fields=projectecsc39&&type=projects&page=0&size=0",
"/resources2/?format=json&refine=true&fields=instancetypename&fields=foslabel&fields=relfunder&fields=sdg&fields=country&fields=resultlanguagename&fields=resulthostingdatasource&fields=community&&type=results&page=0&size=0",
"/resources2/?format=json&refine=true&fields=instancetypename&fields=foslabel&fields=relfunder&fields=relfundinglevel0_id&fields=relproject&fields=sdg&fields=country&fields=resultlanguagename&fields=resulthostingdatasource&fields=community&&fq=resultbestaccessright%20exact%20%22Open%20Access%22&fq=relfunder%20exact%20%22ec__________%3A%3AEC%7C%7CEuropean%20Commission%7C%7CEC%22&type=results&page=0&size=0",
"/resources2/?format=json&refine=true&fields=resultbestaccessright&fields=relfunder&fields=instancetypename&fields=resultlanguagename&fields=community&fields=resulthostingdatasource&fields=country&&type=results&page=0&size=0",
"/resources2/?format=json&refine=true&fields=resultbestaccessright&fields=relfunder&fields=relfundinglevel0_id&fields=relproject&fields=instancetypename&fields=resultlanguagename&fields=community&fields=resulthostingdatasource&fields=country&&fq=resultbestaccessright%20exact%20%22Open%20Access%22&fq=relfunder%20exact%20%22ec__________%3A%3AEC%7C%7CEuropean%20Commission%7C%7CEC%22&type=results&page=0&size=0",
"/resources2/?format=json&refine=true&fields=instancetypename&fields=foslabel&fields=relfunder&fields=sdg&fields=country&fields=resultlanguagename&fields=resulthostingdatasource&fields=community&&type=publications&page=0&size=0",
"/resources2/?format=json&refine=true&fields=instancetypename&fields=foslabel&fields=relfunder&fields=sdg&fields=country&fields=resultlanguagename&fields=resulthostingdatasource&fields=community&&type=datasets&page=0&size=0",
"/resources2/?format=json&refine=true&fields=instancetypename&fields=foslabel&fields=relfunder&fields=sdg&fields=country&fields=resultlanguagename&fields=resulthostingdatasource&fields=community&&type=software&page=0&size=0",
"/resources2/?format=json&refine=true&fields=instancetypename&fields=foslabel&fields=relfunder&fields=sdg&fields=country&fields=resultlanguagename&fields=resulthostingdatasource&fields=community&&type=other&page=0&size=0",
"/resources2/?format=json&refine=true&fields=resultbestaccessright&fields=relfunder&fields=instancetypename&fields=resultlanguagename&fields=community&fields=resulthostingdatasource&fields=country&&type=publications&page=0&size=0",
"/resources2/?format=json&refine=true&fields=resultbestaccessright&fields=relfunder&fields=instancetypename&fields=resultlanguagename&fields=community&fields=resulthostingdatasource&fields=country&&type=datasets&page=0&size=0",
"/resources2/?format=json&refine=true&fields=resultbestaccessright&fields=relfunder&fields=instancetypename&fields=resultlanguagename&fields=community&fields=resulthostingdatasource&fields=country&&type=software&page=0&size=0",
"/resources2/?format=json&refine=true&fields=resultbestaccessright&fields=relfunder&fields=instancetypename&fields=resultlanguagename&fields=community&fields=resulthostingdatasource&fields=country&&type=other&page=0&size=0",
"/resources2/?format=json&refine=true&fields=instancetypename&fields=foslabel&fields=relfunder&fields=sdg&fields=country&fields=resultlanguagename&fields=resulthostingdatasource&fields=community&&fq=resultbestaccessright%20exact%20%22Open%20Access%22&type=results&page=0&size=0",
"/resources2/?format=json&refine=true&fields=instancetypename&fields=foslabel&fields=relfunder&fields=sdg&fields=country&fields=resultlanguagename&fields=resulthostingdatasource&fields=community&&fq=resultbestaccessright exact \"Open Access\"&type=results&page=0&size=0",
"/resources2/?format=json&refine=true&fields=funder&fields=projectoamandatepublications&fields=projectstartyear&fields=projectendyear&&type=projects&page=0&size=0",
"/resources2/?format=json&refine=true&fields=eoscdatasourcetype&fields=datasourceodlanguages&fields=datasourceodcontenttypes&fields=datasourcecompatibilityname&fields=country&fields=collectedfromname&fields=datasourcethematic&fields=datasourcejurisdiction&&type=datasources&page=0&size=0",
// "/resources2/?format=json&query= ( (reldatasourcecompatibilityid exact driver or reldatasourcecompatibilityid exact driver-openaire2.0 or reldatasourcecompatibilityid exact openaire2.0 or reldatasourcecompatibilityid exact openaire3.0 or reldatasourcecompatibilityid exact openaire4.0 or reldatasourcecompatibilityid exact openaire-cris_1.1 or reldatasourcecompatibilityid exact openaire2.0_data or reldatasourcecompatibilityid exact hostedBy or relproject=*) ) &refine=true&fields=country&&type=organizations&page=0&size=0",
"/resources2/?format=json&refine=true&fields=country&&type=organizations&fq=(reldatasourcecompatibilityid exact driver or reldatasourcecompatibilityid exact driver-openaire2.0 or reldatasourcecompatibilityid exact openaire2.0 or reldatasourcecompatibilityid exact openaire3.0 or reldatasourcecompatibilityid exact openaire4.0 or reldatasourcecompatibilityid exact openaire-cris_1.1 or reldatasourcecompatibilityid exact openaire2.0_data or reldatasourcecompatibilityid exact hostedBy or relproject=*)&page=0&size=0&minRef=true",
"/resources2/?format=json&refine=true&fields=resultbestaccessright&fields=relfunder&fields=instancetypename&fields=resultlanguagename&fields=community&fields=resulthostingdatasource&fields=country&&fq=resultbestaccessright%20exact%20%22Open%20Access%22&type=results&page=0&size=0",
"/resources2/?format=json&refine=true&fields=resultbestaccessright&fields=relfunder&fields=instancetypename&fields=resultlanguagename&fields=community&fields=resulthostingdatasource&fields=country&&fq=resultbestaccessright exact \"Open Access\"&type=results&page=0&size=0",
"/resources2/?format=json&refine=true&fields=funder&fields=projectstartyear&fields=projectendyear&fields=projectecsc39&&type=projects&page=0&size=0",
"/resources2/?format=json&refine=true&fields=datasourcetypeuiname&fields=datasourceodlanguages&fields=datasourceodcontenttypes&fields=datasourcecompatibilityname&fields=country&fields=collectedfromname&&type=datasources&page=0&size=0",
"/resources2/?format=json&query= ( (reldatasourcecompatibilityid exact driver or reldatasourcecompatibilityid exact driver-openaire2.0 or reldatasourcecompatibilityid exact openaire2.0 or reldatasourcecompatibilityid exact openaire3.0 or reldatasourcecompatibilityid exact openaire4.0 or reldatasourcecompatibilityid exact openaire-cris_1.1 or reldatasourcecompatibilityid exact openaire2.0_data or reldatasourcecompatibilityid exact hostedBy or relproject=*) ) &refine=true&fields=country&&type=organizations&page=0&size=0",
"/resources2/?format=json&size=0&type=organizations&fq=(reldatasourcecompatibilityid exact driver or reldatasourcecompatibilityid exact driver-openaire2.0 or reldatasourcecompatibilityid exact openaire2.0 or reldatasourcecompatibilityid exact openaire3.0 or reldatasourcecompatibilityid exact openaire4.0 or reldatasourcecompatibilityid exact openaire-cris_1.1 or reldatasourcecompatibilityid exact openaire2.0_data or reldatasourcecompatibilityid exact hostedBy or relproject=*)",
"/projects/?format=json&refine=true&page=1&size=0&fields=funder",
// "/projects/?format=json&refine=true&page=1&size=0&fields=funder",
"/projects/?fields=funder&sf=funder&format=json&size=0",
"/results/?fields=relfunder&sf=relfunder&format=json&size=0",
"/resources/?format=json&query=( oaftype exact datasource and (eoscdatasourcetype exact \"Journal Archive\" or eoscdatasourcetype exact \"Repository\"))&refine=true&fields=datasourcetypename&fields=country&fields=datasourceodsubjects&fields=datasourceodcontenttypes&fields=datasourcecompatibilityname&fields=datasourcethematic&fields=datasourcejurisdiction&&type=datasources&page=0&size=0",
"/resources/?format=json&query=( oaftype exact datasource )&refine=true&fields=datasourcetypeuiname&fields=country&fields=datasourceodsubjects&fields=datasourceodcontenttypes&fields=datasourcecompatibilityname&&type=datasources&page=0&size=0",
"/search/v2/api/datasources/count?format=json", "/search/v2/api/publications/count?format=json", "/search/v2/api/datasets/count?format=json", "/search/v2/api/software/count?format=json", "/search/v2/api/other/count?format=json",
"relresulttype%3Dpublication",
"/resources2/?format=json&size=0&type=projects",
"/resources2/?format=json&size=0&type=datasources",
"/resources2/?format=json&size=0&type=results",
"/resources2/?format=json&size=0&type=results&fq=resultbestaccessright%20exact%20%22Open%20Access%22"
"relresulttype%3Dpublication"
];
@ -58,13 +49,7 @@ export class CacheInterceptorService implements HttpInterceptor {
}
public checkForCachedRequests(url){
// Do not call cache when it is not enabled at all.
// This property is not correctly used here. A new property should be introduced. For now it is ok.
if (!properties.useLongCache) {
return false;
}
if(url.indexOf("sf=") !== -1 || url.indexOf("refine=true") !== -1 || url.indexOf("/count?format=json") !== -1 || url.indexOf("relresulttype%3Dpublication") !== -1 ||
(url.indexOf("?format=json&size=0&type=") !== -1 && url.indexOf("query=") == -1)) {
if(url.indexOf("refine=true") !== -1 || url.indexOf("/count?format=json") !== -1 || url.indexOf("relresulttype%3Dpublication") !== -1) {
return this.cachingRequests.some(partUrl => (url.indexOf(partUrl) !== -1));
}
return false;

View File

@ -1,133 +1,313 @@
<div>
<div class="uk-width-xlarge@l uk-width-large" [ngClass]="centerAlign ? 'uk-align-center':''">
<advanced-search-input>
<div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..."
[options]="showOptions.selectOptions" class="uk-width-2-5"></div>
<div class="uk-width-expand" input type="text" [(value)]="keyword" [searchable]="true" placeholder="Entities to link"
[hint]="'Search for ' + openaireEntities.COMMUNITIES + '...'" tooltip="true"></div>
</advanced-search-input>
</div>
<div *ngIf="communities"class="uk-padding">
<div class="uk-grid uk-child-width-1-3" uk-height-match=".uk-card" uk-grid>
<div *ngFor="let community of filter()">
<a class="uk-link-reset uk-height-1-1" (click)="select(community.id, community.label)">
<div [title]="(this.results.length>=basketLimit)?'Basket reached the size limit':''"
class="uk-card uk-card-default uk-card-hover uk-padding-small uk-text-center">
<div class="uk-text-right">
<button class="linking-add-button uk-icon-button-small" [class.uk-disabled]="(this.results.length>=basketLimit)" *ngIf="!isSelected(community.id)">
<icon name="add" [flex]="true"></icon>
</button>
<button *ngIf="isSelected(community.id)" class="linking-selected-button uk-icon-button-small">
<icon name="check" [flex]="true"></icon>
</button>
</div>
<img *ngIf="communityLogos && communityLogos[community.id]"
[src]="communityLogos[community.id] | logoUrl"
class="uk-blend-multiply"
[alt]="((community.title)?community.title:(community.shortTitle?community.shortTitle:'')) + ' logo'"
loading="lazy" style="max-height:70px">
<div class="uk-margin-small-top">
{{community.label}}
</div>
</div>
</a>
</div>
</div>
</div>
<ng-container *ngIf="filter().length == 0">
<div class="uk-alert uk-alert-primary"
role="alert">No Results found
</div>
</ng-container>
</div>
<!-- Categories modal-->
<modal-alert #modal large="true">
<div class="uk-modal-body uk-height-min-medium uk-width-expand">
<div class="uk-margin-bottom">
<input [ngModel]="isSelected(selectedCommunityId)" type="checkbox"
(ngModelChange)="isSelected(selectedCommunityId)?removeById(selectedCommunityId):select(selectedCommunityId,
selectedCommunityLabel);">
<span class="uk-margin-small-left">{{selectedCommunityLabel}}</span>
</div>
<div *ngIf="loading" class="uk-alert uk-alert-primary" role="alert">Loading communities information...</div>
<div *ngIf="error" class="uk-alert uk-alert-warning"
role="alert">An error occurred while loading communities...
</div>
<div class="uk-margin-small-top uk-text-small uk-text-meta" *ngIf="categories[selectedCommunityId] &&
categories[selectedCommunityId].length > 0 ">
Optionally, you can <span class="uk-text-bold">specify additional</span> Community's <span
class="uk-text-bold">paths</span> to link your
sources.
</div>
<div *ngIf="categories[selectedCommunityId] && categories[selectedCommunityId].length == 0 "
class=" uk-text-small uk-text-muted">
No additional community paths found for this community.
</div>
<ul *ngIf="categories[selectedCommunityId] && categories[selectedCommunityId].length > 0 "
class=" uk-list uk-margin-small-top uk-margin-left uk-animation-fade uk-overflow-auto uk-height-medium">
<li *ngFor="let category of categories[selectedCommunityId]">
<div (click)="browseConcepts(category.id)">
<input [ngModel]="isSelected(category.id)" type="checkbox"
(ngModelChange)="isSelected(category.id)?removeById(category.id):addNewContext(selectedCommunityLabel,category.label,{'id':category.id, 'label':category.label});">
<span class="uk-margin-small-left">{{category.label}} </span>
<span *ngIf="!conceptsClassDisplay[category.id]" uk-icon="icon:chevron-down; ratio:0.7"></span>
<span *ngIf="conceptsClassDisplay[category.id]" uk-icon="icon:chevron-up; ratio:0.7"></span>
<div>
<div class="uk-grid uk-margin-top uk-animation-fade">
<div class="uk-width-expand">
<div class="uk-grid uk-flex uk-flex-middle">
<div class="uk-width-1-2">
Select communities to link to
</div>
<div class="uk-width-1-2">
<div class="uk-margin">
<div class="uk-inline">
<span class="uk-form-icon uk-icon" ><svg width="20" height="20" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg" icon="search" ratio="1"><circle fill="none" stroke="#000" stroke-width="1.1" cx="9" cy="9" r="7"></circle><path fill="none" stroke="#000" stroke-width="1.1" d="M14,14 L18,18 L14,14 Z"></path></svg></span>
<input class=" uk-input uk-width-medium" [(ngModel)]="keyword" name="keyword"
placeholder="Search communities..."/>
<span *ngIf="keyword.length > 0" class="uk-margin-small-right uk-icon" style="cursor: pointer;"
(click)="keyword='';">
<svg width="20" height="20" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg" data-svg="close"><path fill="none" stroke="#000"
stroke-width="1.06"
d="M16,16 L4,4"></path><path
fill="none"
stroke="#000"
stroke-width="1.06"
d="M16,4 L4,16"></path></svg>
</span>
</div>
</div>
</div>
<div *ngIf="conceptsCategoryLoading[category.id]" class="uk-alert uk-alert-primary"
role="alert">Loading category information...
</div>
<div>
<div class="uk-margin-right uk-padding">
<span *ngFor="let community of communities" [title]="(this.results.length>=basketLimit)?'Basket reached the size limit':''">
<span [class]="((this.results.length>=basketLimit)?'uk-disabled':'')+' uk-margin-small-bottom uk-margin-small-right '+getCommunityClass(community)"
(click)="select(community)" style="cursor:pointer;">
<a href="#modal-categories" uk-toggle>
{{community.label}}
</a>
</span>
</span>
</div>
<div
*ngIf="conceptsClass[category.id] && conceptsClass[category.id].length == 0 && conceptsClassDisplay[category.id]">No more paths found
</div>
<ul *ngIf="conceptsClass[category.id] && conceptsClassDisplay[category.id]"
class="uk-list uk-animation-fade uk-margin-left uk-margin-top" id="ul_{{category.id}}">
<li *ngFor="let concept1 of conceptsClass[category.id]">
<div (click)="displaySubcategory(concept1.id)">
<input [ngModel]="isSelected(concept1.id)" type="checkbox"
(ngModelChange)="isSelected(concept1.id)?removeById(concept1.id):addNewContext(selectedCommunityLabel,category.label,concept1);">
<span class="uk-margin-small-left">{{concept1.label}}</span>
<span *ngIf="concept1.concepts && concept1.concepts.length==0">
<span *ngIf="!conceptsClassDisplay[concept1.id]" uk-icon="icon:chevron-down; ratio:0.7"></span>
<span *ngIf="conceptsClassDisplay[concept1.id]" uk-icon="icon:chevron-up; ratio:0.7"></span>
<!-- Categories modal-->
<div id="modal-categories" uk-modal="bg-close:false;">
<div class="uk-modal-dialog uk-modal-body uk-height-min-medium">
<a class="uk-modal-close uk-position-right uk-margin-right uk-margin-top" type="button">
<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg" data-svg="close-icon">
<line fill="none" stroke="#000" stroke-width="1.1" x1="1" y1="1" x2="13" y2="13"></line>
<line fill="none" stroke="#000" stroke-width="1.1" x1="13" y1="1" x2="1" y2="13"></line>
</svg>
</a>
<div class="portal-color uk-margin-top">
<span class="uk-icon-button icon-button-small portal-icon-button uk-icon">
<svg height="20" icon="check" ratio="1" viewBox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg"><polyline fill="none" points="4,10 8,15 17,4" stroke="#000" stroke-width="1.1"></polyline></svg>
</span>
</div>
<div>
<div
*ngIf="concept1.concepts && concept1.concepts.length==0 && conceptsClassDisplay[concept1.id]">No more paths found
<span
class="uk-text-bold">{{selectedCommunityLabel}}</span> community is now in your Links Basket
</div>
<div *ngIf="loading" class="uk-alert uk-alert-primary" role="alert">Loading communities information...</div>
<div *ngIf="error" class="uk-alert uk-alert-warning"
role="alert">An error occured while loading communities...
</div>
<!-- *ngIf="categories[selectedCommunityId] && categories[selectedCommunityId].length > 0 " -->
<div class="uk-margin-small-top uk-text-small" *ngIf="categories[selectedCommunityId] &&
categories[selectedCommunityId].length > 0 ">
Optionally, you can specify additional Community's paths to link your sources.
</div>
<div *ngIf="categories[selectedCommunityId] && categories[selectedCommunityId].length == 0 "
class=" uk-margin-small-top uk-text-small uk-text-muted">
No aditional community paths found for this community.
</div>
<ul *ngIf="categories[selectedCommunityId] && categories[selectedCommunityId].length > 0 "
class=" uk-list uk-margin-top uk-animation-fade uk-overflow-auto uk-height-medium">
<li *ngFor="let category of categories[selectedCommunityId]">
<span (click)="browseConcepts(category.id)">
<span *ngIf="!conceptsClassDisplay[category.id]" class="uk-icon"><svg width="20" height="20"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
ratio="1"> <polygon
points="8 5 13 10 8 15"></polygon></svg></span>
<span *ngIf="conceptsClassDisplay[category.id]" class="uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon
points="5 7 15 7 10 12"></polygon></svg>
</span>
{{category.label}} - {{category.id}}</span>
<a *ngIf="!isSelected(category.id)"
(click)="addNewContext(selectedCommunityLabel,category.label,{'id':category.id, 'label':category.label})"
[class]="((this.results.length>=basketLimit)?'uk-disabled':'')+' uk-icon-button icon-button-small'">
<span class="uk-icon" [title]="(this.results.length>=basketLimit)?'Basket reached the size limit':''">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="plus"
ratio="0.8"><rect x="9" y="1" width="1" height="17"></rect><rect x="1" y="9" width="17"
height="1"></rect></svg>
</span>
</a>
<span *ngIf="isSelected(category.id)"
class="uk-icon-button icon-button-small portal-icon-button uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="check"
ratio="1"><polyline fill="none" stroke="#000" stroke-width="1.1"
points="4,10 8,15 17,4"></polyline></svg>
</span>
<div *ngIf="conceptsCategoryLoading[category.id]" class="uk-alert uk-alert-primary"
role="alert">Loading category information...
</div>
<ul *ngIf="concept1.concepts && conceptsClassDisplay[concept1.id] "
class="uk-list uk-animation-fade uk-margin-left uk-margin-top">
<li *ngFor="let concept2 of concept1.concepts">
<div (click)="displaySubcategory(concept2.id)">
<input [ngModel]="isSelected(concept2.id)" type="checkbox"
(ngModelChange)="isSelected(concept2.id)?removeById(concept2.id):addNewContext(selectedCommunityLabel,category.label,concept2);" >
<span *ngIf="concept2.concepts && concept2.concepts.length==0">
<span class="uk-margin-small-left">{{concept2.label}}</span><span *ngIf="!conceptsClassDisplay[concept1.id]" uk-icon="icon:chevron-down; ratio:0.7"></span>
<span *ngIf="conceptsClassDisplay[concept1.id]" uk-icon="icon:chevron-up; ratio:0.7"></span>
</span>
</div>
<ul *ngIf="concept2.concepts && conceptsClassDisplay[concept2.id] "
class="uk-list uk-animation-fade uk-margin-left uk-margin-top">
<li *ngFor="let concept3 of concept2.concepts">
<input [ngModel]="isSelected(concept3.id)" type="checkbox"
(ngModelChange)="isSelected(concept3.id)?removeById(concept2.id):addNewContext(selectedCommunityLabel,category.label,concept3);">
<span class="uk-margin-small-left">{{concept3.label}}</span>
</li>
</ul>
<div
[class]="(conceptsClassDisplay[category.id] && conceptsClass[category.id] && conceptsClass[category.id].length>5)?'uk-panel-scrollable':''">
<div
*ngIf="conceptsClass[category.id] && conceptsClass[category.id].length == 0 && conceptsClassDisplay[category.id]">No more paths found
</div>
<ul *ngIf="conceptsClass[category.id] && conceptsClassDisplay[category.id]"
class="uk-list uk-animation-fade" id="ul_{{category.id}}">
<li *ngFor="let concept1 of conceptsClass[category.id]">
<span (click)="displaySubcategory(concept1.id)">
<span *ngIf="!conceptsClassDisplay[concept1.id] && concept1.concepts" class="uk-icon"><svg
width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon
points="8 5 13 10 8 15"></polygon></svg></span>
<span *ngIf="conceptsClassDisplay[concept1.id] && concept1.concepts" class="uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon
points="5 7 15 7 10 12"></polygon></svg></span>
{{concept1.label}}
</span>
<a *ngIf="!isSelected(concept1.id)"
(click)="addNewContext(selectedCommunityLabel,category.label,concept1)"
[class]="((this.results.length>=basketLimit)?'uk-disabled':'')+' uk-icon-button icon-button-small'"><span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="plus" ratio="0.8"><rect
x="9" y="1" width="1" height="17"></rect><rect x="1" y="9" width="17" height="1"></rect></svg>
</span></a>
<span *ngIf="isSelected(concept1.id)"
class="uk-icon-button icon-button-small portal-icon-button uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="check"
ratio="1"><polyline fill="none" stroke="#000" stroke-width="1.1"
points="4,10 8,15 17,4"></polyline></svg>
</span>
<div
[class]="(conceptsClassDisplay[concept1.id] && concept1.concepts && concept1.concepts.length>5)?'uk-panel-scrollable':''">
<div
*ngIf="concept1.concepts && concept1.concepts.length==0 && conceptsClassDisplay[concept1.id]">No more paths found
</div>
<ul *ngIf="concept1.concepts && conceptsClassDisplay[concept1.id] " class="uk-animation-fade">
<li *ngFor="let concept2 of concept1.concepts"><span
(click)="displaySubcategory(concept2.id)">
<span *ngIf="!conceptsClassDisplay[concept2.id] && concept2.concepts" class="uk-icon"><svg
width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon
points="8 5 13 10 8 15"></polygon></svg></span>
<span *ngIf="conceptsClassDisplay[concept2.id] && concept2.concepts" class="uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon
points="5 7 15 7 10 12"></polygon></svg></span>
{{concept2.label}}</span>
<a *ngIf="!isSelected(concept2.id)"
(click)="addNewContext(selectedCommunityLabel,category.label,concept2)"
[class]="((this.results.length>=basketLimit)?'uk-disabled':'')+' uk-icon-button icon-button-small'"><span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="plus" ratio="0.8"><rect
x="9" y="1" width="1" height="17"></rect><rect x="1" y="9" width="17" height="1"></rect></svg>
</span></a>
<span *ngIf="isSelected(concept2.id)"
class="uk-icon-button icon-button-small portal-icon-button uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
icon="check" ratio="1"><polyline fill="none" stroke="#000" stroke-width="1.1"
points="4,10 8,15 17,4"></polyline></svg>
</span>
<ul *ngIf="concept2.concepts && conceptsClassDisplay[concept2.id] "
class="uk-animation-fade">
<li *ngFor="let concept3 of concept2.concepts">{{concept3.label}} [title]="(this.results.length>=basketLimit)?'Basket reached the size limit':''"
<a *ngIf="!isSelected(concept3.id)"
(click)="addNewContext(selectedCommunityLabel,category.label,concept3)"
[class]="((this.results.length>=basketLimit)?'uk-disabled':'')+' uk-icon-button icon-button-small'"><span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="plus" ratio="0.8"><rect
x="9" y="1" width="1" height="17"></rect><rect x="1" y="9" width="17" height="1"></rect></svg>
</span></a>
<span *ngIf="isSelected(concept3.id)"
class="uk-icon-button icon-button-small portal-icon-button uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
icon="check" ratio="1"><polyline fill="none" stroke="#000" stroke-width="1.1"
points="4,10 8,15 17,4"></polyline></svg>
</span>
</li>
</ul>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
<!-- </li>
</ul> -->
<p class="">
<button class="uk-button uk-button-default uk-modal-close uk-margin-right uk-margin-top uk-align-right"
type="button">Close
</button>
</p>
</div>
</div>
<!-- <div class="uk-text-large">Select a community <helper div="link-context-form" tooltip=true></helper> </div>
<select [(ngModel)]="selectedCommunityId" (ngModelChange)="communityChanged()" class="uk-margin-large-bottom uk-select uk-width-medium " name="select_funder" >
<option value="0" >Select community</option>
<option *ngFor="let community of communities" [value]="community.id" >{{community.label}}</option>
</select> -->
<!--div class="uk-text-large">and then</div>
<div class=" uk-margin-left uk-margin-left">
<div class=" uk-text-bold">search for community concepts</div>
<table class="uk-margin-remove uk-width-1-1 uk-table uk-table-responsive" ><tr>
<tr>
<td *ngIf="selectedCommunityId != '0' && categories.length > 0" class="uk-width-medium">
<select [(ngModel)]="selectedCategoryId" (ngModelChange)="categoryChanged()" class="uk-select uk-width-medium " name="select_funder" >
<option value="0" >Select category</option>
<option *ngFor="let category of categories" [value]="category.id" >{{category.label}}</option>
</select>
</td><td >
<static-autocomplete [(properties)]=properties [(list)] = concepts [allowDuplicates]=true [showSelected]=false [placeHolderMessage] = "'Concept name'" title = "Concepts" [multipleSelections]=true (addItem) = "select($event)" > </static-autocomplete>
</td></tr>
</table>
</div-->
<!-- <div *ngIf="loading" class="uk-alert uk-alert-primary" role="alert">Loading communities information...</div>
<div *ngIf="error" class="uk-alert uk-alert-warning" role="alert">An error occured while loading communities...</div>
<div class="uk-text-large ">or</div>
<div class=" uk-text-bold uk-margin-bottom uk-margin-left">browse through community categories:
<button uk-toggle="target: #browse; animation: uk-animation-fade" class="uk-button portal-button"> Browse </button>
</div> -->
<div class="uk-margin-left">
<!-- <div id="browse" class=" uk-margin-small">
<div *ngIf="selectedCommunityId =='0'" class="uk-alert uk-alert-warning" >Please select community first...</div>
<div *ngIf="selectedCommunityId !='0'" class="uk-panel uk-panel-scrollable">
<ul class="uk-list ">
<li>
<span (click)="displaySubcategory(selectedCommunityId)" >
<span *ngIf="!conceptsClassDisplay[selectedCommunityId]" class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon points="8 5 13 10 8 15"></polygon></svg></span>
<span *ngIf="conceptsClassDisplay[selectedCommunityId]" class="uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon points="5 7 15 7 10 12"></polygon></svg></span>{{selectedCommunityLabel}}
</span>
<a *ngIf="!isSelected(selectedCommunityId)" (click)="addNewContext(selectedCommunityLabel,null,{'id':selectedCommunityId, 'label':selectedCommunityLabel})" class="uk-icon-button icon-button-small uk-icon">
<span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="plus" ratio="0.8"><rect x="9" y="1" width="1" height="17"></rect><rect x="1" y="9" width="17" height="1"></rect></svg>
</span> </a>
<span *ngIf="isSelected(selectedCommunityId)" class="uk-label uk-label-success uk-margin-small-top">Added</span>
<ul *ngIf="conceptsClassDisplay[selectedCommunityId]" class="uk-animation-fade" >
<li *ngFor="let category of categories" >
<span (click)="browseConcepts(category.id)" >
<span *ngIf="!conceptsClassDisplay[category.id]" class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon points="8 5 13 10 8 15"></polygon></svg></span>
<span *ngIf="conceptsClassDisplay[category.id]" class="uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon points="5 7 15 7 10 12"></polygon></svg></span>
{{category.label}}</span><a *ngIf="!isSelected(category.id)" (click)="addNewContext(selectedCommunityLabel,category.label,{'id':category.id, 'label':category.label})" class="uk-icon-button icon-button-small" >
<span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="plus" ratio="0.8"><rect x="9" y="1" width="1" height="17"></rect><rect x="1" y="9" width="17" height="1"></rect></svg>
</span></a>
<span *ngIf="isSelected(category.id)" class="uk-label uk-label-success uk-margin-small-top">Added</span>
<div *ngIf="conceptsCategoryLoading[category.id]" class="uk-alert uk-alert-primary" role="alert">Loading category information...</div>
<ul *ngIf="conceptsClass[category.id] && conceptsClassDisplay[category.id]" class="uk-list uk-animation-fade" id="ul_{{category.id}}" >
<li *ngFor="let concept1 of conceptsClass[category.id]" >
<span (click)="displaySubcategory(concept1.id)" >
<span *ngIf="!conceptsClassDisplay[concept1.id] && concept1.concepts" class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon points="8 5 13 10 8 15"></polygon></svg></span>
<span *ngIf="conceptsClassDisplay[concept1.id] && concept1.concepts" class="uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon points="5 7 15 7 10 12"></polygon></svg></span>
{{concept1.label}}
</span>
<a *ngIf="!isSelected(concept1.id)" (click)="addNewContext(selectedCommunityLabel,category.label,concept1)" class="uk-icon-button icon-button-small"><span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="plus" ratio="0.8"><rect x="9" y="1" width="1" height="17"></rect><rect x="1" y="9" width="17" height="1"></rect></svg>
</span></a>
<span *ngIf="isSelected(concept1.id)" class="uk-label uk-label-success uk-margin-small-top">Added</span>
<ul *ngIf="concept1.concepts && conceptsClassDisplay[concept1.id] " class="uk-animation-fade" >
<li *ngFor="let concept2 of concept1.concepts"><span (click)="displaySubcategory(concept2.id)" >
<span *ngIf="!conceptsClassDisplay[concept2.id] && concept2.concepts" class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon points="8 5 13 10 8 15"></polygon></svg></span>
<span *ngIf="conceptsClassDisplay[concept2.id] && concept2.concepts" class="uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon points="5 7 15 7 10 12"></polygon></svg></span>
{{concept2.label}}</span>
<a *ngIf="!isSelected(concept2.id)" (click)="addNewContext(selectedCommunityLabel,category.label,concept2)" class="uk-icon-button icon-button-small"><span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="plus" ratio="0.8"><rect x="9" y="1" width="1" height="17"></rect><rect x="1" y="9" width="17" height="1"></rect></svg>
</span></a>
<span *ngIf="isSelected(concept2.id)" class="uk-label uk-label-success uk-margin-small-top">Added</span>
<ul *ngIf="concept2.concepts && conceptsClassDisplay[concept2.id] " class="uk-animation-fade" >
<li *ngFor="let concept3 of concept2.concepts">{{concept3.label}}
<a *ngIf="!isSelected(concept3.id)" (click)="addNewContext(selectedCommunityLabel,category.label,concept3)" class="uk-icon-button icon-button-small"><span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="plus" ratio="0.8"><rect x="9" y="1" width="1" height="17"></rect><rect x="1" y="9" width="17" height="1"></rect></svg>
</span></a>
<span *ngIf="isSelected(concept3.id)" class="uk-label uk-label-success uk-margin-small-top">Added</span>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</li>
</ul>
</ul>
</div>
</div> -->
</div>
</li>
<div *ngIf="warningMessage.length > 0" class="uk-alert uk-alert-warning" role="alert">{{warningMessage}}</div>
<div *ngIf="infoMessage.length > 0" class="uk-alert uk-alert-primary" role="alert">{{infoMessage}}</div>
</div>
</div>
</ul>
</div>
<div *ngIf="warningMessage.length > 0" class="uk-alert uk-alert-warning" role="alert">{{warningMessage}}</div>
<div *ngIf="infoMessage.length > 0" class="uk-alert uk-alert-primary" role="alert">{{infoMessage}}</div>
</modal-alert>

View File

@ -1,13 +1,11 @@
import {Component, Input, ViewChild} from '@angular/core';
import {Component, Input} from '@angular/core';
import {Router} from '@angular/router';
import {ContextsService} from './service/contexts.service';
import {ClaimEntity, ShowOptions} from './claimHelper.class';
import {ClaimEntity} from './claimHelper.class';
import {Session} from '../../login/utils/helper.class';
import {LoginErrorCodes} from '../../login/utils/guardHelper.class';
import {EnvProperties} from '../../utils/properties/env-properties';
import {Subscriber} from "rxjs";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {CommunitiesService} from "../../connect/communities/communities.service";
import {UserManagementService} from "../../services/user-management.service";
import {Session} from "../../login/utils/helper.class";
declare var UIkit: any;
@ -17,16 +15,13 @@ declare var UIkit: any;
})
export class ClaimContextSearchFormComponent {
@Input() public centerAlign: boolean = false;
@Input() public results:ClaimEntity[];
@Input() public sources;
@Input() public properties: EnvProperties;
@Input() communityId: string = null;
@Input() public inlineClaim: boolean = false;
@Input() basketLimit;
@Input() showOptions:ShowOptions;
@ViewChild('modal') modal;
modalClicked = false;
public selectedCommunityId: string = "0";
public selectedCategoryId: string = "0";
public query = '';
@ -43,47 +38,11 @@ export class ClaimContextSearchFormComponent {
public loading: boolean = false;
public error: boolean = false;
@Input() localStoragePrefix: string = "";
openaireEntities = OpenaireEntities;
entitiesSelectOptions;
keyword = "";
subscriptions = [];
communityLogos = {};
communityIds = [];
user = null;
ngOnInit() {
this.entitiesSelectOptions = this.showOptions.selectOptions;
//get community logos
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
this.user = user;
this.subscriptions.push(this._communitiesService.getCommunities(this.properties, this.properties.communityAPI+"/communities/").subscribe(
communitiesResults => {
if(communitiesResults!=null) {
this.communityLogos = {};
for (let community of communitiesResults) {
if(community.logoUrl && community.logoUrl.length > 0) {
this.communityLogos[community.communityId] = community;
}
}
this.communityIds = communitiesResults.filter(community => {
return community.claim == "all" ||
Session.isCommunityCurator(this.user) ||
Session.isClaimsCurator(this.user) ||
(community.claim == "membersOnly" && Session.isSubscribedTo("community", community.communityId,this.user)) ||
(community.claim == "managersOnly" && Session.isManager("community", community.communityId,this.user))
}).map(community => community.communityId);
this.getCommunities();
}
},
error => {
this.getCommunities();
}
));
}, error => {
}));
this.getCommunities();
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
@ -92,63 +51,36 @@ export class ClaimContextSearchFormComponent {
}
});
}
constructor(private _contextService: ContextsService, private router: Router, private _communitiesService: CommunitiesService, private userManagementService: UserManagementService,) {
constructor(private _contextService: ContextsService, private router: Router) {
}
filter() {
return this.communities?this.communities.filter(community => this.keyword.length ==0 || community.label.toLowerCase().indexOf(this.keyword.toLowerCase()) != -1):[];
getCommunityClass(community) {
let addclass = "";
if (this.isSelected(community.id)) {
addclass += " contextlabelSelected ";
} else {
addclass += " contextlabelNotSelected ";
}
if (this.keyword.length > 0) {
if (community.label.toLowerCase().indexOf(this.keyword.toLowerCase()) == -1) {
addclass += " fadeOut "
}
}
return addclass + 'uk-label';
}
remove(community: any) {
select(community) {
this.selectedCommunityId = community.id;
this.selectedCommunityLabel = community.label;
this.getCategories();
this.removeById(community.id);
this.openModal();
}
removeById(id) {
let index: number = -1;
for (let _i = 0; _i < this.results.length; _i++) {
let item = this.results[_i];
if (item.id == id) {
index = _i;
}
}
if (this.isSelected(community.id)) {
if (index > -1) {
this.results.splice(index, 1);
if (this.results != null) {
localStorage.setItem(this.localStoragePrefix, JSON.stringify(this.results));
}
UIkit.notification(OpenaireEntities.COMMUNITY + ' removed from your basket!', {
status: 'warning',
timeout: 4000,
pos: 'bottom-right'
});
}
}
select(communityId, communityLabel) {
// console.log("SELECT", communityId)
this.selectedCommunityId = communityId;
this.selectedCommunityLabel = communityLabel;
this.getCategories();
if (this.isSelected(communityId)) {
this.removeById(communityId);
} else {
this.addNewContext(communityLabel, null, {'id': communityId, 'label': communityLabel});
this.addNewContext(community.label, null, {'id': community.id, 'label': community.label});
}
}
public openModal() {
this.modalClicked = true;
this.modal.cancelButton = false;
this.modal.okButton = false;
this.modal.alertTitle = this.selectedCommunityLabel;
this.modal.open();
}
isSelected(id): boolean {
for (let _i = 0; _i < this.results.length; _i++) {
let item = this.results[_i];
@ -159,40 +91,44 @@ export class ClaimContextSearchFormComponent {
}
return false;
}
getClaimEntity(community, category, concept){
addNewContext(community, category, concept, notify = true) {
// if (this.results.length > 50) {
// UIkit.notification({
// message: 'Your basket exceeds the number of allowed concepts (50)',
// status: 'warning',
// timeout: 1500,
// pos: 'top-center'
// });
// return;
// }
const entity: ClaimEntity = new ClaimEntity() ;
entity.type = "community";
entity.context = {community: community, category: category, concept: concept};
entity.id = entity.context.concept.id;
return entity;
}
addNewContext(community, category, concept, notify = true) {
const entity: ClaimEntity = this.getClaimEntity(community, category, concept) ;
this.warningMessage = "";
if (!this.isSelected(entity.id)) {
this.results.push(entity);
localStorage.setItem(this.localStoragePrefix, JSON.stringify(this.results));
UIkit.notification(OpenaireEntities.COMMUNITY + ' added in your basket!', {
status: 'success',
timeout: 4000,
pos: 'bottom-right'
});
}
}
getCommunities() {
if (!Session.isLoggedIn()) {
this.saveStateAndRedirectLogin();
} else {
this.loading = true;
this.subscriptions.push(this._contextService.getCommunitiesByState().subscribe(
this.subscriptions.push(this._contextService.getPublicCommunitiesByState().subscribe(
data => {
this.communities = data.filter(community => {
return this.communityIds.indexOf(community.id) != -1
});
this.communities = data;
if (this.communities.length > 0) {
this.communities.sort((n1, n2) => n1.title > n2.title);
this.communities.sort((n1, n2) => n1.label > n2.label);
}
this.loading = false;
if (this.communityId != null && this.communityIds.indexOf(this.communityId) != -1) {
if (this.communityId != null) {
//preselect community
this.selectedCommunityId = this.communityId;
for (let i = 0; i < this.communities.length; i++) {
@ -215,26 +151,25 @@ export class ClaimContextSearchFormComponent {
this.error = true;
}
));
}
}
getCategories() {
this.loading = true;
// this.categories=[];
if (this.selectedCommunityId != '0') {
if (!Session.isLoggedIn()) {
this.saveStateAndRedirectLogin();
} else {
if (this.categories[this.selectedCommunityId]) {
this.loading = false;
if(this.categories[this.selectedCommunityId].length > 0){
this.openModal()
}
return;
}
this.subscriptions.push(this._contextService.getCategories(this.selectedCommunityId, this.properties.contextsAPI).subscribe(
data => {
if(data.length > 0){
this.openModal()
}
this.categories[this.selectedCommunityId] = data;
this.concepts = [];
if (this.query !== "") {
@ -250,9 +185,79 @@ export class ClaimContextSearchFormComponent {
}
));
}
}
}
/*
getConcepts() {
this.loading = true;
if (this.selectedCategoryId != '0') {
if (!Session.isLoggedIn()) {
this.saveStateAndRedirectLogin();
} else {
this.concepts = [];
this._contextService.getConcepts(this.selectedCategoryId, "", true, this.properties.contextsAPI).subscribe(
data => {
this.concepts = data;
for (var i = 0; i < data.length; i++) {
if (data[i].hasSubConcept == true) {
this.getSubConcepts(data[i].id);
}
}
this.addCommunityInConcepts();
if (this.query !== "") {
var event = {value: ""};
event.value = this.query;
// this.filter(event);
}
this.loading = false;
},
err => {
//console.log(err);
this.handleError("Error getting concepts for category with id: " + this.selectedCategoryId, err);
this.loading = false;
}
);
}
} else {
this.concepts = [];
this.loading = false;
}
}*/
/*
getSubConcepts(conceptId) {
this.loading = true;
if (this.selectedCategoryId != '0') {
if (!Session.isLoggedIn()) {
this.saveStateAndRedirectLogin();
} else {
this._contextService.getSubConcepts(conceptId, "", true, this.properties.contextsAPI).subscribe(
data => {
for (var i = 0; i < data.length; i++) {
this.concepts.push(data[i]);
}
if (this.query !== "") {
var event = {value: ""};
event.value = this.query;
// this.filter(event);
}
this.loading = false;
},
err => {
//console.log(err);
this.handleError("Error getting subconcepts for concept with id: " + conceptId, err);
this.loading = false;
}
);
}
} else {
this.concepts = [];
this.loading = false;
}
}*/
displaySubcategory(id) {
if (this.conceptsClassDisplay[id] != null) {
this.conceptsClassDisplay[id] = !this.conceptsClassDisplay[id];
@ -263,6 +268,9 @@ export class ClaimContextSearchFormComponent {
}
browseConcepts(categoryId) {
if (!Session.isLoggedIn()) {
this.saveStateAndRedirectLogin();
} else {
if (this.conceptsClass[categoryId] != null) {
this.conceptsClassDisplay[categoryId] = !this.conceptsClassDisplay[categoryId];
return;
@ -290,6 +298,8 @@ export class ClaimContextSearchFormComponent {
this.conceptsCategoryLoading[categoryId] = false;
}
));
}
}
browseSubConcepts(categoryId, conceptId) {
@ -311,6 +321,59 @@ export class ClaimContextSearchFormComponent {
}
// communityChanged(){
// this.warningMessage = "";
// this.infoMessage = "";
// for(var i = 0; i< this.communities.length; i++){
// if(this.communities[i].id==this.selectedCommunityId){
// this.selectedCommunityLabel = this.communities[i].label;
// break;
// }
// }
// this.selectedCategoryId = "0";
// this.selectedCategoryLabel="Select Category:";
// if(this.selectedCommunityId != "0"){
// this.getCategories();
// }
// }
// categoryChanged(){
// this.warningMessage = "";
// this.infoMessage = "";
// for(var i = 0; i< this.categories.length; i++){
// if(this.categories[i].id==this.selectedCategoryId){
// this.selectedCategoryLabel = this.categories[i].label;
// break;
// }
// }
// this.getConcepts();
// }
/* addCommunityInConcepts() {
this.concepts.push({"id": this.selectedCommunityId, "label": this.selectedCommunityLabel});
// if(this.autocomplete){
// this.autocomplete.updateList(this.concepts);
// }
}*/
saveStateAndRedirectLogin() {
// if(this.projects != null){
// localStorage.setItem(this.localStoragePrefix + "projects", JSON.stringify(this.projects));
// }
// localStorage.setItem(this.localStoragePrefix + "contexts", JSON.stringify(this.selectedList));
if (this.results != null) {
localStorage.setItem(this.localStoragePrefix + "results", JSON.stringify(this.results));
}
if (this.sources != null) {
localStorage.setItem(this.localStoragePrefix + "sources", JSON.stringify(this.sources));
}
this.router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this.router.url
}
});
}
private static handleError(message: string, error) {
console.error("Claim context search form (component): " + message, error);
}

View File

@ -1,26 +1,18 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../../openaireLibrary/shared/shared.module';
import { SharedModule } from '../../shared/shared.module';
import { ClaimContextSearchFormComponent } from './claimContextSearchForm.component';
import {StaticAutocompleteModule} from '../../utils/staticAutoComplete/staticAutoComplete.module';
import { RouterModule } from '@angular/router';
import {HelperModule} from '../../utils/helper/helper.module';
import {ClaimProjectsSearchFormModule} from "./claimProjectSearchForm.module";
import {AdvancedSearchInputModule} from "../../sharedComponents/advanced-search-input/advanced-search-input.module";
import {InputModule} from "../../sharedComponents/input/input.module";
import {CommunitiesService} from "../../connect/communities/communities.service";
import {LogoUrlPipeModule} from "../../utils/pipes/logoUrlPipe.module";
import {IconsModule} from "../../utils/icons/icons.module";
import {AlertModalModule} from "../../utils/modal/alertModal.module";
@NgModule({
imports: [
SharedModule, RouterModule,
SharedModule,RouterModule,
StaticAutocompleteModule,
HelperModule, ClaimProjectsSearchFormModule, AdvancedSearchInputModule, InputModule, LogoUrlPipeModule, IconsModule, AlertModalModule
HelperModule
],
providers: [CommunitiesService],
declarations: [
ClaimContextSearchFormComponent
], exports: [ClaimContextSearchFormComponent ]

View File

@ -1,7 +1,5 @@
//Classes used in linking / inlinelinking when selecting an entity
import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {ClaimsProperties} from "./claims.properties";
export class ClaimResult {
public source: string;
@ -29,7 +27,6 @@ export class ClaimResult {
export class ClaimProject {
public funderId: string;
public funderShortname: string;
public funderName: string;
public acronym: string;
public startDate: string;
@ -39,12 +36,6 @@ export class ClaimProject {
public fundingLevel0: string;
public url: string;
}
export class ClaimOrganization {
public name: string;
// public shortName: string;
public url: string;
// public country: string;
}
export class ClaimContext {
public community: string;
@ -79,7 +70,6 @@ export class ClaimEntity {
result: ClaimResult;
project: ClaimProject;
context: ClaimContext;
organization: ClaimOrganization;
constructor() {
this.warningMessages = [];
@ -101,7 +91,6 @@ export class ClaimRecord2Insert {
targetAccessRights: string;
targetEmbargoEndDate: string;
claimedInDashboard: string;
idSuffix:string;
constructor() {
@ -116,7 +105,7 @@ export class ClaimDBRecord {
targetType: string;
semantics: string;
approved: string;
source: ClaimDBResult | ClaimDBProject | ClaimDBContext;
source: ClaimDBResult | ClaimProject | ClaimContext;
target: ClaimDBResult;
indexed:boolean;
}
@ -125,12 +114,7 @@ export class ClaimDBContext {
title: string;
openaireId: string;
}
export class ClaimDBOrganization {
openaireId: string;
name: string;
shortName: string;
country: string;
}
export class ClaimDBProject {
openaireId: string;
name: string;
@ -158,9 +142,9 @@ export class ShowOptions {
show: string; //show values: source, result, project, context, claim
linkTo: string; // linkTo /values: result, project, context
linkToEntities: string[]; // show linkToEntities /values: result, project, context
basketShowSources: boolean = true;
basketShowLinksTo: boolean = false;
selectOptions= [];
basketShowSources: boolean;
basketShowLinksTo: boolean;
constructor() {
this.show = "source";
this.linkTo = "project";
@ -171,37 +155,23 @@ export class ShowOptions {
showSource() {
this.show = "source";
this.basketswitchToSources();
HelperFunctions.scroll();
}
basketswitchToSources() {
this.basketShowLinksTo = false;
this.basketShowSources = true;
}
basketswitchToLinkTo() {
this.basketShowLinksTo = true;
this.basketShowSources = false;
this.basketShowSources = true;
HelperFunctions.scroll();
}
showLinkTo() {
// console.log(this.linkTo, "showLinkTo")
this.show = this.linkTo;
this.basketswitchToLinkTo();
this.basketShowLinksTo = true;
this.basketShowSources = false;
HelperFunctions.scroll();
}
initSelectOptions(claimProperties:ClaimsProperties){
let options =[];
if(this.linkToEntities.indexOf('result')!=-1){
options.push({value: 'result',label: OpenaireEntities.RESULTS})
showBasketSources() {
if (this.show != 'source') {
this.basketShowSources = !this.basketShowSources;
this.basketShowLinksTo = !this.basketShowSources;
}
if(this.linkToEntities.indexOf('project')!=-1){
options.push({value: 'project',label: claimProperties.SELECT_ENTITIES.projects})
}
if(this.linkToEntities.indexOf('context')!=-1){
options.push({value: 'context',label: OpenaireEntities.COMMUNITIES})
}
this.selectOptions = options;
// console.log(options, claimProperties.SELECT_ENTITIES.projects)
}
}

View File

@ -1,76 +1,197 @@
<div class="uk-width-expand" [ngClass]="centerAlign ? 'uk-align-center':''">
<advanced-search-input (searchEmitter)="search(page,size)">
<div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..."
[options]="showOptions.selectOptions" class="uk-width-medium@xl uk-width-auto"></div>
<div *ngIf="funderOptions && funderOptions.length > 0" input type="select" [(value)]="selectedFunder" placeholder="Funder" hint="Select Funder..."
[options]="funderOptions" class="uk-width-expand" (valueChange)="funderChanged($event)"></div>
<div class="uk-width-expand" input type="text" [(value)]="keyword" [searchable]="true" placeholder="Projects to link"
[hint]="'Search for ' + openaireEntities.PROJECTS + '...'" tooltip="true" [disabled]="isNoProjectFunder"></div>
</advanced-search-input>
</div>
<div *ngIf=" openaireResultsStatus != errorCodes.LOADING && !isNoProjectFunder && this.selectedFunder && openaireResults.length == 0">
<div class="uk-text-center uk-text-large uk-text-meta uk-margin-large-top">No {{openaireEntities.PROJECT.toLowerCase()}} results yet... <br>Start
searching for {{openaireEntities.PROJECTS.toLowerCase()}} to add them in the Basket
<form class=" uk-margin-top uk-animation ">
<div class="uk-margin-small-bottom">Start searching for projects and add them to the basket to link them to your sources
<!-- <helper div="link-project-form" tooltip=true></helper> -->
</div>
<!-- <input class=" uk-input uk-width-large" [(ngModel)]="keyword" name="keyword" placeholder="Search for projects..."/>-->
<div class="uk-inline">
<a *ngIf="keyword.length > 0" class="uk-form-icon uk-form-icon-flip"
(click)="keyword = ''"
uk-icon="icon: close"></a>
<input type="text" class="uk-input uk-width-xlarge@l uk-width-large@m uk-width-medium"
placeholder="Search for projects..." aria-describedby="sizing-addon2"
[(ngModel)]="keyword" name="keyword">
</div>
<span class="input-group-btn space">
<button (click)="search(page,size)" type="submit" class=" uk-button portal-button">Search</button>
</span>
</form>
<div *ngIf="!showResults">
<div class="uk-text-center uk-text-large uk-text-muted uk-margin-large-top">No project results yet... <br>Start
searching for projects to add them in the Basket
</div>
</div>
<div *ngIf=" openaireResultsStatus != errorCodes.LOADING && this.funderOptions.length > 1 && !this.selectedFunder && openaireResultsNum <= 0 ">
<div class="uk-text-center uk-text-large uk-text-meta uk-margin-large-top">Select funder or search for projects to proceed
<div *ngIf="showResults" class="uk-margin-top">
<div *ngIf="openaireResultsStatus == errorCodes.NONE" class="uk-alert uk-alert-primary"
role="alert">No Results found
</div>
</div>
<div class="uk-margin-top">
<div class="uk-grid" uk-grid>
<div *ngIf="!isNoProjectFunder && openaireResultsStatus != errorCodes.LOADING && openaireResultsNum > 1 " class="search-filters uk-width-1-1">
<div class="uk-grid uk-grid-small" uk-grid>
<ng-container *ngFor="let filter of rangeFilters">
<div>
<dropdown-filter [name]="filter.selectedFromAndToValues?filter.selectedFromAndToValues:filter.title"
dropdownMinWidth="450">
<div class="uk-padding-small">
<range-filter [isDisabled]="openaireResultsStatus == errorCodes.LOADING"
[filter]="filter" (onFilterChange)="dateFilterChanged(filter)"
[showQuickButtons]="false"
></range-filter>
</div>
</dropdown-filter>
<div *ngIf="openaireResultsStatus == errorCodes.ERROR" class="uk-alert uk-alert-warning"
role="alert">An Error Occured
</div>
<div *ngIf="openaireResultsStatus == errorCodes.NOT_AVAILABLE" class="uk-alert uk-alert-danger"
role="alert">Service not available
</div>
<div class="uk-grid">
<div class="search-filters uk-width-medium">
<!-- <div class="uk-width-1-1 uk-margin-small-bottom ">
<div *ngIf="countFilters()>0" class="uk-margin-small-bottom">
<span *ngIf = "searchUtils.keyword.length > 0"><span class="uk-text-bold">Keywords:</span>
<a (click) = "clearKeywords() " title="Remove keywords" [class]="((disableForms)?' uk-disabled':' ')+' portal-color '"><span class=" clickable " aria-hidden="true"><span class="uk-icon ">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="close" ratio="0.8"><path fill="none" stroke="#000" stroke-width="1.6" d="M16,16 L4,4"></path><path fill="none" stroke="#000" stroke-width="1.6" d="M16,4 L4,16"></path></svg>
</span></span></a>
<span [innerHtml]="searchUtils.keyword"></span>
</span>
<div *ngFor="let filter of filters " >
<span *ngIf = "filter.countSelectedValues > 0"> <span class="uk-text-bold">{{filter.title}}:</span>
<span *ngFor="let value of getSelectedValues(filter); let i = index; let end = last; " >
<a [title]="'Remove '+value.name"(click) = "removeFilter(value, filter) " [class]="((disableForms)?' uk-disabled':' ')+' portal-color '"><span class=" clickable" aria-hidden="true"><span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="close" ratio="0.8"><path fill="none" stroke="#000" stroke-width="1.6" d="M16,16 L4,4"></path><path fill="none" stroke="#000" stroke-width="1.6" d="M16,4 L4,16"></path></svg>
</span></span></a>
<span [innerHtml]="(value.name.length > 25)?value.name.substring(0,25)+'...':value.name" [title]="value.name"></span><span *ngIf="!end" class=" ">, </span>
</span>
</span>
</div>
</ng-container>
<ng-container *ngFor="let filter of filters ">
<div>
<dropdown-filter [count]="filter.countSelectedValues" [name]="filter.title"
dropdownMinWidth="450">
<div class="uk-padding-small">
<search-filter [isDisabled]="openaireResultsStatus == errorCodes.LOADING"
[filter]="filter" [filterValuesNum]="0" [showResultCount]=true
(onFilterChange)="filterChanged($event)" [actionRoute]="false"></search-filter>
</div>
</dropdown-filter>
</div>
</ng-container>
</div>
<div class="uk-margin-small-bottom uk-margin-small-top uk-grid">
<a *ngIf="countFilters()>1" (click)="clearFilters()" [class]="((disableForms)?'uk-disabled uk-link-muted':'')+' portal-link ' + 'uk-width-1-2'">
Clear All
</a>
</div>
<!-- </ng-container>-->
</div> -->
<div *ngIf="countFilters()>0" class="uk-grid uk-flex uk-flex-bottom">
<div class="uk-grid">
<h6 class="uk-text-bold">Filters</h6>
<a *ngIf="countFilters()>1" (click)="clearFilters()"
[class]="((openaireResultsStatus ==
errorCodes.LOADING)?'uk-disabled uk-link-muted':'')+' portal-link '">
Clear All
</a>
</div>
<div *ngIf="countFilters()>0" class="uk-grid uk-grid-small uk-text-small uk-margin-small-top " uk-grid>
<ng-container *ngFor="let filter of rangeFilters " >
<ng-container *ngIf = "filter.selectedFromAndToValues">
<span [title]="'Remove '+ filter.selectedFromAndToValues" (click) = "removeRangeFilter(filter) " >
<span class="selectedFilterLabel ">
<a [class]="((openaireResultsStatus ==
errorCodes.LOADING)?' uk-disabled':' ')+' uk-link-text '">
<span class=" clickable" aria-hidden="true">
<span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="close" ratio="0.8"><path fill="none" stroke="#000" stroke-width="1.6" d="M16,16 L4,4"></path><path fill="none" stroke="#000" stroke-width="1.6" d="M16,4 L4,16"></path></svg>
</span>
</span>
<span class="uk-margin-small-left">{{filter.selectedFromAndToValues}}</span>
</a>
</span>
</span>
</ng-container>
</ng-container>
<ng-container *ngFor="let filter of filters " >
<ng-container *ngIf = "filter.countSelectedValues > 0">
<span *ngFor="let value of getSelectedValues(filter); let i = index; let end = last; "
[title]="'Remove '+value.name" (click) = "removeFilter(value, filter) " >
<!-- if no grid on the div above, remove it and move class 'selectedFilterLabel' on top span -->
<span class="selectedFilterLabel ">
<a [class]="((openaireResultsStatus ==
errorCodes.LOADING)?' uk-disabled':' ')+' uk-link-text '">
<span class=" clickable" aria-hidden="true">
<span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="close" ratio="0.8"><path fill="none" stroke="#000" stroke-width="1.6" d="M16,16 L4,4"></path><path fill="none" stroke="#000" stroke-width="1.6" d="M16,4 L4,16"></path></svg>
</span>
</span>
<span class="uk-margin-small-left" [innerHtml]="(value.name.length > 34)?value.name.substring(0,34)+'...':value.name"></span>
</a>
</span>
</span>
</ng-container>
</ng-container>
</div>
</div>
<!--<ul class="uk-list">
<li class="uk-open">
<h6 class="uk-margin-bottom-remove ">Active between
</h6>
<div aria-expanded="false">
<div class="searchFilterBoxValues ">
<form class="uk-inline">
<input class=" uk-input uk-width-2-5" [(ngModel)]="startYear" name="keyword"
placeholder="Year (e.g 1990)"/>
<input class=" uk-input uk-width-2-5" [(ngModel)]="endYear" name="keyword"
placeholder="Year (e.g 1990)"/>
<button type="submit" (click)="yearChanged()" style="cursor: pointer;" class="uk-icon"><svg width="20"
height="20"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
icon="chevron-right"
ratio="1"><polyline
fill="none" stroke="#000" stroke-width="1.03" points="7 4 13 10 7 16"></polyline></svg></button>
</form>
</div>
</div>
</li>
</ul>-->
<ng-container *ngFor="let filter of rangeFilters">
<li>
<range-filter [isDisabled]="openaireResultsStatus ==
errorCodes.LOADING" [filter]="filter" (onFilterChange)="dateFilterChanged(filter)"
[showQuickButtons]="false"
></range-filter>
</li>
</ng-container>
<search-filter *ngFor="let filter of filters " [isDisabled]="false" [filter]="filter" [showResultCount]=true
(onFilterChange)="filterChanged($event)" [actionRoute]="false"></search-filter>
</div>
<div class="uk-width-expand@m uk-width-1-1@s uk-first-column">
<div *ngIf="openaireResultsStatus == errorCodes.NONE" class="uk-alert uk-alert-primary"
role="alert">No Results found
</div>
<div *ngIf="openaireResultsStatus == errorCodes.ERROR" class="uk-alert uk-alert-warning"
role="alert">An Error Occured
</div>
<div *ngIf="openaireResultsStatus == errorCodes.NOT_AVAILABLE" class="uk-alert uk-alert-danger"
role="alert">Service not available
</div>
<div *ngIf="openaireResultsStatus == errorCodes.LOADING" class="uk-animation-fade uk-margin-top uk-width-1-1"
role="alert">
<loading></loading>
</div>
<claim-results [localStoragePrefix]="localStoragePrefix" [results]=openaireResults
[selectedResults]=selectedProjects [basketLimit]="basketLimit"></claim-results>
<div *ngIf="isNoProjectFunder && openaireResultsStatus != errorCodes.LOADING " class="uk-alert uk-alert-default">No projects for funder <span class=" uk-text-bold">{{selectedFunder.name}}</span>. </div>
<div *ngIf="openaireResultsNum != null && openaireResultsNum > 0 && openaireResultsStatus != errorCodes.LOADING " class="uk-flex uk-flex-center ">
<paging-no-load [currentPage]="openaireResultsPage"
<!-- <div *ngIf="openaireResultsNum != null && openaireResultsNum > 0" class="uk-clearfix portal-hr ">
<div class="uk-grid">
<div *ngIf="openaireResultsNum>0" class="uk-width-1-2">
<span class="portal-color">{{openaireResultsNum|number}}</span> projects, page <span
class="portal-color">{{openaireResultsPage | number}}</span> of <span
class="portal-color">{{totalPages(openaireResultsNum)|number}}</span>
</div>
<div class="uk-width-1-2 uk-padding-remove">
<paging-no-load class="uk-float-right" [currentPage]="openaireResultsPage"
[totalResults]="openaireResultsNum" [term]="keyword" [size]="size"
(pageChange)="openaireResultsPageChange($event)"></paging-no-load>
</div>
</div>
</div>-->
<div *ngIf="openaireResultsNum != null && openaireResultsNum > 0" class="uk-clearfix ">
<div class= "paging-hr searchPaging uk-margin-small-bottom"
*ngIf="(openaireResultsNum > 0) || (openaireResultsStatus == errorCodes.LOADING)">
<div class="uk-panel uk-margin-small-top uk-grid uk-flex uk-flex-middle">
<div class="uk-width-1-1@s uk-width-1-2@m uk-text-uppercase"
*ngIf="openaireResultsNum > 0">
<span class="uk-text-bold">{{openaireResultsNum|number}}</span>
<span class="uk-text-muted uk-text-uppercase"> projects, page </span>
<span class="uk-text-bold">{{openaireResultsPage | number}}</span>
<span class="uk-text-muted uk-text-uppercase"> of </span>
<span class="uk-text-bold">{{(totalPages(openaireResultsNum)|number)}}</span>
</div>
<div class="float-children-right-at-medium margin-small-top-at-small uk-width-expand uk-padding-remove-left">
<paging-no-load class="uk-float-right" [currentPage]="openaireResultsPage"
[totalResults]="openaireResultsNum" [term]="keyword"
[size]="size" (pageChange)="openaireResultsPageChange($event)"></paging-no-load>
</div>
</div>
</div>
</div>
<div *ngIf="openaireResultsStatus == errorCodes.LOADING" class="uk-animation-fade uk-margin-top uk-width-1-1"
role="alert"><span class="loading-gif uk-align-center"></span></div>
<claim-results [localStoragePrefix]="localStoragePrefix" [results]=openaireResults
[selectedResults]=selectedProjects [basketLimit]="basketLimit"></claim-results>
</div>
</div>
</div>

View File

@ -1,4 +1,4 @@
import {Component, ElementRef, EventEmitter, Input, Output, ViewChild} from '@angular/core';
import {Component, ElementRef, EventEmitter, Input, Output} from '@angular/core';
import {SearchProjectsService} from '../../services/searchProjects.service';
import {ProjectService} from '../../landingPages/project/project.service';
import {ClaimEntity, ClaimProject} from './claimHelper.class';
@ -7,10 +7,9 @@ import {ErrorCodes} from '../../utils/properties/errorCodes';
import {StringUtils} from "../../utils/string-utils.class";
import {Filter, Value} from "../../searchPages/searchUtils/searchHelperClasses.class";
import {RangeFilter} from "../../utils/rangeFilter/rangeFilterHelperClasses.class";
import {OpenaireEntities, SearchFields} from "../../utils/properties/searchFields";
import {SearchFields} from "../../utils/properties/searchFields";
import {NewSearchPageComponent} from "../../searchPages/searchUtils/newSearchPage.component";
import {Subscriber} from "rxjs";
import { properties } from 'src/environments/environment';
declare var UIkit:any;
@ -21,22 +20,31 @@ declare var UIkit:any;
})
export class ClaimProjectsSearchFormComponent {
ngOnInit() {
// this.getFunders();
// this.search(this.page, this.size);
}
// @ViewChild (ModalLoading) loading : ModalLoading ;
// @Input() public inline: boolean = false ; // for claimed started from landing pages
public query = '';
@Input() public centerAlign: boolean = false;
@Input() public selectedProjects:ClaimEntity[]=[] ;
public elementRef;
// public funders:string[];
// public selectedFunderId:string ="0";
// selectedFunderName:string ="Select funder:";
@Output() projectSelected = new EventEmitter();
public properties:EnvProperties = properties;
@Input() public properties:EnvProperties;
@Input() public inlineClaim:boolean=false;
@Input() localStoragePrefix:string = "";
@Input() basketLimit;
@Input() showOptions;
public errorCodes:ErrorCodes = new ErrorCodes();
public projects:string[];
public warningMessage = "";
openaireResults:ClaimEntity[] = [];
openaireResultsNum: number = -1;
openaireResultsNum: number ;
openaireResultsPage : number = 1;
openaireResultsStatus:number = this.errorCodes.NONE;
page : number = 1;
@ -44,95 +52,58 @@ export class ClaimProjectsSearchFormComponent {
keyword:string = '';
showResults = false;
// public openaireRefineFields: string[] = ["relfunder", "relproject", "resultbestaccessright", "instancetypename", "resultlanguagename", "community"];
// public openaireRefineFieldsQuery: string = "&refine=true&fields=funder&fields=projectstartyear&fields=projectendyear&fields=projectecsc39";
public refineFields: string[] = ["funder"];
public refineFieldsQuery: string = "&refine=true&fields=funder";
filters = [];
prevFilters = [];
// startYear = "";
// endYear = "";
public rangeFilters: RangeFilter[] = [];
public searchFields: SearchFields = new SearchFields();
public rangeFields:string[][] = this.searchFields.PROJECT_RANGE_FIELDS;
openaireEntities = OpenaireEntities;
sub;
selectedFunder = null;
funderOptions = [];
isNoProjectFunder = false;
constructor(private _service: ProjectService, private _projectService: SearchProjectsService, myElement: ElementRef) {
this.elementRef = myElement;
this.rangeFilters = RangeFilter.parse(this.rangeFields,"project");
this.getFunders();
this.rangeFilters = RangeFilter.parse(this.rangeFields,"project");
}
sub;
ngOnDestroy() {
if (this.sub instanceof Subscriber) {
this.sub.unsubscribe();
}
}
getFunders(){
this.openaireResultsStatus = this.errorCodes.LOADING;
this.showResults = true;
this.sub = this._projectService.advancedSearchProjects("", 1, 0, this.properties,
this.refineFieldsQuery, this.refineFields, "&type=projects&sf=funder", false, false).subscribe(
data => {
let option = {value : null, label: "No funder selected"};
this.funderOptions.push(option);
for(let v of data[2][0].values){
let option = {value : v, label: v.name};
this.funderOptions.push(option);
}
this.openaireResultsStatus = this.errorCodes.DONE;
}, error =>{
this.openaireResultsStatus = this.errorCodes.ERROR;
})
}
funderChanged(value){
this.keyword = ""
this.selectedFunder = value;
this.isNoProjectFunder = this.selectedFunder && this.selectedFunder.number == 1;
this.openaireResults = [];
this.openaireResultsNum = -1;
if(this.isNoProjectFunder){
this.showResults = true;
this.search(1,1);
}else{
this.openaireResults = [];
}
}
search(page,size) {
/* if (this.keyword.length == 0) {
this.showResults = false;
if(this.keyword.length == 0){
this.showResults =false;
return;
}*/
this.showResults = true;
}
this.showResults =true;
this.openaireResults = [];
this.openaireResultsStatus = this.errorCodes.LOADING;
this.prevFilters = this.filters;
//searchProjects (params: string, refineParams:string, page: number, size: number, refineFields:string[] , properties:EnvProperties ):any {
this.sub = this._projectService.advancedSearchProjects(this.createOpenaireQueryParams(), page, size, this.properties, this.createOpenaireRefineQuery(), [], null, false, false).subscribe(
// this.sub = this._projectService.searchProjects(this.createOpenaireQueryParams(),(page==1)? this.refineFieldsQuery:null, page, size, (page==1)?this.refineFields:[], this.properties).subscribe(
this.sub = this._projectService.searchProjects(this.createOpenaireQueryParams(),(page==1)? this.refineFieldsQuery:null, page, size, (page==1)?this.refineFields:[], this.properties).subscribe(
data => {
if (data != null) {
this.openaireResultsPage = page;
this.openaireResultsNum = data[0];
this.openaireResults = ClaimProjectsSearchFormComponent.openaire2ClaimEntity(data[1], this.properties);
if (data[2] && data[2].length > 0) {
this.filters = this.checkSelectedFilters(data[2], this.prevFilters);
}
if(data != null) {
this.openaireResultsPage=page;
this.openaireResultsNum = data[0];
this.openaireResults =ClaimProjectsSearchFormComponent.openaire2ClaimEntity(data[1], this.properties);
if(data[2] && data[2].length > 0){
this.filters = this.checkSelectedFilters( data[2], this.prevFilters);
}
this.openaireResultsStatus = this.errorCodes.DONE;
if (this.openaireResultsNum == 0) {
this.openaireResultsStatus = this.errorCodes.NONE;
this.filters = this.checkSelectedFilters([], this.prevFilters);
this.openaireResultsStatus = this.errorCodes.DONE;
if(this.openaireResultsNum == 0){
this.openaireResultsStatus = this.errorCodes.NONE;
}
}else {
this.openaireResultsStatus = this.errorCodes.ERROR;
}
/* if(this.isNoProjectFunder && this.claimResultsComponent){
this.claimResultsComponent.add(this.openaireResults[0])
}*/
} else {
this.openaireResultsStatus = this.errorCodes.ERROR;
}
},
},
err => {
this.openaireResultsStatus = this.errorCodes.ERROR;
//console.log(err.status);
@ -140,23 +111,85 @@ export class ClaimProjectsSearchFormComponent {
}
);
}
remove(item){
// select(entity){
// if(this.selectedProjects.length > 50){
// UIkit.notification({
// message : 'Your basket exceeds the number of allowed projects (50)',
// status : 'warning',
// timeout : 1500,
// pos : 'top-center'
// });
// return;
// }
// this.query = "";
// // this.searchTermStream.next(this.query); //clear
// entity = entity.value;
// // var project: ClaimProject = new ClaimProject();
// // project.funderId = entity.funderId;
// // project.funderName = entity.funderName;
// // project.id = entity.id;
// // project.projectName = entity.projectName;
// // project.projectAcronym = entity.projectAcronym;
// // project.startDate = entity.startDate;
// // project.endDate = entity.endDate;
// // project.code = entity.code;
// // project.jurisdiction = entity.jurisdiction;
// // project.fundingLevel0 = entity.fundingLevel0;
//
//
// var index:number =this.selectedProjects.indexOf(entity);
// var found:boolean = false;
// this.warningMessage = "";
//
// for (var _i = 0; _i < this.selectedProjects.length; _i++) {
// let project = this.selectedProjects[_i];
// if(entity.id == project.id){
// found=true;
// this.warningMessage = "Project already in your basket";
// }
// }
//
// if (!found) {
// this.selectedProjects.push(entity);
// if(this.selectedProjects != null){
// localStorage.setItem(this.localStoragePrefix + "projects", JSON.stringify(this.selectedProjects));
// }
// this.projectSelected.emit({
// value: true
// });
//
// }
// }
/* static showItem(item):string{
return ((item.field[1]['@value'])?item.field[1]['@value']+" - ":"" ) + item.field[3]['@value'];
}*/
remove(item){
let index:number =this.selectedProjects.indexOf(item);
if (index > -1) {
this.selectedProjects.splice(index, 1);
}
}
static openaire2ClaimEntity(items, properties:EnvProperties){
/* handleClick(event){
var clickedComponent = event.target;
var inside = false;
do {
if (clickedComponent === this.elementRef.nativeElement) {
inside = true;
}
clickedComponent = clickedComponent.parentNode;
} while (clickedComponent);
}*/
static openaire2ClaimEntity(items, properties:EnvProperties){
const projects: ClaimEntity[] = [];
for(const item of items){
const entity: ClaimEntity = new ClaimEntity();
entity.project = new ClaimProject();
entity.project.funderId = item.funderId;
entity.project.funderShortname = item.funderShortname?item.funderShortname:(entity.project.funderId?entity.project.funderId.split("::")[1]:"");
entity.project.funderName = item.funderName;
entity.project.funderName = item.funderShortname;
entity.id = item.id;
entity.project.url = (item.code !="unidentified") ? properties.searchLinkToProject + entity.id : null;
entity.project.url = properties.searchLinkToProject + entity.id;
entity.title = item.title.name;
entity.project.acronym = item.acronym;
entity.project.startDate = item.startYear;
@ -179,47 +212,43 @@ export class ClaimProjectsSearchFormComponent {
}
createOpenaireQueryParams(): string {
createOpenaireQueryParams():string {
let query = "";
if (this.keyword.length > 0) {
// query += "q=" + StringUtils.quote(StringUtils.URIEncode(this.keyword));
query += StringUtils.quote(StringUtils.URIEncode(this.keyword));
if(this.keyword.length > 0){
query += "q=" + StringUtils.quote(StringUtils.URIEncode(this.keyword));
}
return query;
}
createOpenaireRefineQuery(): string {
/*if(this.startYear.length > 0 ){
query+='&fq=projectstartyear exact \"'+this.startYear+'\"'
}
if(this.endYear.length > 0 ){
query+='&fq=projectendyear exact \"'+this.endYear+'\"'
}*/
let allFqs = "";
for (let filter of this.filters) {
if (filter.countSelectedValues > 0) {
let count_selected = 0;
for (let filter of this.filters){
if(filter.countSelectedValues > 0){
let count_selected=0;
let fq = "";
for (let value of filter.values) {
if (value.selected == true) {
for (let value of filter.values){
if(value.selected == true){
count_selected++;
fq += (fq.length > 0 ? " " + filter.filterOperator + " " : "") + filter.filterId + " exact " + (StringUtils.quote(value.id));
fq+=(fq.length > 0 ? " " + filter.filterOperator + " ":"" ) + filter.filterId + " exact " + (StringUtils.quote(value.id));
}
}
if (count_selected > 0) {
fq = "&fq=" + StringUtils.URIEncode(fq);
if(count_selected > 0){
fq="&fq="+StringUtils.URIEncode(fq);
allFqs += fq;
}
}
}
if(this.selectedFunder){
allFqs += "&fq=" + StringUtils.URIEncode( "funder exact " + (StringUtils.quote(this.selectedFunder.id)));
}
if(!this.isNoProjectFunder || !this.selectedFunder){
allFqs += '&fq=(projectcode<>"unidentified")'
}
for (let i = 0; i < this.rangeFilters.length; i++) {
for (let i=0; i<this.rangeFilters.length; i++){
let filter = this.rangeFilters[i];
//selectedFromValue, selectedToValue, equalityOp, equalityOpFrom, equalityOpTo, filterOp ){
allFqs += NewSearchPageComponent.createRangeFilterQuery(this.rangeFields[i], filter.selectedFromValue, filter.selectedToValue, " within ", ">=", "<=", "and")
allFqs+= NewSearchPageComponent.createRangeFilterQuery(this.rangeFields[i],filter.selectedFromValue, filter.selectedToValue, " within ", ">=" ,"<=", "and" )
}
return allFqs + "&type=projects";
}
return query+allFqs;
}
public yearChanged() {
this.search(this.page, this.size);
@ -254,21 +283,7 @@ export class ClaimProjectsSearchFormComponent {
}
}
filter.countAllValues = filter.values.length;
}
if(filters.length == 0 ){
for(let j=0; j< prevFilters.length ; j++) {
let filter = Object.assign({}, prevFilters[j]);
filter.values = [];
for (let filterValue of prevFilters[j].values) {
if (filterValue.selected) {
filterValue.number = 0;
filter.values.push(filterValue);
}
}
filter.countAllValues = filter.values.length;
filters.push(filter)
}
}
return filters;
}

View File

@ -1,9 +1,11 @@
import {NgModule} from '@angular/core';
import { NgModule } from '@angular/core';
import {SharedModule} from '../../shared/shared.module';
import {CommonModule} from '@angular/common';
import { SharedModule } from '../../shared/shared.module';
import { CommonModule } from '@angular/common';
import {ClaimProjectsSearchFormComponent} from './claimProjectSearchForm.component';
// import {LoadingModalModule} from '../../utils/modal/loadingModal.module';
import {ProjectServiceModule} from '../../landingPages/project/projectService.module';
import {ProjectsServiceModule} from '../../services/projectsService.module';
import {EntitiesAutocompleteModule} from '../../utils/entitiesAutoComplete/entitiesAutoComplete.module';
@ -11,26 +13,23 @@ import {HelperModule} from '../../utils/helper/helper.module';
import {ClaimResultsModule} from './claimResults.module';
import {PagingModule} from '../../utils/paging.module';
import {PagingModule } from '../../utils/paging.module';
import {SearchFilterModule} from '../../searchPages/searchUtils/searchFilter.module';
import {RangeFilterModule} from "../../utils/rangeFilter/rangeFilter.module";
import {AdvancedSearchInputModule} from "../../sharedComponents/advanced-search-input/advanced-search-input.module";
import {InputModule} from "../../sharedComponents/input/input.module";
import {DropdownFilterModule} from "../../utils/dropdown-filter/dropdown-filter.module";
import {LoadingModule} from "../../utils/loading/loading.module";
@NgModule({
imports: [
SharedModule, CommonModule,
// LoadingModalModule,
ProjectServiceModule, ProjectsServiceModule, EntitiesAutocompleteModule, HelperModule,
PagingModule, SearchFilterModule, ClaimResultsModule, RangeFilterModule, AdvancedSearchInputModule, InputModule, DropdownFilterModule, LoadingModule
],
@NgModule({
imports: [
SharedModule, CommonModule,
// LoadingModalModule,
ProjectServiceModule, ProjectsServiceModule, EntitiesAutocompleteModule, HelperModule,
PagingModule, SearchFilterModule, ClaimResultsModule, RangeFilterModule
],
providers:[
],
declarations: [
ClaimProjectsSearchFormComponent,
],
exports: [ClaimProjectsSearchFormComponent]
})
declarations: [
ClaimProjectsSearchFormComponent
],
exports: [ClaimProjectsSearchFormComponent ]
})
export class ClaimProjectsSearchFormModule { }

View File

@ -1,21 +1,28 @@
<div class="uk-flex uk-flex-center uk-flex-left@m">
<div *ngIf="showOptions && showOptions.linkToEntities.length > 0" class="uk-width-xlarge@l uk-width-large" [ngClass]="centerAlign ? 'uk-align-center':''">
<advanced-search-input (searchEmitter)="search(true)">
<div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..."
[options]="showOptions.selectOptions" class="uk-width-2-5"></div>
<div class="uk-width-expand" input type="text" [(value)]="keyword" [searchable]="true" placeholder="Entities to link"
[hint]="'Search for ' + openaireEntities.RESULTS.toLowerCase() + '...'" tooltip="true"></div>
</advanced-search-input>
<form class=" uk-margin-top">
<div class="uk-margin-small-bottom">Start searching Research Outcomes and add them to the Basket to Link
<!-- <helper div="link-entity-form" styleName="" tooltip=true></helper> -->
</div>
<div *ngIf="!showOptions" class="uk-width-xlarge@l uk-width-large">
<div search-input [(value)]="keyword" [placeholder]="'Search for ' + openaireEntities.RESULTS.toLowerCase() + '...'"
[searchInputClass]="'inner background'" (searchEmitter)="search(true)"></div>
<!-- <input class=" uk-input uk-width-large form-control" [(ngModel)]="keyword" name="keyword"-->
<!-- placeholder="Search for research outcomes..."/>-->
<div class="uk-inline">
<a *ngIf="keyword.length > 0" class="uk-form-icon uk-form-icon-flip"
(click)="keyword = ''"
uk-icon="icon: close"></a>
<input type="text" class="uk-input uk-width-xlarge@l uk-width-large@m uk-width-medium"
placeholder="Search for research outcomes..." aria-describedby="sizing-addon2"
[(ngModel)]="keyword" name="keyword">
</div>
</div>
<span class="input-group-btn space">
<button (click)="search(true)" type="submit" class=" uk-button portal-button">Search</button>
</span>
<!--helper div="link-entity-form" styleName="uk-width-medium"></helper-->
</form>
<div *ngIf="!showSearchResults">
<div class="uk-text-center uk-text-large uk-text-meta uk-margin-large-top">
No {{showOptions?openaireEntities.RESULTS.toLowerCase() :'sources'}} yet...<br>Use the searchbar to find and link
{{showOptions?openaireEntities.RESULTS.toLowerCase() :'sources'}}.
<div class="uk-text-center uk-text-large uk-text-muted uk-margin-large-top">
No research outcomes yet...<br>Start searching for research outcomes to add them in the Basket
</div>
</div>
<div *ngIf="showSearchResults" class="uk-margin-top uk-animation">
@ -47,63 +54,135 @@
</div>
<div *ngIf="crossrefResultsNum != null && crossrefResultsNum > 0" class="uk-clearfix ">
<div class="uk-grid">
<!-- <div *ngIf="crossrefResultsNum>0" class="uk-width-1-2">
<span class="portal-color">{{crossrefResultsNum|number}}</span> research outcomes, page <span
class="portal-color">{{crossrefPage | number}}</span> of <span
class="portal-color">{{countTotalPages(crossrefResultsNum)|number}}</span>
</div>-->
<div class="uk-width-1-1@s uk-width-1-2@m uk-text-uppercase"
*ngIf="crossrefResultsNum > 0">
{{crossrefResultsNum|number}}
<span class="uk-text-muted uk-text-uppercase"> research outcomes, page </span>
{{crossrefPage | number}}
<span class="uk-text-muted uk-text-uppercase"> of </span>
{{(countTotalPages(crossrefResultsNum)|number)}}
</div>
<div class="uk-width-1-2 uk-padding-remove-left">
<paging-no-load class="uk-float-right" [currentPage]="crossrefPage" [totalResults]="crossrefResultsNum"
[term]="keyword"
[size]="size" (pageChange)="crossrefPageChange($event)"></paging-no-load>
</div>
</div>
</div>
<div *ngIf="crossrefStatus === errorCodes.LOADING" class="uk-animation-fade uk-margin-top uk-width-1-1"
role="alert">
<loading></loading>
</div>
role="alert"><span class="loading-gif uk-align-center"></span></div>
<div>
<claim-results [localStoragePrefix]=localStoragePrefix [results]=crossrefResults
[selectedResults]=selectedResults [basketLimit]="basketLimit"></claim-results>
</div>
<div class="uk-flex uk-flex-center" *ngIf="crossrefStatus != errorCodes.LOADING && crossrefResultsNum>0 ">
<paging-no-load
[currentPage]="crossrefPage" [totalResults]="crossrefResultsNum"
[term]="keyword"
[size]="size" (pageChange)="crossrefPageChange($event)"></paging-no-load>
</div>
</div>
</div>
<div *ngIf="activeTab == 'openaire'" id="openaire" class="uk-animation-fade">
<div class="uk-grid">
<div class="search-filters uk-width-1-1">
<div class="search-filters uk-width-medium">
<div *ngIf="countFilters()>0" class="uk-grid uk-flex uk-flex-bottom">
<div class="uk-grid">
<h6 class="uk-text-bold">Filters</h6>
<a *ngIf="countFilters()>1" (click)="clearFilters()"
[class]="((openaireResultsStatus ==
errorCodes.LOADING)?'uk-disabled uk-link-muted':'')+' portal-link '">
Clear All
</a>
</div>
<div *ngIf="countFilters()>0" class="uk-grid uk-grid-small uk-text-small uk-margin-small-top " uk-grid>
<ng-container *ngFor="let filter of rangeFilters " >
<ng-container *ngIf = "filter.selectedFromAndToValues">
<span [title]="'Remove '+ filter.selectedFromAndToValues" (click) = "removeRangeFilter(filter) " >
<span class="selectedFilterLabel ">
<a [class]="((openaireResultsStatus ==
errorCodes.LOADING)?' uk-disabled':' ')+' uk-link-text '">
<span class=" clickable" aria-hidden="true">
<span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="close" ratio="0.8"><path fill="none" stroke="#000" stroke-width="1.6" d="M16,16 L4,4"></path><path fill="none" stroke="#000" stroke-width="1.6" d="M16,4 L4,16"></path></svg>
</span>
</span>
<span class="uk-margin-small-left">{{filter.selectedFromAndToValues}}</span>
</a>
</span>
</span>
</ng-container>
</ng-container>
<div *ngIf="openaireResultsNum > 0" class="uk-grid uk-grid-small" uk-grid>
<ng-container *ngFor="let filter of rangeFilters">
<div>
<dropdown-filter [name]="filter.selectedFromAndToValues?filter.selectedFromAndToValues:filter.title"
dropdownMinWidth="450">
<div class="uk-padding-small">
<range-filter [isDisabled]="openaireResultsStatus == errorCodes.LOADING"
[filter]="filter" (onFilterChange)="dateFilterChanged(filter)"
[showQuickButtons]="false"
></range-filter>
</div>
</dropdown-filter>
</div>
</ng-container>
<ng-container *ngFor="let filter of openaireResultsfilters ">
<div *ngIf="(filter.values.length != 0 )">
<dropdown-filter [count]="filter.countSelectedValues" [name]="filter.title"
dropdownMinWidth="450">
<div class="uk-padding-small">
<search-filter [isDisabled]="openaireResultsStatus == errorCodes.LOADING"
[filter]="filter" [filterValuesNum]="0" [showResultCount]=true
(onFilterChange)="filterChanged($event)" [actionRoute]="false"></search-filter>
</div>
</dropdown-filter>
</div>
</ng-container>
<ng-container *ngFor="let filter of openaireResultsfilters " >
<ng-container *ngIf = "filter.countSelectedValues > 0">
<span *ngFor="let value of getSelectedValues(filter); let i = index; let end = last; "
[title]="'Remove '+value.name" (click) = "removeFilter(value, filter) " >
<!-- if no grid on the div above, remove it and move class 'selectedFilterLabel' on top span -->
<span class="selectedFilterLabel ">
<a [class]="((openaireResultsStatus ==
errorCodes.LOADING)?' uk-disabled':' ')+' uk-link-text '">
<span class=" clickable" aria-hidden="true">
<span class="uk-icon">
<svg width="16" height="16" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="close" ratio="0.8"><path fill="none" stroke="#000" stroke-width="1.6" d="M16,16 L4,4"></path><path fill="none" stroke="#000" stroke-width="1.6" d="M16,4 L4,16"></path></svg>
</span>
</span>
<span class="uk-margin-small-left" [innerHtml]="(value.name.length > 34)?value.name.substring(0,34)+'...':value.name"></span>
</a>
</span>
</span>
</ng-container>
</ng-container>
</div>
</div>
<!-- Type filter-->
<ul class="uk-list" >
<!--<li class="uk-open uk-margin-small-bottom">
<h6 class="uk-margin-bottom-remove ">Result Type (4)
</h6>
<div aria-expanded="false">
<div class="searchFilterBoxValues ">
<div *ngFor="let type of openaireTypeValues" class="uk-animation-fade filterItem">
<div title="{{type.title}}">
<input [value]="type.value" [(ngModel)]="openaireResultsType" [name]=type.value
type="radio" (ngModelChange)="openaireTypeChanged(type.value)"/>
{{_formatName(type.title,type.count)}}
<span *ngIf="type.count!=null">{{' (' + (type.count|number) + ')'}}</span>
</div>
</div>
</div>
</div>
</li>-->
<ng-container *ngFor="let filter of rangeFilters">
<li>
<range-filter [isDisabled]="openaireResultsStatus ==
errorCodes.LOADING" [filter]="filter" (onFilterChange)="dateFilterChanged(filter)"
[showQuickButtons]="false"
></range-filter>
</li>
</ng-container>
</ul>
<search-filter *ngFor="let filter of openaireResultsfilters " [isDisabled]="openaireResultsStatus ==
errorCodes.LOADING" [filter]="filter"
[showResultCount]=true
(onFilterChange)="filterChanged($event)" [actionRoute]="false"></search-filter>
</div>
<div class="uk-width-expand@m uk-width-1-1@s uk-first-column">
<div class="">
<div class="uk-margin-top">
<!-- <quick-selections [resultTypes]="resultTypes"
(typeChange)="openaireTypeChanged()" [isDisabled]="openaireResultsStatus ==
errorCodes.LOADING"
[quickFilter]="quickFilter" [QFselected]="(quickFilter)?quickFilter.selected:null"
[properties]="properties">
</quick-selections>-->
<div *ngIf="openaireResultsStatus == errorCodes.NONE" class="uk-alert uk-alert-primary"
role="alert">No Results found
</div>
@ -113,17 +192,31 @@
<div *ngIf="openaireResultsStatus == errorCodes.NOT_AVAILABLE" class="uk-alert uk-alert-danger"
role="alert">Service not available
</div>
<div *ngIf="openaireResultsNum != null && openaireResultsNum > 0" class="uk-clearfix ">
<div class= "paging-hr searchPaging uk-margin-small-bottom"
*ngIf="(openaireResultsNum > 0) || (openaireResultsStatus == errorCodes.LOADING)">
<div class="uk-panel uk-margin-small-top uk-grid uk-flex uk-flex-middle">
<div class="uk-width-1-1@s uk-width-1-2@m uk-text-uppercase"
*ngIf="openaireResultsNum > 0">
<span class="uk-text-bold">{{openaireResultsNum|number}}</span>
<span class="uk-text-muted uk-text-uppercase"> research outcomes, page </span>
<span class="uk-text-bold">{{openaireResultsPage | number}}</span>
<span class="uk-text-muted uk-text-uppercase"> of </span>
<span class="uk-text-bold">{{(countTotalPages(openaireResultsNum)|number)}}</span>
</div>
<div class="float-children-right-at-medium margin-small-top-at-small uk-width-expand uk-padding-remove-left" *ngIf=" openaireResultsStatus != errorCodes.LOADING">
<paging-no-load class="uk-float-right" [currentPage]="openaireResultsPage"
[totalResults]="openaireResultsNum" [term]="keyword"
[size]="size" (pageChange)="openaireResultsPageChange($event)"></paging-no-load>
</div>
</div>
</div>
</div>
<div *ngIf="openaireResultsStatus === errorCodes.LOADING"
class="uk-animation-fade uk-margin-top uk-width-1-1"
role="alert"><loading></loading></div>
role="alert"><span class="loading-gif uk-align-center"></span></div>
<claim-results [localStoragePrefix]=localStoragePrefix
[results]=openaireResults [selectedResults]=selectedResults [basketLimit]="basketLimit"></claim-results>
<div class="uk-flex uk-flex-center" *ngIf=" openaireResultsStatus != errorCodes.LOADING && openaireResultsNum != null && openaireResultsNum > 0" >
<paging-no-load [currentPage]="openaireResultsPage"
[totalResults]="openaireResultsNum" [term]="keyword"
[size]="size" (pageChange)="openaireResultsPageChange($event)"></paging-no-load>
</div>
</div>
</div>
</div>
@ -138,7 +231,30 @@
<div *ngIf="orcidStatus == errorCodes.NONE && orcidResultsNum == -1"
class="uk-alert uk-alert-primary "> No results found
</div>
<div *ngIf=" ((orcidResultsNum >0) && (totalPages > 1) && ( 0 < page && page <= totalPages )) "
class="uk-clearfix">
<div class="uk-grid">
<!--<div *ngIf="orcidResultsNum>0" class="uk-width-1-2">
<span class="portal-color">{{orcidResultsNum|number}}</span> research outcomes, page <span
class="portal-color">{{orcidPage | number}}</span> of <span
class="portal-color">{{countTotalPages(orcidResultsNum)|number}}</span>
</div>-->
<div class="uk-width-1-1@s uk-width-1-2@m uk-text-uppercase"
*ngIf="orcidResultsNum > 0">
{{orcidResultsNum|number}}
<span class="uk-text-muted uk-text-uppercase"> research outcomes, page </span>
{{orcidPage | number}}
<span class="uk-text-muted uk-text-uppercase"> of </span>
{{(countTotalPages(orcidResultsNum)|number)}}
</div>
<div class="uk-width-1-2 uk-padding-remove-left">
<paging-no-load class="uk-float-right" [currentPage]="orcidPage" [totalResults]="orcidResultsNum"
[term]="keyword" [size]="size"
(pageChange)="orcidPageChange($event)"></paging-no-load>
</div>
</div>
</div>
<div *ngIf="orcidResultsNum >= 0" class="panel-body">
<span><span class="uk-text-bold">Showing results for</span>
<a target="_blank" href="http://orcid.org/{{authorId}}"> <span
@ -168,18 +284,9 @@
[selectedResults]=selectedResults [basketLimit]="basketLimit"></claim-results>
<div *ngIf="orcidResultsNum == 0" class="uk-alert uk-alert-primary uk-margin-top"> No results found</div>
</div>
<div *ngIf=" ((orcidResultsNum >0) && (totalPages > 1) && ( 0 < page && page <= totalPages )) "
class="uk uk-flex uk-flex-center">
<paging-no-load [currentPage]="orcidPage" [totalResults]="orcidResultsNum"
[term]="keyword" [size]="size"
(pageChange)="orcidPageChange($event)"></paging-no-load>
</div>
</div>
<div *ngIf="orcidStatus == errorCodes.LOADING" class="uk-animation-fade uk-margin-top uk-width-1-1" role="alert">
<loading></loading></div>
<span class="loading-gif uk-align-center"></span></div>
</div>
</div>
<div *ngIf="activeTab == 'datacite'" id="datacite" class="uk-animation-fade">
@ -190,18 +297,35 @@
role="alert">Service not available
</div>
<div class="uk-margin-top">
<div *ngIf="dataciteResultsNum != null && dataciteResultsNum > 0" class="uk-clearfix ">
<div class="uk-grid">
<!-- <div *ngIf="dataciteResultsNum>0" class="uk-width-1-2">
<span class="portal-color">{{dataciteResultsNum|number}}</span> research outcomes, page <span
class="portal-color">{{datacitePage | number}}</span> of <span
class="portal-color">{{countTotalPages(dataciteResultsNum)|number}}</span>
</div>-->
<div class="uk-width-1-1@s uk-width-1-2@m uk-text-uppercase"
*ngIf="dataciteResultsNum > 0">
{{dataciteResultsNum|number}}
<span class="uk-text-muted uk-text-uppercase"> research outcomes, page </span>
{{datacitePage | number}}
<span class="uk-text-muted uk-text-uppercase"> of </span>
{{(countTotalPages(dataciteResultsNum)|number)}}
</div>
<div class="uk-width-1-2 uk-padding-remove-left">
<paging-no-load class="uk-float-right" [currentPage]="datacitePage" [totalResults]="dataciteResultsNum"
[term]="keyword"
[size]="size" (pageChange)="datacitePageChange($event)"></paging-no-load>
</div>
</div>
</div>
<div *ngIf="dataciteStatus == errorCodes.LOADING" class="uk-animation-fade uk-margin-top uk-width-1-1"
role="alert"><loading></loading></div>
role="alert"><span class="loading-gif uk-align-center"></span></div>
<div>
<claim-results [localStoragePrefix]=localStoragePrefix *ngIf="dataciteResults.length > 0 "
[results]=dataciteResults [selectedResults]=selectedResults [basketLimit]="basketLimit"></claim-results>
</div>
<div *ngIf="dataciteResultsNum != null && dataciteResultsNum > 0" class="uk uk-flex uk-flex-center ">
<paging-no-load [currentPage]="datacitePage" [totalResults]="dataciteResultsNum"
[term]="keyword"
[size]="size" (pageChange)="datacitePageChange($event)"></paging-no-load>
</div>
</div>
</div>

View File

@ -11,7 +11,7 @@ import {Filter, Value} from "../../searchPages/searchUtils/searchHelperClasses.c
import {forkJoin, Observable, Subscriber} from 'rxjs';
import {NewSearchPageComponent} from "../../searchPages/searchUtils/newSearchPage.component";
import {RangeFilter} from "../../utils/rangeFilter/rangeFilterHelperClasses.class";
import {OpenaireEntities, SearchFields} from "../../utils/properties/searchFields";
import {SearchFields} from "../../utils/properties/searchFields";
@Component({
selector: 'claim-result-search-form',
templateUrl: 'claimResultSearchForm.component.html',
@ -23,15 +23,13 @@ export class ClaimResultSearchFormComponent {
source: string = "datacite";
type: string = "dataset";
showSearchResults: boolean = false;
@Input() public centerAlign: boolean = false;
@Input() public select: boolean = true;
@Input() public keyword: string = '';
@Input() public selectedResults: ClaimEntity[];
@Input() public properties: EnvProperties;
@Input() localStoragePrefix: string = "";
@Input() basketLimit;
@Input() showOptions;
openaireEntities = OpenaireEntities;
public errorCodes: ErrorCodes = new ErrorCodes();
dataciteResults: ClaimEntity[] = [];
@ -865,7 +863,7 @@ export class ClaimResultSearchFormComponent {
}
}
filter.countAllValues = filter.values.length;
}
return filters;
}

View File

@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../../openaireLibrary/shared/shared.module';
import { SharedModule } from '../../shared/shared.module';
import { CommonModule } from '@angular/common';
import { MatSelectModule } from "@angular/material/select";
import {ClaimResultSearchFormComponent} from './claimResultSearchForm.component';
@ -17,16 +17,10 @@ import {HelperModule} from '../../utils/helper/helper.module';
import {SearchFilterModule} from '../../searchPages/searchUtils/searchFilter.module';
import {QuickSelectionsModule} from "../../searchPages/searchUtils/quick-selections.module";
import {RangeFilterModule} from "../../utils/rangeFilter/rangeFilter.module";
import {ClaimProjectsSearchFormModule} from "./claimProjectSearchForm.module";
import {AdvancedSearchInputModule} from "../../sharedComponents/advanced-search-input/advanced-search-input.module";
import {InputModule} from "../../sharedComponents/input/input.module";
import {SearchInputModule} from "../../sharedComponents/search-input/search-input.module";
import {DropdownFilterModule} from "../../utils/dropdown-filter/dropdown-filter.module";
import {LoadingModule} from "../../utils/loading/loading.module";
@NgModule({
imports: [SharedModule, CommonModule, SearchResearchResultsServiceModule, PagingModule, SearchCrossrefServiceModule,
SearchDataciteServiceModule, HelperModule, SearchFilterModule, ClaimResultsModule, MatSelectModule, QuickSelectionsModule, RangeFilterModule, ClaimProjectsSearchFormModule, AdvancedSearchInputModule, InputModule, SearchInputModule, DropdownFilterModule, LoadingModule],
SearchDataciteServiceModule, HelperModule, SearchFilterModule, ClaimResultsModule, MatSelectModule, QuickSelectionsModule, RangeFilterModule],
providers:[
SearchOrcidService
],

View File

@ -6,69 +6,78 @@ declare var UIkit: any;
@Component({
selector: 'claim-results',
template: `
<div *ngIf="results.length > 0 " class="uk-margin-top">
<div *ngFor="let entity of results" class="uk-card">
<div class="uk-padding-small">
<ul *ngIf="results.length > 0 " class="uk-list uk-list-divider">
<li *ngFor=" let entity of results " [class]="(isSelected(entity))?'uk-block-muted':''">
<div>
<div class="uk-text-muted">
{{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}}
</div>
<div class="uk-grid">
<div class="uk-width-expand uk-margin-right">
<claim-title [entity]="entity" [showIcon]="false"></claim-title>
<div class="uk-width-expand">
<claim-title [entity]="entity"></claim-title>
<claim-result-metadata [entity]="entity"></claim-result-metadata>
<claim-project-metadata [entity]="entity"></claim-project-metadata>
</div>
<div class="uk-margin-auto-vertical uk-padding-remove-left uk-margin-small-left uk-margin-small-right" [title]="(this.selectedResults.length>=basketLimit)?'Basket reached the size limit':''">
<button class="linking-add-button uk-icon-button-small" [class.uk-disabled]="(this.selectedResults.length>=basketLimit)" *ngIf="!isSelected(entity)"
<div class="uk-margin-auto-vertical uk-padding-remove-left uk-margin-small-left" [title]="(this.selectedResults.length>=basketLimit)?'Basket reached the size limit':''">
<a [class]="(this.selectedResults.length>=basketLimit)?'uk-icon-button uk-disabled':'uk-icon-button'" *ngIf="!isSelected(entity)"
(click)="add(entity)">
<icon name="add" [flex]="true"></icon>
</button>
<button *ngIf="isSelected(entity)" class="linking-selected-button uk-icon-button-small" (click)="remove(entity)">
<icon name="check" [flex]="true"></icon>
</button>
<span class="uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="plus"
ratio="1"><rect x="9" y="1" width="1" height="17"></rect><rect x="1" y="9" width="17"
height="1"></rect></svg>
</span>
</a>
<span *ngIf="isSelected(entity)" class="uk-icon-button portal-icon-button">
<span class="uk-icon" >
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="check" ratio="1"><polyline fill="none" stroke="#000" stroke-width="1.1" points="4,10 8,15 17,4"></polyline></svg>
</span>
</span>
</div>
</div>
</div>
</div>
</div>
`
</li>
</ul>`,
})
export class ClaimResultsComponent {
@Input() results: ClaimEntity[];
@Input() selectedResults: ClaimEntity[];
@Input() localStoragePrefix: string = "";
@Input() basketLimit;
private isSelected(result: ClaimEntity) {
ngOnInit() {
}
public isSelected(item: ClaimEntity) {
return !!this.selectedResults.find(result => item.id === result.id);
let found: boolean = false;
const id = result.id;
for (let _i = 0; _i < this.selectedResults.length; _i++) {
let item = this.selectedResults[_i];
if (item.id && item.id == id) {
found = true;
break;
}
}
return found;
// indexOf doesn't work when results came from
// return this.selectedResults.indexOf(entity)!=-1;
}
add(item: ClaimEntity) {
// if (this.selectedResults.length > this.basketLimit) {
// UIkit.notification({
// message: 'Your basket exceeds the number of allowed results (150)',
// status: 'warning',
// timeout: 1500,
// pos: 'top-center'
// });
// return;
// }
let found: boolean = this.isSelected(item);
if (!found) {
this.selectedResults.push(item);
localStorage.setItem(this.localStoragePrefix, JSON.stringify(this.selectedResults));
UIkit.notification(item.type + ' added in your basket!', {
status: 'success',
timeout: 4000,
pos: 'bottom-right'
});
}
}
remove(item: ClaimEntity) {
const index: number = this.selectedResults.findIndex(result => item.id === result.id);
if (index > -1) {
this.selectedResults.splice(index, 1);
if (this.selectedResults != null) {
localStorage.setItem(this.localStoragePrefix, JSON.stringify(this.selectedResults));
}
UIkit.notification(item.type + ' removed from your basket!', {
status: 'warning',
timeout: 4000,
pos: 'bottom-right'
});
}
}
}

View File

@ -1,17 +1,16 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../../openaireLibrary/shared/shared.module';
import { SharedModule } from '../../shared/shared.module';
import { CommonModule } from '@angular/common';
import {ClaimResultsComponent} from './claimResults.component';
import {ClaimEntitiesMetadataModule} from "../linking/selected/ClaimEntitiesMetadata.module";
import {IconsModule} from "../../utils/icons/icons.module";
@NgModule({
imports: [
SharedModule, CommonModule, ClaimEntitiesMetadataModule, IconsModule
],
imports: [
SharedModule, CommonModule, ClaimEntitiesMetadataModule
],
providers:[
],
declarations: [

View File

@ -1,23 +0,0 @@
export class ClaimsProperties{
ALLOW_ORGANIZATION_LINKING:boolean = false;
SELECT_ENTITIES = {
projects:"Funding"
}
INLINE_ENTITY = {
show: true,
guideText : null
}
BASKET ={
source_title: "Source",
target_title: "Link source to"
}
METADATA_PREVIEW ={
source_title: "Source",
target_title: "Link to",
edit_source_title: "Edit",
edit_target_title: "Edit",
edit_target_icon: "edit"
}
}

View File

@ -1,142 +1,170 @@
<schema2jsonld *ngIf="url" [URL]="url" [name]="pageTitle" type="other"></schema2jsonld>
<div class="uk-grid">
<div class="uk-width-expand uk-position-relative uk-margin-small-top">
<div class="uk-width-1-1">
</div>
<div class="uk-grid helper-grid">
<div class="uk-width-expand ">
<div
class="uk-card-body uk-padding-remove-bottom uk-padding-remove-top " [class.paging-hr]="
!pageLoading && claims && claims.length > 0">
<helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0"
[texts]="pageContents['top']"></helper>
<div *ngIf="filterForm" [id]="actions?'page_content_actions':null" [class.uk-blur-background]="actions" [attr.uk-sticky]="(actions)?'media: @m':null" [attr.offset]="offset">
<div [class.uk-padding-small]="actions" class="uk-padding-remove-vertical">
<div class="uk-flex uk-flex-right@m uk-flex-center uk-flex-wrap uk-flex-middle">
<div search-input [disabled]="loading" [searchControl]="filterForm.controls.keyword" searchInputClass="outer"
placeholder="Search links" class="uk-width-1-3@xl uk-width-2-5@l uk-width-1-2@m uk-width-1-1"
(searchEmitter)="changeKeyword()" [expandable]="true"></div>
<form class="">
<div 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 #searchInputComponent search-input [control]="filterForm.controls.keyword" [showSearch]="false" placeholder="Search links"
[selected]="inputkeyword" (closeEmitter)="onSearchClose()" (resetEmitter)="resetInput()"
[bordered]="true" colorClass="uk-text-secondary"></div>
</div>
<div class=" uk-grid uk-flex-middle">
<div class="">Filter by: </div>
<div class="uk-width-medium uk-padding-remove uk-margin-small-left" dashboard-input
[formInput]="filterForm.get('entities')"
placeholder="Search by entities"
type="chips" [options]="allOptions" chipLabel="label">
</div>
<div class="">Sort by: </div>
<div class="uk-width-medium uk-padding-remove uk-margin-small-left" dashboard-input
[formInput]="filterForm.get('sort')"
type="select"
[options]="sortOptions">
</div>
</div>
</form>
<div *ngIf="!(pageLoading || showErrorMessage || showForbiddenMessage || userValidMessage.length > 0 || (claims &&
claims.length
==0))"
class="searchPaging uk-panel uk-margin-top "
data-uk-grid-margin="">
<div class="uk-grid uk-flex-middle">
<div class="uk-width-1-2">
<div *ngIf="enableDelete && claims && claims.length > 0">
<span class="uk-margin-small-top">
<input id="checkAll" type="checkbox" (click)="selectAll($event)"
[ngModel]="selected.length==claims.length"/>
</span>
<a [class]=" ' grey-portal-link uk-margin-medium-left '+(selected.length > 0?'':'uk-disabled')"
(click)="confirmOpen()">
<span class="uk-icon "><svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
icon="trash" ratio="1"><polyline fill="none" stroke="#000"
points="6.5 3 6.5 1.5 13.5 1.5 13.5 3"></polyline><polyline
fill="none" stroke="#000" points="4.5 4 4.5 18.5 15.5 18.5 15.5 4"></polyline><rect x="8" y="7"
width="1"
height="9"></rect><rect
x="11" y="7" width="1" height="9"></rect><rect x="2" y="3" width="16" height="1"></rect></svg></span>
Delete <span
*ngIf="selected.length > 0 && selected.length < resultsNum">{{selected.length | number}}</span><span
*ngIf="selected.length == resultsNum"> all </span> links
</a>
</div>
</div>
<div *ngIf="resultsNum" class="uk-width-1-2 uk-grid uk-flex-right uk-flex-middle ">
<div class="uk-text-muted uk-text-uppercase">
<span class="uk-text-bold">{{resultsNum|number}}</span> links, page <span
class="uk-text-bold">{{page | number}}</span> of <span
class="uk-text-bold">{{totalPages(resultsNum)|number}}</span>
</div>
<paging-no-load [currentPage]="page" [totalResults]="resultsNum" [size]="size"
[loading]="pageLoading"
(pageChange)="pageChange($event)" class="uk-float-right"></paging-no-load>
</div>
</div>
</div>
</div>
<loading *ngIf="pageLoading" class="uk-padding"></loading>
<div *ngIf="!pageLoading" >
<div *ngIf="showErrorMessage " class="uk-alert uk-alert-danger ">
An Error occured.
</div>
<div *ngIf="showForbiddenMessage " class="uk-alert uk-alert-danger ">
You are not authorized to view the results.
</div>
<div *ngIf=" userValidMessage.length > 0 " class="uk-alert uk-alert-danger ">
User session is not valid. Please login again.
</div>
<div *ngIf=" claims && claims.length == 0" class="uk-margin-top">
<div class="uk-alert uk-alert-primary ">No entries found.</div>
</div>
<div class="uk-margin-small-top">
<div *ngFor="let claim of claims "
class="uk-card uk-card-default uk-card-body uk-margin-bottom ng-star-inserted">
<div class="uk-grid">
<div *ngIf="enableDelete">
<input [id]="claim.id" type="checkbox" (click)="select(claim,$event)"
[ngModel]="isSelected(claim.id)"/>
</div>
<div class="uk-width-expand">
<div class="uk-margin-bottom">
<claim-entity [entity]="claim.target" [type]="claim.targetType" [properties]=properties
[externalPortalUrl]=externalPortalUrl [source]="true"></claim-entity>
</div>
<div class="uk-margin-small-bottom">
<span *ngIf="isClaimAvailable(claim) else notAvailable" class="uk-label uk-label-success"
[attr.uk-tooltip]="'title:<div class=\'uk-margin uk-padding-small\'>The link information is available in the portal and the APIs.</div>'"
>available
</span>
<ng-template #notAvailable><span class="uk-label uk-label-danger"
[attr.uk-tooltip]="'title:<div class=\'uk-margin uk-padding-small\'>The link information will be added in the portal and the APIs in the next content provision workflow.</div>'"
>pending</span></ng-template>
</div>
<div class="uk-margin-small-bottom"><span *ngIf="showUserEmail" class="uk-margin-right"><span class="title">Claimed by:</span>
{{claim.userMail}}</span>
<span
class="title">Claimed date:</span> {{claim.date}}</div>
<div class="uk-margin-small-bottom uk-margin-top">
<!-- <span class="title">Link to:</span> -->
<claim-entity [entity]="claim.source" [type]="claim.sourceType" [source]="false" [properties]=properties
[externalPortalUrl]=externalPortalUrl></claim-entity>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="!( showErrorMessage || showForbiddenMessage || userValidMessage.length > 0 || (claims
&& claims.length
==0))" class="paging-hr uk-margin-top">
<div class="uk-grid ">
<div *ngIf="resultsNum>0" class="uk-width-1-2 uk-text-muted uk-text-uppercase">
<span class="uk-text-bold">{{resultsNum|number}}</span> links, page <span
class="uk-text-bold">{{page | number}}</span> of <span
class="uk-text-bold">{{totalPages(resultsNum)|number}}</span>
</div>
<div *ngIf="resultsNum" class="uk-width-1-2 ">
<paging-no-load [currentPage]="page" [totalResults]="resultsNum" [size]="size"
(pageChange)="pageChange($event)" class="uk-float-right"></paging-no-load>
</div>
</div>
</div>
<div [class.uk-padding]="actions" class="uk-padding-remove-vertical">
<div class="uk-margin-small-top">
<results-and-pages [type]="resultsNum !== 1?'Links':'Link'" [page]="page" [pageSize]="size" [hasSearch]="true" [searchTerm]="keyword"
[totalResults]="resultsNum" customClasses="uk-margin-remove"></results-and-pages>
</div>
<div class="uk-grid uk-flex-middle uk-margin-small-top" uk-grid>
<div *ngIf="fetchBy != 'User' && properties.environment == 'development'" >
<input [(ngModel)]="mine" [checked]="mine" (ngModelChange)="goTo(1)" type="checkbox" class="uk-checkbox"> Mine
</div>
<div>
<dropdown-filter #dropdownFilter dropdownClass="uk-width-medium uk-padding-small"
name="Type of Entity" [disabled]="loading" [count]="entities.length">
<h6 class="uk-margin-remove-bottom" title="Type of Entity">Type of Entity</h6>
<ul class="uk-list uk-margin-remove-bottom">
<li *ngFor="let option of allOptions">
<a class="uk-link-text">
<label (click)="select(option.value, $event, dropdownFilter)" class="uk-flex uk-flex-middle">
<input class="uk-checkbox"
type="checkbox" [checked]="isSelected(option.value)">
<span class="uk-margin-small-left">{{option.label}}</span>
</label>
</a>
</li>
</ul>
</dropdown-filter>
</div>
<div>
<div input inputClass="flat x-small" placeholder="Sort by"
[formInput]="filterForm.get('sort')" class="uk-width-small"
type="select" [options]="sortOptions">
</div>
</div>
<div class="uk-width-expand@l uk-width-1-1 uk-flex uk-flex-right@m uk-flex-center">
<paging-no-load [currentPage]="page" [totalResults]="resultsNum" [size]="size"
[loading]="false" (pageChange)="pageChange($event)"></paging-no-load>
</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="claims && claims.length == 0" class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div>No links found</div>
</div>
<ng-container *ngIf="claims && claims.length > 0">
<div class="uk-flex uk-flex-middle uk-margin-top uk-margin-small-bottom uk-padding-small uk-padding-remove-horizontal">
<div class="uk-width-xsmall uk-flex uk-flex-center uk-flex-middle">
<label>
<input id="checkAll" type="checkbox" (click)="selectAll($event)" class="uk-checkbox" title="Select All"
[ngModel]="selected.length == claims.length"/>
</label>
</div>
<button class="uk-button uk-button-link" [class.uk-disabled]="selected.length == 0" [disabled]="selected.length == 0"
(click)="deleteOpen()">
<span>Delete ({{selected.length}})</span>
</button>
</div>
<ul class="uk-margin-small-top uk-list uk-list-striped">
<li *ngFor="let claim of claims; let i=index" class="uk-flex uk-flex-middle uk-padding-small uk-padding-remove-horizontal">
<div class="uk-width-xsmall uk-flex uk-flex-center uk-flex-middle">
<input type="checkbox" class="uk-checkbox"
[id]="claim.id" (click)="selectClaim(claim, $event)" [ngModel]="isSelectedClaim(claim.id)">
</div>
<div class="uk-width-expand">
<div class="uk-grid uk-grid-small uk-flex-middle" uk-grid>
<div class="uk-width-expand">
<div class="uk-margin-small-bottom">
<claim-entity [entity]="claim.target" [type]="claim.targetType" [properties]=properties
[externalPortalUrl]=externalPortalUrl [source]="true" [linkAvailable]="isClaimAvailable(claim)"></claim-entity>
</div>
<div class="uk-margin-small-bottom">
<span *ngIf="isClaimAvailable(claim) else notAvailable" class="uk-label uk-label-small uk-label-success"
[attr.uk-tooltip]="'title: The link information is available in the portal and the APIs.'">available</span>
<ng-template #notAvailable>
<span class="uk-label uk-label-small uk-label-danger"
[attr.uk-tooltip]="'title:The link information will be added in the portal and the APIs in the next content provision workflow.'">pending</span>
</ng-template>
</div>
<div class="uk-text-small">
<div *ngIf="showUserEmail" class="uk-margin-xsmall-bottom">
<span class="uk-text-meta">Claimed by:</span>
<span class="uk-margin-xsmall-left">{{claim.userMail}}</span>
</div>
<div>
<span class="uk-text-meta">Claimed date:</span>
<span class="uk-margin-xsmall-left">{{claim.date}}</span>
</div>
</div>
</div>
<div class="uk-visible@m">
<div class="claim-divider">
<icon class="uk-position-center" name="link" customClass="uk-text-primary" ratio="2" [flex]="true"></icon>
</div>
</div>
<div class="uk-width-1-2@m uk-width-1-1">
<claim-entity [entity]="claim.source" [type]="claim.sourceType" [source]="false" [properties]=properties
[externalPortalUrl]=externalPortalUrl></claim-entity>
</div>
</div>
</div>
<div class="uk-width-xsmall uk-flex uk-flex-center uk-flex-middle">
<button class="uk-button uk-button-link uk-flex uk-flex-middle" (click)="deleteOpen(i)">
<icon name="delete" [flex]="true"></icon>
</button>
</div>
</li>
</ul>
<div class="uk-margin-medium-top uk-flex uk-flex-center uk-flex-right@m">
<paging-no-load *ngIf="resultsNum" [currentPage]="page" [totalResults]="resultsNum" [size]="size"
(pageChange)="pageChange($event)"></paging-no-load>
</div>
</ng-container>
</div>
</div>
</div>
</div>
<helper *ngIf="pageContents && pageContents['right'] && pageContents['right'].length > 0"
[texts]="pageContents['right']" class="uk-width-1-5"></helper>
</div>
<helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0"
[texts]="pageContents['bottom']"></helper>
<modal-alert #deleteModal [overflowBody]="false" (alertOutput)="delete()">
<modal-alert (alertOutput)="confirmClose()">
<h4 class="modal-title uk-text-bold " id="myModalLabel">Are you sure?</h4>
<p>
You are about to delete {{this.selected.length}} link(s) you selected. <br>
<span class="uk-text-bold">
Usually it takes 2-4 weeks for the links to permanently disappear from the Openaire platfrom.
</span>
</p>
<p>Do you want to delete the link(s)?</p>
</modal-alert>
<modal-loading [message]="'Please wait...'"></modal-loading>

View File

@ -1,7 +0,0 @@
@import (reference) "~src/assets/openaire-theme/less/_import-variables";
.claim-divider {
position: relative;
padding: 0 20px;
height: 100%;
}

View File

@ -1,11 +1,14 @@
import {Component, Input, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {Component, Input, ViewChild} from '@angular/core';
import {Location} from '@angular/common';
import {ActivatedRoute, Router} from '@angular/router';
import {Subject, Subscriber} from 'rxjs';
import {debounceTime, distinctUntilChanged} from 'rxjs/operators';
import {ClaimsService} from '../service/claims.service';
import {User} from '../../../login/utils/helper.class';
import {ModalLoading} from '../../../utils/modal/loading.component';
import {AlertModal} from '../../../utils/modal/alert';
import {Session, User} from '../../../login/utils/helper.class';
import {EnvProperties} from '../../../utils/properties/env-properties';
import {LoginErrorCodes} from '../../../login/utils/guardHelper.class';
import {SEOService} from '../../../sharedComponents/SEO/SEO.service';
import {IndexInfoService} from '../../../utils/indexInfo.service';
import {ClaimDBRecord} from '../claimHelper.class';
@ -14,21 +17,21 @@ import {HelperService} from '../../../utils/helper/helper.service';
import {Meta, Title} from '@angular/platform-browser';
import {PiwikService} from '../../../utils/piwik/piwik.service';
import {properties} from '../../../../../environments/environment';
import {FormBuilder, FormGroup} from '@angular/forms';
import {FormArray, FormBuilder, FormGroup} from '@angular/forms';
import {Option} from '../../../sharedComponents/input/input.component';
import {OpenaireEntities} from "../../../utils/properties/searchFields";
import {HelperFunctions} from "../../../utils/HelperFunctions.class";
import {NotificationHandler} from "../../../utils/notification-handler";
import {DropdownFilterComponent} from "../../../utils/dropdown-filter/dropdown-filter.component";
import {SearchInputComponent} from '../../../sharedComponents/search-input/search-input.component';
declare var UIkit;
@Component({
selector: 'displayClaims',
templateUrl: 'displayClaims.component.html',
styleUrls: ['displayClaims.component.less']
// providers: [ClaimsService]
})
export class DisplayClaimsComponent implements OnInit, OnDestroy {
export class DisplayClaimsComponent {
@Input() piwikSiteId = null;
@Input() pageTitle: string = "";
properties: EnvProperties = properties;
properties: EnvProperties;
public searchTermStream = new Subject<string>();
subscriptions: any = [];
public subResults: any;
@ -39,90 +42,93 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
@Input() isAdmin: boolean = false;
page: number = 1;
size: number = 50;
defaultSize:number = 50;
sizes = [10, 20, 30, 50];
keyword: string; // the keyword string to give to the request as parameter
types = ["All", "Project", "Context", "Result", "User", "Organization"];
loading: boolean = false;
inputkeyword: string; // the string written in the input field (keyword=inputkeyword when its length is bigger than 3 and the user stops typing)
@ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent;
types = ["All", "Project", "Context", "Result", "User"];
pageLoading:boolean = false;
@Input() fetchBy: string;
@Input() fetchId: string;
@Input() user: User;
resultsNum: number = 0;
resultsNum: number;
claims: ClaimDBRecord[];
@Input() externalPortalUrl: string = null;
@Input() claimsInfoURL: string;// ="https://www.openaire.eu/linking";
lastIndexDate = null;
@ViewChild(ModalLoading) loading: ModalLoading;
public filterForm: FormGroup;
public entities: string[] = [];
selected = [];
mine = false;
allOptions: Option[] = [
{label: OpenaireEntities.PUBLICATIONS, value: "publication"},
{label: OpenaireEntities.DATASETS, value: "dataset"},
{label: OpenaireEntities.SOFTWARE, value: "software"},
{label: OpenaireEntities.OTHER, value: "other"},
{label: OpenaireEntities.PROJECTS, value: "project"},
{label: OpenaireEntities.COMMUNITIES, value: "context"}];
public entitiesCtrl: FormArray;
allOptions: Option[] = [{label: "Projects", value: {id:"project", label: "Projects"}},{label: "Publications", value:{id:"publication", label: "Publications"}},{label: "Research data", value: {id:"dataset", label: "Research data"}},
{label: "Software", value: {id:"software", label: "Software"}},{label: "Other reserch products", value: {id:"other", label: "Other reserch products"}},{label: "Communities", value: {id:"context", label: "Communities"}}];
sortOptions: Option[] = [
{label: "Date (recent) ", value: {sort: "date", descending: true}},
{label: "Date (oldest) ", value: {sort: "date", descending: false}},
{label: "Title (desc) ", value: {sort: "target", descending: true}},
{label: "Title (asc) ", value: {sort: "target", descending: false}},
{label:"Date (recent) ", value:{ sort: "date", descending: true }}, {label:"Date (oldest) ", value:{ sort: "date",descending:false }},
// {label:"User (desc) ", value:{ sort: "user",descending: true }}, {label:"User (asc) ", value:{ sort: "user",descending:false }},
// {label:"Title (desc) ", value:{ sort: "source",descending: true }}, {label:"Title (asc) ", value:{ sort: "source",descending:false }},
{label:"Title (desc) ", value:{ sort: "target",descending: true }}, {label:"Title (asc) ", value: { sort: "target",descending:false }},
];
entityTypes: string[] = [];
index: number;
// descending = true;
// sortby = "date";
selected = [];
// deleteMessage: string = "";
showErrorMessage: boolean = false;
showForbiddenMessage: boolean = false;
userValidMessage: string = "";
//params for pagingFormatter to use when navigate to page
params;
@ViewChild("deleteModal") deleteModal;
@ViewChild(AlertModal) alert;
claimsDeleted: number = 0;
@Input() communityId: string = null;
url = null;
public pageContents = null;
/* Sticky actions */
@Input()
public actions: boolean = false;
public offset: number;
constructor(private _claimService: ClaimsService, private route: ActivatedRoute, private _router: Router, private location: Location,
private _meta: Meta, private _title: Title, private _piwikService: PiwikService,
private seoService: SEOService, private indexInfoService: IndexInfoService, private helper: HelperService, private _fb: FormBuilder) {
}
ngOnInit() {
if (typeof document !== "undefined" && this.actions) {
this.offset = Number.parseInt(getComputedStyle(document.documentElement).getPropertyValue('--header-height'));
}
this.entities = [];
this.entitiesCtrl = this._fb.array([]);
this.filterForm = this._fb.group({
keyword: [''],
entities: this._fb.control(this.entities),
entities: this.entitiesCtrl,
sort: this._fb.control(this.sortOptions[0].value)
});
this.properties = properties;
this.url = properties.domain + properties.baseLink + this._router.url;
if (!this.myClaims) {
this.sortOptions.push({label: "User (desc) ", value: {sort: "user", descending: true}});
this.sortOptions.push({label: "User (asc) ", value: {sort: "user", descending: false}})
if(!this.myClaims){
this.sortOptions.push({label:"User (desc) ", value:{ sort: "user",descending: true }});
this.sortOptions.push( {label:"User (asc) ", value:{ sort: "user",descending:false }})
}
var description = "Openaire, linking, claim, publication, research data, software, other research product, project, community";
this.updateTitle(this.pageTitle);
this.updateDescription(description);
this.updateUrl(this.url);
this.subscriptions.push(this._piwikService.trackView(this.properties, this.pageTitle).subscribe());
if(properties.adminToolsPortalType !== "explore") {
this.subscriptions.push(this.helper.getPageHelpContents(this.properties, this.communityId, this._router.url).subscribe(contents => {
this.pageContents = contents;
}));
if (this.properties.enablePiwikTrack && (typeof document !== 'undefined')) {
this.subscriptions.push(this._piwikService.trackView(this.properties, this.pageTitle, this.piwikSiteId).subscribe());
}
this.subscriptions.push(this.helper.getPageHelpContents(this.properties, this.communityId, this._router.url).subscribe(contents => {
this.pageContents = contents;
}));
this.subscriptions.push(this.indexInfoService.getLastIndexDate(this.properties).subscribe(res => {
this.lastIndexDate = res;
}));
this.subscriptions.push(this.route.queryParams.subscribe(params => {
this.seoService.createLinkForCanonicalURL(this.url, false);
if (this.myClaims) {
this.fetchBy = "User";
this.fetchId = this.user.email;
@ -132,14 +138,18 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
this.fetchId = (this.fetchId) ? this.fetchId : params['fetchId'];
this.fetchId = this.fetchId ? this.fetchId : '';
}
let page = (params['page'] === undefined) ? 1 : +params['page'];
this.mine = (params['mine'] == 'true' ? true:false);
let size = (params['size'] === undefined) ? this.defaultSize : +params['size'];
this.keyword = (params['keyword'] ? params['keyword'] : "");
this.filterForm.get('keyword').setValue(this.keyword);
this.inputkeyword = this.keyword;
this.page = (page <= 0) ? 1 : page;
this.size = (size <= 0) ? this.defaultSize : size;
this.entityTypes = [];//(params['types']?params['types']:[]);
this.setTypes(params['types']); // check the appropriate checkboxes
this.setSortBy(params['sort']);
// this.setTypes(params['types']); // check the appropriate checkboxes
this.setSortby(params['sort']);
this.getClaims();
this.subscriptions.push(this.searchTermStream
.pipe(debounceTime(300), distinctUntilChanged())
@ -151,241 +161,185 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
this.subscriptions.push(this.filterForm.get('entities').valueChanges.subscribe(value => {
this.goTo();
}));
this.subscriptions.push(this.filterForm.get('keyword').valueChanges.subscribe(value => {
this.changekeyword();
}));
this.subscriptions.push(this.filterForm.get('sort').valueChanges.subscribe(value => {
this.goTo();
}));
}));
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
}
});
if (this.subResults) {
if(this.subResults){
this.subResults.unsubscribe();
}
}
getClaims() {
let types = '';
for (let type of this.entities) {
types += (types.length > 0 ? '&' : '') + "types=" + type;
}
this.loading = true;
if (this.subResults) {
this.subResults.unsubscribe();
}
if (this.fetchBy == "Project") {
this.subResults = this._claimService.getClaimsByProject(this.size, this.page, this.fetchId, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL).subscribe(
data => {
this.manageAPIData(data);
this.loading = false;
},
err => {
this.handleErrors(err, "Error getting claims for project with id: " + this.fetchId);
if (!Session.isLoggedIn()) {
this.userValidMessage = "User session has expired. Please login again.";
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
);
} else if (this.fetchBy == "Organization") {
this.subResults = this._claimService.getClaimsByOrganization(this.size, this.page, this.fetchId, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL, this.mine).subscribe(
data => {
this.manageAPIData(data);
this.loading = false;
},
err => {
this.handleErrors(err, "Error getting claims for project with id: " + this.fetchId);
}
);
} else if (this.fetchBy == "User") {
this.subResults = this._claimService.getClaimsByUser(this.size, this.page, this.fetchId, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL).subscribe(
data => {
this.manageAPIData(data);
this.loading = false;
},
err => {
this.handleErrors(err, "Error getting claims for user with id: " + this.fetchId);
this.loading = false;
}
);
} else if (this.fetchBy == "Result") {
this.subResults = this._claimService.getClaimsByResult(this.size, this.page, this.fetchId, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL).subscribe(
data => {
this.manageAPIData(data);
this.loading = false;
},
err => {
this.handleErrors(err, "Error getting claims for entity with id: " + this.fetchId);
this.loading = false;
}
);
} else if (this.fetchBy == "Context") {
this.subResults = this._claimService.getClaimsBycontext(this.size, this.page, this.fetchId, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL, this.mine).subscribe(
data => {
this.manageAPIData(data);
this.loading = false;
},
err => {
this.handleErrors(err, "Error getting claims for context with id: " + this.fetchId);
this.loading = false;
}
);
});
} else {
this.subResults = this._claimService.getClaims(this.size, this.page, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL, this.mine).subscribe(
data => {
this.manageAPIData(data);
this.loading = false;
},
err => {
this.handleErrors(err, "Error getting claims");
this.loading = false;
}
);
this.selected = [];
let types = '';
this.showErrorMessage = false;
this.showForbiddenMessage = false;
for (let type of this.entitiesCtrl.getRawValue()) {
types += (this.entitiesCtrl.getRawValue().length > 0 ? '&' : '') + "types=" + type.id;
}
this.pageLoading = true;
if(this.subResults){
this.subResults.unsubscribe();
}
if (this.fetchBy == "Project") {
this.subResults = this._claimService.getClaimsByProject(this.size, this.page, this.fetchId, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL).subscribe(
data => {
this.manageAPIData(data);
this.pageLoading = false;
},
err => {
this.handleErrors(err, "Error getting claims for project with id: " + this.fetchId);
}
);
} else if (this.fetchBy == "User") {
this.subResults = this._claimService.getClaimsByUser(this.size, this.page, this.fetchId, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL).subscribe(
data => {
this.manageAPIData(data);
this.pageLoading = false;
},
err => {
this.handleErrors(err, "Error getting claims for user with id: " + this.fetchId);
this.pageLoading = false;
}
);
} else if (this.fetchBy == "Result") {
this.subResults = this._claimService.getClaimsByResult(this.size, this.page, this.fetchId, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL).subscribe(
data => {
this.manageAPIData(data);
this.pageLoading = false;
},
err => {
this.handleErrors(err, "Error getting claims for entity with id: " + this.fetchId);
this.pageLoading = false;
}
);
} else if (this.fetchBy == "Context") {
this.subResults = this._claimService.getClaimsBycontext(this.size, this.page, this.fetchId, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL).subscribe(
data => {
this.manageAPIData(data);
this.pageLoading = false;
},
err => {
this.handleErrors(err, "Error getting claims for context with id: " + this.fetchId);
this.pageLoading = false;
}
);
} else {
this.subResults = this._claimService.getClaims(this.size, this.page, this.keyword, this.filterForm.get("sort").value.sort, this.filterForm.get("sort").value.descending, types, this.properties.claimsAPIURL).subscribe(
data => {
this.manageAPIData(data);
this.pageLoading = false;
},
err => {
this.handleErrors(err, "Error getting claims");
this.pageLoading = false;
}
);
}
}
}
manageAPIData(data) {
this.claims = data.data;
this.resultsNum = +data.total;
this.resultsNum = data.total;
}
handleErrors(err, message) {
NotificationHandler.rise(message, "danger");
console.error("Display Claims (component): " + message + " " + (err && err.error ? err.error : ''));
this.showErrorMessage = true;
console.error("Dispaly Claims (component): " + message +" " + (err && err.error?err.error:''));
try {
let error = err && err.error?err.error:err;
if (error.code && error.code == 403) {
this.showErrorMessage = false;
this.showForbiddenMessage = true;
if(!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
}
}
} catch (e) {
}
}
goTo(page: number = 1) {
this.page = page;
this.location.go(location.pathname, this.getParametersString());
HelperFunctions.scroll();
this.getClaims();
}
getParametersString() {
let params = '';
params += (this.page == 1 ? "" : (params.length > 0 ? '&' : '') + "page=" + this.page);
params += (this.size == 10 ? "" : (params.length > 0 ? '&' : '') + "size=" + this.size);
let types = "";
for (let type of this.entities) {
types += (types.length > 0 ? ',' : '') + type;
for (let type of this.entitiesCtrl.getRawValue()) {
types += (this.entitiesCtrl.getRawValue().length > 0 ? ',' : '') + type.id;
}
params += (this.entities.length > 0) ? (params.length > 0 ? '&' : '') + "types=" + types : "";
params += (this.filterForm.get("sort").value.sort == 'date' && this.filterForm.get("sort").value.descending ? "" : (params.length > 0 ? '&' : '') + "sort=" + this.filterForm.get("sort").value.sort + "-" + this.filterForm.get("sort").value.descending);
params += (this.entitiesCtrl.getRawValue().length > 0) ? (params.length > 0 ? '&' : '') + "types=" + types : "";
if (this.isAdmin) {
params += (this.fetchBy == 'All' ? "" : (params.length > 0 ? '&' : '') + "fetchBy=" + this.fetchBy);
params += (this.fetchId == '' ? "" : (params.length > 0 ? '&' : '') + "fetchId=" + this.fetchId);
}
params += (this.filterForm.get("sort").value.sort == 'date' && this.filterForm.get("sort").value.descending ? "" : (params.length > 0 ? '&' : '') + "sort=" +this.filterForm.get("sort").value.sort + "-" + this.filterForm.get("sort").value.descending);
params += (this.keyword == '' ? "" : (params.length > 0 ? '&' : '') + "keyword=" + this.keyword);
if (this.communityId != null) {
params += "&communityId=" + this.communityId;
}
return params;
}
setSortBy(sortby: string) {
setSortby(sortby: string) {
let sort = "date";
let desc = "desc";
if (sortby && sortby.split("-").length == 2) {
if(sortby && sortby.split("-").length == 2){
sort = sortby.split("-")[0];
desc = sortby.split("-")[1];
}
let option = this.sortOptions.find(option => option.value.sort == sort && ((option.value.descending && desc == "desc") || (!option.value.descending && desc == "asc")));
this.filterForm.get("sort").setValue(option ? option.value : this.sortOptions[0].value);
let option = this.sortOptions.find( option => option.value.sort == sort && ((option.value.descending && desc=="desc") || (!option.value.descending && desc=="asc")));
this.filterForm.get("sort").setValue(option?option.value:this.sortOptions[0].value);
}
setTypes(typesParam: string) {
for (let type of typesParam ? typesParam.split(',') : []) {
this.entities.push(type);
}
}
changeKeyword() {
if (this.filterForm.get("keyword") && (this.filterForm.get("keyword").value?.length >= 3 || this.filterForm.get("keyword").value?.length == 0)) {
changekeyword() {
if (this.filterForm.get("keyword").value.length >= 3 || this.filterForm.get("keyword").value.length == 0) {
this.searchTermStream.next(this.filterForm.get("keyword").value);
}
}
select(value: string, event, dropdownFilter: DropdownFilterComponent) {
if(event.target instanceof HTMLInputElement) {
dropdownFilter.closeDropdown();
if(event.target.checked && !this.entities.find(entity => value === entity)) {
this.entities.push(value);
} else if(!event.target.checked) {
let index = this.entities.indexOf(value);
if(index !== -1) {
this.entities.splice(index, 1);
}
}
this.filterForm.get('entities').setValue(this.entities);
}
}
isSelected(value: string) {
return this.filterForm && this.filterForm.get('entities').value.find(entity => entity === value);
}
deleteOpen(index: number = null) {
this.index = index;
this.deleteModal.alertTitle = 'Delete Confirmation';
this.deleteModal.message = 'Are you sure you want to delete ' + (this.index != null ? '1' : this.selected.length) + ' link(s)?';
this.deleteModal.okButtonText = 'Yes';
this.deleteModal.open();
}
delete() {
let claimsToBeDeleted = ((this.index != null) ? [this.claims[this.index].id] : this.selected.map(claim => claim.id));
// console.log(claimsToBeDeleted);
this.subscriptions.push(this._claimService.deleteBulk(claimsToBeDeleted, this.properties.claimsAPIURL).subscribe(
res => {
if (this.index != null) {
this.claims.splice(this.index, 1);
this.resultsNum = this.resultsNum - 1;
NotificationHandler.rise('Link has been deleted successfully');
} else {
claimsToBeDeleted.forEach(claimId => {
this.claims.splice(this.claims.findIndex((id) => id == claimId), 1);
});
this.resultsNum = this.resultsNum - claimsToBeDeleted.length;
NotificationHandler.rise(claimsToBeDeleted.length + ' links have been deleted successfully');
}
this.selected = [];
let goToPage = this.page;
if (this.totalPages(this.resultsNum) < this.page && this.page > 0) {
goToPage = this.page - 1;
}
this.goTo(goToPage);
}, err => {
this.handleErrors(err, "Error deleting claim with id: " + this.claims[this.index].id);
}
));
}
pageChange($event) {
let page: number = +$event.value;
this.goTo(page);
}
isClaimAvailable(claim: ClaimDBRecord): boolean {
//claim.target.collectedFrom == "infrastruct_::openaire" &&
let lastUpdateDate = new Date((this.lastIndexDate != null) ? this.lastIndexDate : this.properties.lastIndexUpdate);
let lastUpdateDateStr = Dates.getDateToString(lastUpdateDate);
let claimDate = new Date(claim.date);
let claimDateStr = Dates.getDateToString(claimDate);
//TODO remove when organization links are integrated in Graph ------>
if(claim.sourceType == 'organization'){
return false;
}
// remove until here <-------
if (claimDateStr < lastUpdateDateStr) {
return true;
} else {
return claim.target.collectedFrom != "infrastruct_::openaire";
}
}
totalPages(totalResults: number): number {
let totalPages: any = totalResults / (this.size);
if (!(Number.isInteger(totalPages))) {
totalPages = (parseInt(totalPages, 10) + 1);
}
return totalPages;
}
selectClaim(item: any, event) {
select(item: any, event) {
let value = event.currentTarget.checked;
if (value) {
this.selected.push(item);
@ -396,6 +350,8 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
this.selected.splice(_i, 1);
}
}
}
}
@ -412,7 +368,7 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
}
}
isSelectedClaim(id: string) {
isSelected(id: string) {
for (let _i = 0; _i < this.selected.length; _i++) {
let claim = this.selected[_i];
if (claim['id'] == id) {
@ -422,24 +378,159 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
return false;
}
confirmOpen() {
if (this.selected.length <= 0) {
} else {
this.alert.cancelButton = true;
this.alert.okButton = true;
this.alert.alertTitle = "";// "Delete " + this.selected.length + " links(s)";
this.alert.okButtonLeft = false;
// this.alert.message = this.selected.length + " links will be deleted. Do you want to proceed? ";
this.alert.okButtonText = "Delete";
this.alert.cancelButtonText = "Cancel";
this.alert.open();
}
}
confirmClose() {
this.delete();
}
delete() {
this.loading.open();
this.claimsDeleted = 0;
let ids = [];
for (let i = 0; i < this.selected.length; i++) {
let id = this.selected[i].id;
ids.push(id);
}
this.batchDeleteById(ids);
}
batchDeleteById(ids: string[]) {
if (!this.user) {
this.userValidMessage = "User session has expired. Please login again.";
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
//console.warn("Deleting claim with ids:"+ids);
this.subscriptions.push(this._claimService.deleteBulk(ids, this.properties.claimsAPIURL).subscribe(
res => {
//console.info('Delete response'+res.code );
//console.warn("Deleted ids:"+ res.deletedIds);
//console.warn("Not found ids:"+ res.notFoundIds);
//remove this claim from the
let newClaims = this.claims;
for (let id of res.deletedIds) {
for (let _i = 0; _i < this.claims.length; _i++) {
let claim = this.claims[_i];
if (claim['id'] == id) {
newClaims.splice(_i, 1);
}
}
for (let _i = 0; _i < this.selected.length; _i++) {
let claim = this.selected[_i];
if (claim['id'] == id) {
this.selected.splice(_i, 1);
}
}
}
this.claims = newClaims;
this.resultsNum = this.resultsNum - res.deletedIds.length;
this.loading.close();
if (res.deletedIds.length > 0) {
UIkit.notification('<div class = " " >' + res.deletedIds.length + ' link(s) successfully deleted.</div>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
}
if (res.notFoundIds.length > 0) {
UIkit.notification('<div class = " " >' + res.notFoundIds.length + ' link(s) couldn\'t be deleted.</div>', {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
}
let goToPage = this.page;
if (this.totalPages(this.resultsNum) < this.page && this.page > 0) {
goToPage = this.page - 1;
}
this.goTo(goToPage);
}, err => {
//console.log(err);
this.handleErrors(err,"Error deleting claims with ids: " + ids);
this.showErrorMessage = true;
this.loading.close();
}));
}
}
pageChange($event) {
let page: number = +$event.value;
this.goTo(page);
}
isClaimAvailable(claim: ClaimDBRecord): boolean {
//claim.target.collectedFrom == "infrastruct_::openaire" &&
let lastUpdateDate = new Date((this.lastIndexDate != null) ? this.lastIndexDate : this.properties.lastIndexUpdate);
let lastUpdateDateStr = Dates.getDateToString(lastUpdateDate);
let claimDate = new Date(claim.date);
let claimDateStr = Dates.getDateToString(claimDate);
if (claimDateStr < lastUpdateDateStr) {
return true;
} else {
if (claim.target.collectedFrom != "infrastruct_::openaire" && claim.indexed) {
// check if direct index succeded
return true
}
}
return false;
}
totalPages(totalResults: number): number {
let totalPages: any = totalResults / (this.size);
if (!(Number.isInteger(totalPages))) {
totalPages = (parseInt(totalPages, 10) + 1);
}
return totalPages;
}
private updateDescription(description: string) {
this._meta.updateTag({content: description}, "name='description'");
this._meta.updateTag({content: description}, "property='og:description'");
}
private updateTitle(title: string) {
var _prefix = "";
if (!this.communityId) {
_prefix = "OpenAIRE | ";
}
var _title = _prefix + ((title.length > 50) ? title.substring(0, 50) : title);
if (this.myClaims) {
if(this.myClaims) {
this._title.setTitle(_title);
}
this._meta.updateTag({content: _title}, "property='og:title'");
}
private updateUrl(url: string) {
this._meta.updateTag({content: url}, "property='og:url'");
}
public onSearchClose() {
this.inputkeyword = this.filterForm.get('keyword').value;
}
public resetInput() {
this.inputkeyword = null;
this.searchInputComponent.reset()
}
}

View File

@ -17,21 +17,17 @@ import {HelperModule} from '../../../utils/helper/helper.module';
import {Schema2jsonldModule} from '../../../sharedComponents/schema2jsonld/schema2jsonld.module';
import { SEOServiceModule } from '../../../sharedComponents/SEO/SEOService.module';
import {IndexInfoServiceModule} from "../../../utils/indexInfoService.module";
import {PiwikServiceModule} from "../../../utils/piwik/piwikService.module";
import {SearchInputModule} from '../../../sharedComponents/search-input/search-input.module';
import {InputModule} from '../../../sharedComponents/input/input.module';
import {LoadingModule} from '../../../utils/loading/loading.module';
import {NoLoadPaging} from "../../../searchPages/searchUtils/no-load-paging.module";
import {IconsModule} from "../../../utils/icons/icons.module";
import {DropdownFilterModule} from "../../../utils/dropdown-filter/dropdown-filter.module";
import {IconsService} from "../../../utils/icons/icons.service";
import {link} from "../../../utils/icons/icons";
@NgModule({
imports: [
CommonModule, FormsModule, RouterModule, ClaimServiceModule, LoadingModalModule, AlertModalModule,
ClaimEntityFormatterModule, PagingModule, HelperModule, Schema2jsonldModule, SEOServiceModule,
IndexInfoServiceModule, MatSelectModule, SearchInputModule, MatAutocompleteModule, MatChipsModule, MatFormFieldModule, MatSlideToggleModule, InputModule, LoadingModule, NoLoadPaging, IconsModule, DropdownFilterModule
ClaimEntityFormatterModule, PagingModule, HelperModule, Schema2jsonldModule, SEOServiceModule, PiwikServiceModule,
IndexInfoServiceModule, MatSelectModule, SearchInputModule, MatAutocompleteModule, MatChipsModule, MatFormFieldModule, MatSlideToggleModule, InputModule, LoadingModule
],
declarations: [
DisplayClaimsComponent
@ -41,8 +37,4 @@ import {link} from "../../../utils/icons/icons";
DisplayClaimsComponent
]
})
export class DisplayClaimsModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([link])
}
}
export class DisplayClaimsModule { }

View File

@ -1,8 +1,6 @@
import {Component, Input} from '@angular/core';
import {EnvProperties} from '../../../utils/properties/env-properties';
import {ClaimDBContext, ClaimDBOrganization, ClaimDBProject, ClaimDBResult} from "../claimHelper.class";
import {OpenaireEntities} from "../../../utils/properties/searchFields";
import {StringUtils} from "../../../utils/string-utils.class";
import {ClaimDBContext, ClaimDBProject, ClaimDBResult} from "../claimHelper.class";
//Usage Example "<claim-entity [entity]="" [type]="" > </claim-entity>"
@ -11,49 +9,39 @@ import {StringUtils} from "../../../utils/string-utils.class";
selector: 'claim-entity',
template: `
<div *ngIf="type == 'publication' || type == 'dataset' || type == 'software' || type == 'other'"
[attr.uk-tooptip]="getEntityName(type)">
<div *ngIf="source" class="uk-text-small">
{{getEntityName(type)}}
</div>
<div>
<span *ngIf="!source" class="uk-text-meta uk-text-small uk-margin-small-right uk-text-nowrap">Link to:</span>
<publication-title [entity]="entity" param="id"
path="/search/result" [externalPortalUrl]=externalPortalUrl [linkAvailable]="linkAvailable"></publication-title>
</div>
[title]="(type == 'publication'?'Publication':(type == 'dataset'?'research data':(type == 'other'?'other research product':'software')))">
<div *ngIf="source" class="uk-text-muted title">{{type == 'publication'?'publication':(type == 'dataset'?'research data':(type == 'other'?'other':'software'))}}</div>
<span *ngIf="!source" class="title">Link to {{type == 'publication'?'publication':(type == 'dataset'?'research data':(type == 'other'?'other':'software'))}}: </span>
<publication-title [entity]="entity" param="id"
path="/search/result" [externalPortalUrl]=externalPortalUrl></publication-title>
</div>
<div *ngIf="type == 'project'" [attr.uk-tooptip]="getEntityName(type)">
<span class="uk-text-meta uk-text-small uk-margin-small-right uk-text-nowrap">Link to:</span>
<div *ngIf="type == 'project' " title="Project">
<span class="uk-text-muted title">Link to project: </span>
<project-title [project]="entity" [searchLink]=properties.searchLinkToProject
[externalPortalUrl]=externalPortalUrl></project-title>
</div>
<div *ngIf="type == 'organization'" [attr.uk-tooptip]="getEntityName(type)">
<span class="uk-text-meta uk-text-small uk-margin-small-right uk-text-nowrap">Link to:</span>
<organization-title [organization]="entity"></organization-title>
</div>
<div *ngIf="type == 'context'">
<span class="uk-text-meta uk-text-small uk-margin-small-right uk-text-nowrap">Link to:</span>
<h6 class="uk-h6 uk-margin-remove">
<span class="uk-text-truncate" uk-tooltip="Concept">{{entity.title}}</span>
</h6>
<div *ngIf="type == 'context' " title="Concept">
<span class="uk-text-muted title">Link to community: </span> <span class="uk-text-large">{{entity.title}}</span>
</div>
`
})
export class ClaimEntityFormatter {
@Input() entity: ClaimDBResult | ClaimDBContext | ClaimDBProject | ClaimDBOrganization;
@Input() entity: ClaimDBResult | ClaimDBContext | ClaimDBProject;
@Input() type: string;
@Input() properties: EnvProperties;
@Input() externalPortalUrl: string = null;
@Input() source: boolean = true;
@Input() linkAvailable: boolean = true;
public openAIREEntities = OpenaireEntities;
constructor() {
}
public getEntityName(entityType:string) {
return StringUtils.getEntityName(entityType);
ngOnInit() {
}
}

View File

@ -5,19 +5,18 @@ import { RouterModule } from '@angular/router';
import {ProjectTitleFormatter} from './projectTitleFormatter.component';
import {PublicationTitleFormatter} from './publicationTitleFormatter.component';
import {ClaimEntityFormatter} from './claimEntityFormatter.component';
import {OrganizationTitleFormatterComponent} from "./organizationTitleFormatter.component";
@NgModule({
imports: [
CommonModule, RouterModule
],
declarations: [
ProjectTitleFormatter, PublicationTitleFormatter, ClaimEntityFormatter, OrganizationTitleFormatterComponent
ProjectTitleFormatter, PublicationTitleFormatter, ClaimEntityFormatter
],
providers: [ ],
exports: [
ProjectTitleFormatter, PublicationTitleFormatter, ClaimEntityFormatter, OrganizationTitleFormatterComponent
ProjectTitleFormatter, PublicationTitleFormatter, ClaimEntityFormatter
]
})

View File

@ -1,18 +0,0 @@
import {Component, Input} from '@angular/core';
@Component({
selector: 'organization-title',
template: `
<h6 *ngIf="organization" class="uk-margin-remove multi-line-ellipsis lines-2">
<p class="uk-margin-remove">
{{(organization.shortName ? ('[' + organization.shortName + '] ') : '')}}{{organization.name}}
</p>
</h6>
`
})
export class OrganizationTitleFormatterComponent {
@Input() organization: any;
public url: string;
}

View File

@ -7,28 +7,24 @@ import {properties} from "../../../../../environments/environment";
@Component({
selector: 'project-title',
template: `
<ng-container>
<h6 class="uk-margin-remove multi-line-ellipsis lines-2">
<p class="uk-margin-remove">
<a *ngIf="externalPortalUrl" [href]="externalPortalUrl + projectUrl + '?projectId='+project['openaireId']" class="uk-link uk-link-heading" [class.uk-disabled]="project.name == 'unidentified'">
<span *ngIf="project['code'] != 'unidentified'">{{(project['acronym'] ? ('[' + project['acronym'] + '] ') : '')}}{{project['name']}}</span>
<span *ngIf="project['code'] == 'unidentified'">{{project['funderName']}}</span>
</a>
<a *ngIf="!externalPortalUrl" [routerLink]="projectUrl" [queryParams]="routerHelper.createQueryParam('projectId',project['openaireId'])" class="uk-link uk-link-heading" [class.uk-disabled]="project.name == 'unidentified'">
<span *ngIf="project['code'] != 'unidentified'">{{(project['acronym'] ? ('[' + project['acronym'] + '] ') : '')}}{{project['name']}}</span>
<span *ngIf="project['code'] == 'unidentified'">{{project['funderName']}} </span>
</a>
</p>
</h6>
</ng-container>
<span *ngIf="project['funderName'] && project['code'] != 'unidentified'" class="uk-margin-small-top">
<span class="uk-text-meta">Funder: </span>{{project['funderName']}}
<span *ngIf="externalPortalUrl" class="project-title uk-text-large">
<span><a
[href]="externalPortalUrl + projectUrl + '?projectId='+project['openaireId']">{{(project['acronym'] ? ('[' + project['acronym'] + '] ') : '')}}{{project['name']}}</a></span>
</span>
<span *ngIf="!externalPortalUrl" class="project-title uk-text-large">
<span><a [queryParams]="routerHelper.createQueryParam('projectId',project['openaireId'])"
routerLinkActive="router-link-active"
[routerLink]="projectUrl">{{(project['acronym'] ? ('[' + project['acronym'] + '] ') : '')}}{{project['name']}} </a></span>
</span>
<span *ngIf="project['funderName']">
<span class="uk-text-muted title"> Funder: </span>{{project['funderName']}}
</span>
`
})
export class ProjectTitleFormatter {
@Input() project: any;
@Input() project: string[];
@Input() searchLink: string;
@Input() externalPortalUrl: string = null;
public url: string;

View File

@ -6,23 +6,41 @@ import {RouterHelper} from '../../../utils/routerHelper.class';
@Component({
selector: 'publication-title',
template: `
<ng-container *ngIf="entity.openaireId">
<h6 class="uk-margin-remove multi-line-ellipsis lines-2">
<p class="uk-margin-remove">
<a *ngIf="!externalPortalUrl" [queryParams]="routerHelper.createQueryParam(param,entity.openaireId)"
[routerLink]="path" class="uk-link uk-link-heading" [class.uk-disabled]="!linkAvailable">{{entity.title?entity.title:"[No title available]"}}</a>
<a *ngIf="externalPortalUrl" [href]="externalPortalUrl + path+'?'+param+'='+entity.openaireId" class="uk-link uk-link-heading custom-external" [class.uk-disabled]="!linkAvailable">{{entity.title?entity.title:"[No title available]"}}</a>
</p>
</h6>
</ng-container>
<span *ngIf="!externalPortalUrl" class="publication-title uk-text-large">
<span *ngIf="entity.openaireId"><a [queryParams]="routerHelper.createQueryParam(param,entity.openaireId)" routerLinkActive="router-link-active"
[routerLink]="path"> {{entity.title?entity.title:"[No title available]"}}</a></span>
<!--span *ngIf="url" class="uk-margin-small-left" ><a target="_blank" href="{{url}}" >
(<span class="custom-external custom-icon" ></span>link)</a></span-->
</span>
<span *ngIf="externalPortalUrl" class="publication-title uk-text-large">
<span *ngIf="entity.openaireId"><a [href]="externalPortalUrl + path+'?'+param+'='+entity.openaireId"> {{entity.title}}</a></span>
</span>
<!-- <div *ngIf="entity.accessRights || entity.bestLicense">-->
<!-- <span class="uk-text-muted">Access mode </span>{{entity.accessRights}} {{entity.bestLicense}}-->
<!-- <span class=" " *ngIf="entity.accessRights == 'EMBARGO' && entity.embargoEndDate"> {{entity.embargoEndDate}}</span>-->
<!-- </div>-->
`
})
export class PublicationTitleFormatter {
// @Input() title: string;
// @Input() url: string;
// @Input() id: string;
@Input() param: string;
@Input() path: string;
@Input() entity: any;
@Input() externalPortalUrl: string = null;
@Input() linkAvailable: boolean = true;
public routerHelper: RouterHelper = new RouterHelper();
constructor() {
}
ngOnInit() {
}
}

View File

@ -10,45 +10,44 @@ export class ClaimsService {
}
private getClaimRequest(size : number, page : number, url :string, fromCache:boolean):any {
return this.http.get(url, CustomOptions.getAuthOptionsWithBody());
return this.http.get(url, CustomOptions.getAuthOptions());
}
getClaims( size : number, page : number, keyword:string, sortby: string, descending: boolean, types: string, apiUrl:string, mine:boolean):any {
let url = apiUrl +"claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+(types.length>0?"&"+types:types) + (mine?"&mine=true":"") + (mine?"&mine=true":"");
getClaims( size : number, page : number, keyword:string, sortby: string, descending: boolean, types: string, apiUrl:string):any {
let url = apiUrl +"claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+"&"+types;
return this.getClaimRequest(size,page,url,true);
}
getClaimsByUser( size : number, page : number, user:string, keyword:string, sortby: string, descending: boolean, types: string, apiUrl:string):any {
//console.info('ClaimsService: getClaims for user : '+user);
let url = apiUrl +"users/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+(types.length>0?"&"+types:types);
let url = apiUrl +"users/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+"&"+types;
return this.getClaimRequest(size,page,url,false);
}
getClaimsBycontext( size : number, page : number, contextId:string, keyword:string, sortby: string, descending: boolean, types: string , apiUrl:string, mine:boolean):any {
getClaimsBycontext( size : number, page : number, contextId:string, keyword:string, sortby: string, descending: boolean, types: string , apiUrl:string):any {
//console.info('ClaimsService: getClaims for context : '+contextId);
let url = apiUrl +"contexts/"+contextId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+(types.length>0?"&"+types:types);
let url = apiUrl +"contexts/"+contextId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+"&"+types;
return this.getClaimRequest(size,page,url,true);
}
getClaimsByResult( size : number, page : number, resultId:string, keyword:string, sortby: string, descending: boolean, types: string, apiUrl:string ):any {
//console.info('ClaimsService: getClaims for entity : '+resultId);
let url = apiUrl +"results/"+resultId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+(types.length>0?"&"+types:types);
let url = apiUrl +"results/"+resultId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+"&"+types;
return this.getClaimRequest(size,page,url,true);
}
getClaimsByProject( size : number, page : number, projectId:string, keyword:string, sortby: string, descending: boolean, types: string, apiUrl:string ):any {
//console.info('ClaimsService: getClaims for project : '+projectId);
let url = apiUrl +"projects/"+projectId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+(types.length>0?"&"+types:types);
let url = apiUrl +"projects/"+projectId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+"&"+types;
return this.getClaimRequest(size,page,url,true);
}
getClaimsByOrganization( size : number, page : number, organizationId:string, keyword:string, sortby: string, descending: boolean, types: string, apiUrl:string, mine:boolean):any {
let url = apiUrl +"organizations/"+organizationId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+(types.length>0?"&"+types:types) + (mine?"&mine=true":"");
return this.getClaimRequest(size,page,url,true);
}
deleteClaimById(claimId:string , apiUrl:string):any{
//console.warn('Trying to delete claim with id : '+claimId);
let url = apiUrl +"claims/"+claimId;
// let headers = new Headers({ 'Content-Type': 'application/json' });
// let options = new RequestOptions({ headers: headers });
return this.http.delete( url, CustomOptions.getAuthOptionsWithBody())//.map(request => <any> request.json())
// .do(request => console.info("After delete" ))
.pipe(catchError(this.handleError));
}
@ -62,7 +61,10 @@ export class ClaimsService {
}
url= apiUrl +"claims/bulk?"+url;
return this.http.delete( url, CustomOptions.getAuthOptionsWithBody())//.map(request => <any> request.json())
// let headers = new Headers({ 'Content-Type': 'application/json' });
// let options = new RequestOptions({ headers: headers });
return this.http.delete( url, CustomOptions.getAuthOptions())//.map(request => <any> request.json())
// .do(request => console.info("After delete" ))
.pipe(catchError(this.handleError));
}
@ -70,27 +72,40 @@ export class ClaimsService {
// console.warn('Trying toinsert claims : '+claims);
let url = apiUrl +"claims/bulk";
let body = JSON.stringify( claims );
//console.warn('Json body: : '+body);
// let headers = new Headers({ 'Content-Type': 'application/json' });
// let options = new RequestOptions({ headers: headers });
return this.http.post(url, body, CustomOptions.getAuthOptionsWithBody())
//.map(res => res.json())
//.do(request => console.info("Insert Response:"+request.status) )
.pipe(catchError(this.handleError));
}
insertClaim(claim, apiUrl:string):any{
//console.warn('Trying toinsert claim : '+claim);
let url = apiUrl +"claims";
let body = JSON.stringify( claim );
// let headers = new Headers({ 'Content-Type': 'application/json' });
// let options = new RequestOptions({ headers: headers });
return this.http.post(url, body, CustomOptions.getAuthOptionsWithBody())
//.map(res => res.json())
//.do(request => console.info("Insert Response:"+request.status) )
.pipe(catchError(this.handleError));
}
insertDirectRecords(records, apiUrl:string):any{
//console.warn('Trying to feedrecords : '+records);
let url = apiUrl +"feed/bulk";
let body = JSON.stringify( records );
//console.warn('Json body: : '+body);
// let headers = new Headers({ 'Content-Type': 'application/json' });
// let options = new RequestOptions({ headers: headers });
return this.http.post(url, body, CustomOptions.getAuthOptionsWithBody())
//.map(res => res.json())
//.do(request => console.info("Insert Response:"+request) )
.pipe(catchError(this.handleError));
}
getStatus(jobId, apiUrl:string):any{
let url = apiUrl +"jobStatus/" + jobId;
return this.http.get(url,CustomOptions.getAuthOptionsWithBody())
.pipe(catchError(this.handleError));
}
private handleError (error: Response) {
// in a real world app, we may send the error to some remote logging infrastructure
// instead of just logging it to the console
@ -98,4 +113,22 @@ export class ClaimsService {
return observableThrowError(error || 'Server error');
}
// getClaim(id:string, apiUrl:string):any {
// let url = apiUrl+"claims/"+id;
// return new Promise((resolve, reject) => {
// this.http.get(url)
// //.map(res => res.json())
// .subscribe(
// data => {
// resolve(data['data']);
// },
// err => {
// reject(err);
// }
// )
// ;
// });
// }
}

View File

@ -7,7 +7,7 @@ import {properties} from "../../../../../environments/environment";
@Injectable({ providedIn: 'root' })
export class ContextsService {
private communitiesSubject: BehaviorSubject<any> = new BehaviorSubject(null);
private promise: Promise<void>;
private promise: Promise<any>;
private sub: Subscription = null;
constructor(private http: HttpClient=null ) {
@ -34,7 +34,7 @@ export class ContextsService {
public initCommunities() {
let url = properties.contextsAPI + 's/';
this.promise = new Promise<void>((resolve => {
this.promise = new Promise<any>((resolve => {
this.sub = this.http.get((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => this.parseCommunities(res, true) ))
.subscribe(

View File

@ -2,10 +2,8 @@ import {throwError as observableThrowError} from 'rxjs';
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {ClaimEntity, ClaimResult} from '../claimHelper.class';
import {map, timeout} from "rxjs/operators";
import {map} from "rxjs/operators";
import {EnvProperties} from "../../../utils/properties/env-properties";
import {properties} from "../../../../../environments/environment";
import {StringUtils} from "../../../utils/string-utils.class";
@Injectable()
export class SearchCrossrefService {
@ -22,9 +20,7 @@ export class SearchCrossrefService {
}
searchCrossrefByDOIs(DOIs: string[], properties: EnvProperties, parse: boolean = false, file: boolean = false): any {
let timeoutTime: number = properties.environment == "production" ? 6000 : 12000;
// let timeoutTimeForFile: number = 60000;
searchCrossrefByDOIs(DOIs: string[], properties: EnvProperties, parse: boolean = false): any {
var doisParams = "";
for (var i = 0; i < DOIs.length; i++) {
@ -32,21 +28,11 @@ export class SearchCrossrefService {
}
let url = properties.searchCrossrefAPIURL + '?filter=' + doisParams;
return this.http.get(url)
// .pipe(timeout(file ? timeoutTimeForFile : (timeoutTime)))
.pipe(timeout(timeoutTime))
.pipe(map(request => request['message']))
.pipe(map(request => [request["total-results"], parse ? this.parse(request['items']) : request]))
//.map(request => <any> request.json().message)
.pipe(map(request => request['message']))
.pipe(map(request => [request["total-results"], parse ? this.parse(request['items']) : request]))
//.catch(this.handleError);
}
searchCrossrefByDOI(DOI: string): any {
let timeoutTimeForFile: number = 20000;
let url = properties.searchCrossrefAPIURL + '/' + StringUtils.URIEncode(DOI);
return this.http.get(url)
.pipe(timeout(timeoutTimeForFile))
.pipe(map(request => request['message']))
.pipe(map(request => this.parse(request)))
}
searchCrossrefByMultipleDOIs(dois: string[], properties: EnvProperties, parse: boolean = false): any {
let url = properties.searchCrossrefAPIURL + '?filter=doi:';
for (var i = 0; i < dois.length; i++) {
@ -70,11 +56,8 @@ export class SearchCrossrefService {
parse(response): ClaimEntity[] {
const results: ClaimEntity[] = [];
let length = Array.isArray(response) ? response.length : 1;
for (let i = 0; i < length; i++) {
const item = Array.isArray(response) ? response[i] : response;
for (let i = 0; i < response.length; i++) {
const item = response[i];
const entity: ClaimEntity = new ClaimEntity();
entity.result = new ClaimResult();
entity.result.publisher = null;

View File

@ -3,7 +3,7 @@ import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {EnvProperties} from '../../../utils/properties/env-properties';
import {ClaimEntity, ClaimResult} from '../claimHelper.class';
import {catchError, map, timeout} from 'rxjs/operators';
import {catchError, map} from 'rxjs/operators';
import {properties} from "../../../../../environments/environment";
@ -21,14 +21,10 @@ export class SearchDataciteService {
//.catch(this.handleError);
}
getDataciteResultByDOI(doi: string, properties: EnvProperties, parse: boolean = false, file: boolean = false): any {
let timeoutTime: number = properties.environment == "production" ? 6000 : 12000;
let timeoutTimeForFile: number = 20000;
getDataciteResultByDOI(doi: string, properties: EnvProperties, parse: boolean = false): any {
let url = properties.searchDataciteAPIURL + '/' + doi;
let key = url;
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(timeout(file ? timeoutTimeForFile : (timeoutTime)))
.pipe(map(request => (parse ? SearchDataciteService.parse([request["data"]])[0] : request)), catchError(err => of(null)));
}
@ -50,6 +46,7 @@ export class SearchDataciteService {
static parse(response): ClaimEntity[] {
const results: ClaimEntity[] = [];
console.log(response);
for (let i = 0; i < response.length; i++) {
const item = response[i];
const entity: ClaimEntity = new ClaimEntity();
@ -58,20 +55,22 @@ export class SearchDataciteService {
entity.result.journal = null;
entity.result.DOI = item.attributes.doi;
entity.id = item.attributes.doi;
entity.title = Array.isArray(item.attributes.titles) && item.attributes.titles[0].title?item.attributes.titles[0].title:null;
entity.title = item.attributes.title;
entity.result.url = properties.doiURL + item.attributes.doi;
entity.result.source = 'datacite';
entity.type = 'dataset';
entity.result.date = item.attributes.publicationYear;
entity.result.date = item.attributes.published;
entity.result.accessRights = "OPEN";
entity.result.publisher = item.attributes['publisher'];
entity.result.publisher = item.attributes['container-title'];
entity.result.journal = null;
entity.result.record = item;
if (item.attributes.creators) {
if (item.attributes.author) {
entity.result.authors = [];
for (let j = 0; j < item.attributes.creators.length; j++) {
const author = item.attributes.creators[j].name;
entity.result.authors.push(author);
for (let j = 0; j < item.attributes.author.length; j++) {
const author = item.attributes.author[j];
if(author.family || author.literal) {
entity.result.authors.push((author.family) ? author.family + (author.given ? ', ' + author.given : '') : author.literal);
}
}
}
results.push(entity);

View File

@ -21,38 +21,14 @@ export class SearchOrcidService {
let url = properties.searchOrcidURL + term + '/record';
return this.http.get(url, { headers: headers })
//.map(res => res.json()['person'])
.pipe(map(res => res['person']))
.pipe(map(res => [res['name']['given-names'],
res['name']['family-name'],
res['name'], res['name']['institution-name']]))
//.map(res => res.json()['person'])
.pipe(map(res => res['person']))
.pipe(map(res => [res['name']['given-names'],
res['name']['family-name'],
res['name']]))
.pipe(map(res => SearchOrcidService.parseOrcidAuthor(res, authorIds, authors, addId)));
}
.pipe(map(res => SearchOrcidService.parseOrcidAuthor(res, authorIds, authors, addId)));
}
searchOrcidSingleAuthor(term: string, properties: EnvProperties, addId): any {
//var headers = new Headers();
//headers.append('Accept', 'application/orcid+json');
let headers = new HttpHeaders({'Accept': 'application/orcid+json'});
let url ="https://pub.orcid.org/v3.0/expanded-search/?q=orcid:" + term + '&start=0&rows=50';
return this.http.get(url, {headers: headers})
.pipe(map(res => res['expanded-result']))
.pipe(map(res => {
if(res) {
for (let auth_result of res) {
const author = {};
author['id'] = auth_result['orcid-id'];
author['authorGivenName'] = auth_result['given-names'];
author['authorFamilyName'] = auth_result['family-names'];
author['institutions'] = auth_result['institution-name'];
return author;
}
}
return null;
}));
}
searchOrcidAuthors(term: string,
properties: EnvProperties): any {
@ -69,42 +45,14 @@ export class SearchOrcidService {
}
searchOrcidAuthorsNew(term: string,
properties: EnvProperties, size = 10): any {
let headers = new HttpHeaders({'Accept': 'application/orcid+json'});
// let url = properties.searchOrcidURL+'search?defType=edismax&q='+term+'&qf=given-name^1.0+family-name^2.0+other-names^1.0+credit-name^1.0&start=0&rows=10';
let url = /*properties.searchOrcidURL +*/ 'https://pub.orcid.org/v3.0/expanded-search?q=' + StringUtils.URIEncode('{!edismax qf="given-and-family-names^50.0 family-name^10.0 given-names^10.0 credit-name^10.0 other-names^5.0 text^1.0" pf="given-and-family-names^50.0" bq="current-institution-affiliation-name:[* TO *]^100.0 past-institution-affiliation-name:[* TO *]^70" mm=1}') + term + '&start=0&rows=' + size;
// given-and-family-names^50.0 family-name^10.0 given-names^10.0 credit-name^10.0 other-names^5.0 text^1.0" pf="given-and-family-names^50.0" bq="current-institution-affiliation-name:[* TO *]^100.0 past-institution-affiliation-name:[* TO *]^70" mm=1}
// https://pub.orcid.org/v3.0/expanded-search/?q=%7B!edismax%20qf%3D%22given-and-family-names%5E50.0%20family-name%5E10.0%20given-names%5E10.0%20credit-name%5E10.0%20other-names%5E5.0%20text%5E1.0%22%20pf%3D%22given-and-family-names%5E50.0%22%20bq%3D%22current-institution-affiliation-name%3A%5B*%20TO%20*%5D%5E100.0%20past-institution-affiliation-name%3A%5B*%20TO%20*%5D%5E70%22%20mm%3D1%7Dpaolo%20manghi&start=0&rows=50
//q={!edismax qf="given-and-family-names^50.0 family-name^10.0 given-names^5.0 credit-name^10.0 other-names^5.0 text^1.0" pf="given-and-family-names^50.0" mm=1}alessia bardi&start=0&rows=10
let key = url;
return this.http.get(url, {headers: headers})
.pipe(map(res => res['expanded-result']))
.pipe(map(res => {
let authors = [];
if(res) {
for (let auth_result of res) {
const author = {};
author['id'] = auth_result['orcid-id'];
author['authorGivenName'] = auth_result['given-names'];
author['authorFamilyName'] = auth_result['family-names'];
author['institutions'] = auth_result['institution-name'];
authors.push(author);
}
}
return authors;
}));
}
searchOrcidPublications(id: string, properties: EnvProperties, parse: boolean = false): any {
let headers = new HttpHeaders({'Accept': 'application/orcid+json'});
let url = properties.searchOrcidURL + id + '/works';
return this.http.get(url, { headers: headers })
.pipe(map(res => res['group']))
.pipe(map(request => (parse ? SearchOrcidService.parse(id, request) : request)));
}
return this.http.get(url, { headers: headers })
.pipe(map(res => res['group']))
.pipe(map(request => (parse ? SearchOrcidService.parse(id, request) : request)));
}
static parseOrcidAuthor(data: any, authorIds: string[], authors, addId): any {
@ -124,9 +72,6 @@ export class SearchOrcidService {
} else {
author['authorFamilyName'] = "";
}
if (data[3] != null) {
author['institution'] = data[3];
}
authors.push(author);
return true;
}

View File

@ -1,5 +1,5 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../../openaireLibrary/shared/shared.module';
import { SharedModule } from '../../shared/shared.module';
import { CommonModule } from '@angular/common';
import {StartOverComponent} from './startOver.component';
import {AlertModalModule} from '../../utils/modal/alertModal.module';

View File

@ -10,17 +10,18 @@ import {Subscriber} from "rxjs";
@Component({
selector: 'claims-admin',
template: `
<div [class.uk-section]="!isConnect">
<div id="tm-main" [class]="((isConnect)?'':'uk-section') +' uk-padding-remove-top tm-middle'">
<div uk-grid class="uk-margin-small-top">
<div class="tm-main uk-width-1-1@s uk-width-1-1@m uk-width-1-1@l uk-row-first">
<div class="tm-main uk-width-1-1@s uk-width-1-1@m uk-width-1-1@l uk-row-first ">
<div [class.uk-container]="!isConnect" [class.uk-container-large]="!isConnect">
<h1 *ngIf="!isConnect" class="uk-h2">
<div *ngIf="!isConnect" class="uk-article-title custom-article-title">
Manage links
</h1>
</div>
<div>
<displayClaims *ngIf="user" [user]="user" [enableDelete]=true [myClaims]=false
[isAdmin]=true [fetchBy]="(fetchId=='openaire')?null:fetchBy"
[fetchId]="(fetchId=='openaire')?null:fetchId" [actions]="isConnect"
[fetchId]="(fetchId=='openaire')?null:fetchId"
[communityId]="(fetchBy && fetchBy == 'Context' && fetchId && fetchId!='openaire')?fetchId:null"
[externalPortalUrl]=externalPortalUrl [claimsInfoURL]=claimsInfoURL
pageTitle="Manage links"></displayClaims>
@ -29,7 +30,9 @@ import {Subscriber} from "rxjs";
</div>
</div>
</div>
`,
})
export class ClaimsAdminComponent {
@Input() fetchBy: string;
@ -37,6 +40,7 @@ export class ClaimsAdminComponent {
@Input() isConnect: boolean = false;
@Input() externalPortalUrl: string;
@Input() claimsInfoURL: string;
@Input() userInfoURL: string;
public user: User = null;
sub;

View File

@ -1,8 +1,11 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../../openaireLibrary/shared/shared.module';
import { SharedModule } from '../../shared/shared.module';
import { ClaimsAdminComponent } from './claimsAdmin.component';
import {DisplayClaimsModule} from '../claim-utils/displayClaims/displayClaims.module';
import { AdminLoginGuard} from'../../login/adminLoginGuard.guard';
import {PreviousRouteRecorder} from '../../utils/piwik/previousRouteRecorder.guard';
import {IsRouteEnabled} from '../../error/isRouteEnabled.guard';
@NgModule({
imports: [
@ -10,7 +13,7 @@ import {DisplayClaimsModule} from '../claim-utils/displayClaims/displayClaims.mo
DisplayClaimsModule
],
providers:[],
providers:[AdminLoginGuard, PreviousRouteRecorder,IsRouteEnabled],
declarations: [
ClaimsAdminComponent
],

View File

@ -18,12 +18,26 @@ export class ClaimsByTokenService {
let key = url;
return this.http.get(url, CustomOptions.getAuthOptionsWithBody());
return this.http.get(url, CustomOptions.getAuthOptions());
//.map(res => <any> res.text())
//.map(request => <any> request.json());
}
/*
getClaims(email: string, token: string, user_token: string):any {
let url = OpenaireProperties.getClaimsAPIURL(); // What else?
let body = JSON.stringify( {"email": email, "token": token} );
console.warn('Json body: : '+body);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(url, body, options)
.map(res => res.json())
.do(request => console.info("Insert Response:"+request.status) )
.catch(this.handleError);
}
*/
updateClaimsCuration( selectedRight: Set<string>, selectedWrong: Set<string>, apiURL:string) {
let url = apiURL + "curate/bulk";

View File

@ -1,7 +1,6 @@
<loading *ngIf="validInput === null" [full]="true" class="uk-position-center"></loading>
<linking-generic *ngIf="validInput" [localStoragePrefix]="localStoragePrefix" [results]="results" [sources]="sources"
[communityId]="communityId" [inlineEntity]="inlineEntity" [showOptions]="showOptions"
pageTitle="Direct Linking" [claimsProperties]="claimsProperties">
[piwikSiteId]="piwikSiteId" pageTitle="Direct Linking">
</linking-generic>
<div *ngIf="validInput== false" id="tm-main" class=" uk-section uk-padding-remove-top tm-middle">

View File

@ -1,17 +1,13 @@
import {Component, Input, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {EnvProperties} from '../../utils/properties/env-properties';
import {ClaimEntity, ClaimOrganization, ClaimProject, ShowOptions} from '../claim-utils/claimHelper.class';
import {ClaimEntity, ClaimProject, ShowOptions} from '../claim-utils/claimHelper.class';
import {EntitiesSearchService} from '../../utils/entitiesAutoComplete/entitySearch.service';
import {SearchResearchResultsService} from '../../services/searchResearchResults.service';
import {LinkingGenericComponent} from "../linking/linkingGeneric.component";
import {ClaimResultSearchFormComponent} from "../claim-utils/claimResultSearchForm.component";
import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {StringUtils} from "../../utils/string-utils.class";
import {ClaimProjectsSearchFormComponent} from "../claim-utils/claimProjectSearchForm.component";
import {ClaimsProperties} from "../claim-utils/claims.properties";
@Component({
@ -19,26 +15,26 @@ import {ClaimsProperties} from "../claim-utils/claims.properties";
templateUrl: 'directLinking.component.html'
})
export class DirectLinkingComponent {
@Input() piwikSiteId = null;
@ViewChild(LinkingGenericComponent) linking: LinkingGenericComponent;
results: ClaimEntity[] = [];
// linkType: string = "project"; // link type (selected in home page) : project, context, software, etc
/* url Parameters for inline linking */
@Input() id: string = null; //entity id
id: string = null; //entity id
type: string = null; // entity type (publication or dataset)
// linkTo: string = null; // entity type (project or context or entity)
// linkToEntities: string[] = [];
showOptions:ShowOptions = new ShowOptions();
validEntityTypes = ["dataset", "publication", "software", "other", "project", "context", "organization"];
validEntityTypes = ["dataset", "publication", "software", "orp", "project", "context"];
sources: ClaimEntity[] = [];
inlineEntity: ClaimEntity = null;
validInput: boolean = null;//'true;
properties: EnvProperties = properties;
properties: EnvProperties;
@Input() communityId: string = null;
localStoragePrefix: string = "";
@Input() organizationClaim: boolean = false;
@Input() claimsProperties:ClaimsProperties = new ClaimsProperties();
constructor(private _router: Router, private route: ActivatedRoute,private entitySearch:EntitiesSearchService,
private _searchResearchResultsService: SearchResearchResultsService) {}
subscriptions = [];
@ -50,21 +46,21 @@ export class DirectLinkingComponent {
});
}
ngOnInit() {
/* if(!this.claimsProperties){
this.claimsProperties = new ClaimsProperties();
}*/
this.properties = properties;
this.subscriptions.push(this.route.queryParams.subscribe(params => {
if(this.organizationClaim){
this.type = "organization";
this.showOptions.linkTo = "result";
}else {
this.id = params['id'];
this.type = params['type'];
this.showOptions.linkTo = params['linkTo'];
}
this.id = params['id'];
this.type = params['type'];
this.showOptions.linkTo = params['linkTo'];
if (this.type != null && this.showOptions.linkTo != null) {
this.type = (this.validEntityTypes.indexOf(this.type) != -1) ? this.type : 'publication';
this.showOptions.linkTo = (this.validEntityTypes.indexOf(this.showOptions.linkTo) != -1 || this.showOptions.linkTo == "result") ? this.showOptions.linkTo : 'project';
// this.show = (this.linkTo != "entity") ? "claim" : "entity";
// this.linkType = this.linkTo;
// let isInlineResult: boolean = false; // is a link entity - entity
// if ((this.type == "publication" || this.type == "dataset" || this.type == "software") && ((this.linkTo == "publication" || this.linkTo == "dataset" || this.linkTo == "software" || this.linkTo == "orp") || this.linkTo == "entity")) {
// isInlineResult = true;
// }
this.localStoragePrefix = (this.communityId ? (this.communityId + "_") : '') + this.type.substr(0, 3) + "_" + this.showOptions.linkTo.substr(0, 3) + "_";
if (localStorage.getItem(this.localStoragePrefix + "results")) {
@ -77,22 +73,20 @@ export class DirectLinkingComponent {
if (this.type == "project") {
// this.linkType = "project";
this.getProjectById(this.id);
} else if (this.type == "organization") {
this.getOrganizationById(this.id);
} else if (this.type == "publication") {
this.getResearchResultById("publication", this.id);
} else if (this.type == "dataset") {
this.getResearchResultById("dataset", this.id);
} else if (this.type == "software") {
this.getResearchResultById("software", this.id);
} else if (this.type == "other") {
} else if (this.type == "orp") {
this.getResearchResultById("other", this.id);
} else {
this.validInput = this.isValidInput(null);
}
//set which entities it is allowed to link to.
// add first the
if(this.type == "project" || this.type == "organization"){
if(this.type == "project"){
this.showOptions.linkToEntities = ["result"];
this.showOptions.linkTo = "result";
}else{
@ -106,27 +100,24 @@ export class DirectLinkingComponent {
this.showOptions.linkToEntities = ["result","project","context" ];
}
}
} else {
this.validInput = this.isValidInput(null);
}
}));
} else {
this.validInput = this.isValidInput(null);
}
}));
}
isValidInput(result: ClaimEntity) {
if (result == null) {
return false;
} else if (this.type == "organization" && !this.claimsProperties.ALLOW_ORGANIZATION_LINKING) {
} else if (this.type == "project" && this.showOptions.linkTo != "result") {
return false;
} else if ((this.type == "project" || this.type == "organization") && this.showOptions.linkTo != "result") {
} else if (["dataset", "publication", "software", "orp"].indexOf(this.type) != -1 && (["project", "context", "result"].indexOf(this.showOptions.linkTo) == -1)) {
return false;
} else if (["dataset", "publication", "software", "other"].indexOf(this.type) != -1 && (["project", "context", "result"].indexOf(this.showOptions.linkTo) == -1)) {
return false;
} else if (["project", "dataset", "publication", "software", "other", "organization"].indexOf(this.type) == -1) {
} else if (["project", "dataset", "publication", "software", "orp"].indexOf(this.type) == -1) {
return false;
} else {
return true;
@ -144,17 +135,6 @@ export class DirectLinkingComponent {
this.handleError("Error getting project by id: " + id, err);
}));
}
getOrganizationById(id: string) {
this.subscriptions.push(this.entitySearch.fetchByType(id,"organization", this.properties).subscribe(
data => {
this.createClaimEntity(data, "organization");
},
err => {
this.validInput = this.isValidInput(null);
//console.log("An error occured")
this.handleError("Error getting project by id: " + id, err);
}));
}
getResearchResultById(resultType: string, id: string) {
this.subscriptions.push(this._searchResearchResultsService.searchById(resultType, id, this.properties).subscribe(data => {
@ -163,7 +143,7 @@ export class DirectLinkingComponent {
err => {
this.validInput = this.isValidInput(null);
//console.log("An error occured")
this.handleError("Error getting "+this.getEntityName(resultType, false)+" by id: " + id, err);
this.handleError("Error getting "+this.getEntityName(resultType, false, true)+" by id: " + id, err);
}));
}
@ -176,28 +156,16 @@ export class DirectLinkingComponent {
entity.type = "project";
entity.title = project.projectName;
entity.project = new ClaimProject();
entity.project.url = properties.searchLinkToProject + entity.id;
entity.project.acronym = project.projectAcronym;
entity.project.code = project.code;
entity.project.endDate = project.endDate;
entity.project.funderId = project.funderId;
entity.project.funderShortname = project.funderShortName?project.funderShortName:(entity.project.funderId.split("::")[1]);
entity.project.funderName = project.funderName;
entity.project.fundingLevel0 = project.fundingLevel0;
entity.project.jurisdiction = project.jurisdiction;
entity.project.startDate = project.startDate;
this.inlineEntity = entity;
}else if(type =="organization"){
let organization = data[0];
let entity:ClaimEntity = new ClaimEntity();
entity.id = organization.id;
entity.type = "organization";
entity.title = organization.label;
entity.organization = new ClaimOrganization();
// entity.organization.url = properties.searchLinkToOrganization + entity.id;
entity.organization.name = organization.label;
this.inlineEntity = entity;
}else{
}else{
results = ClaimResultSearchFormComponent.openaire2ClaimResults(data, this.properties);
}
@ -211,7 +179,15 @@ export class DirectLinkingComponent {
console.error("Direct Linking Page: " + message, error);
}
private getEntityName (entityType:string, plural:boolean) {
return StringUtils.getEntityName(entityType, plural);
private getEntityName (entityType:string, plural:boolean, full:boolean): string {
if(entityType == "publication") {
return "publication" + (plural ? "s" : "");
} else if(entityType == "dataset") {
return (full ? "research data" : ("dataset" + (plural ? "s" : "")));
} else if(entityType == "software") {
return "software";
} else if(entityType == "other") {
return (full ? ("other research product" + (plural ? "s" : "")) : "other");
}
}
}

View File

@ -1,22 +1,24 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../../openaireLibrary/shared/shared.module';
import { SharedModule } from '../../shared/shared.module';
import { DirectLinkingComponent } from './directLinking.component';
import {EntitySearchServiceModule} from '../../utils/entitiesAutoComplete/entitySearchService.module';
import {SearchResearchResultsServiceModule} from '../../services/searchResearchResultsService.module';
import {LoginGuard} from'../../login/loginGuard.guard';
import {PreviousRouteRecorder} from '../../utils/piwik/previousRouteRecorder.guard';
import {IsRouteEnabled} from '../../error/isRouteEnabled.guard';
import {Schema2jsonldModule} from '../../sharedComponents/schema2jsonld/schema2jsonld.module';
import { SEOServiceModule } from '../../sharedComponents/SEO/SEOService.module';
import {LinkingGenericModule} from '../linking/linkingGeneric.module';
import {LoadingModule} from "../../utils/loading/loading.module";
@NgModule({
imports: [
SharedModule,
EntitySearchServiceModule, SearchResearchResultsServiceModule,
Schema2jsonldModule, SEOServiceModule, LinkingGenericModule, LoadingModule
Schema2jsonldModule, SEOServiceModule, LinkingGenericModule
],
providers:[],
providers:[LoginGuard, PreviousRouteRecorder, IsRouteEnabled],
declarations: [
DirectLinkingComponent
], exports:[DirectLinkingComponent]

View File

@ -21,17 +21,15 @@ declare var UIkit: any;
<div>
<!--div class="uk-text-lead">Upload a DOI csv file <helper div="link-result-bulk" tooltip=true ></helper></div>
<label for="exampleInputFile">Select a file: </label-->
<div class="uk-float-left">
<span class="js-upload" uk-form-custom>
<input id="exampleInputFile" class="uk-width-medium" type="file" (change)="fileChangeEvent($event)"/>
<span class="uk-link " style="text-decoration: underline;">Upload a DOI's CSV file </span>
</span>
<div class="js-upload" uk-form-custom>
<input id="exampleInputFile" class="uk-width-medium" type="file" (change)="fileChangeEvent($event)"/>
<span class="uk-link " style="text-decoration: underline;">Upload a DOI's CSV file </span>
<!--button class="uk-button portal-button" type="button" tabindex="-1" [class.disabled]="!enableUpload" ><span class="uk-margin-small-right uk-icon" >
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <polyline fill="none" stroke="#000" points="5 8 9.5 3.5 14 8 "></polyline> <rect x="3" y="17" width="13" height="1"></rect>
<line fill="none" stroke="#000" x1="9.5" y1="15" x2="9.5" y2="4"></line></svg></span> Select</button-->
<!--helper div="link-result-bulk" tooltip=true ></helper-->
<span class=" " title="{{tooltip}}" uk-tooltip><span class="uk-icon" uk-icon="icon: info; ratio: 0.8">&nbsp; </span> </span>
</div>
<span class=" " title="{{tooltip}}" uk-tooltip><span class="uk-icon" uk-icon="icon: info; ratio: 0.8">&nbsp; </span> </span>
<div *ngIf="showReport" uk-alert class="uk-alert-primary">
<a class="uk-alert-close" uk-close></a>
<div>Uploaded file contains <span
@ -109,16 +107,17 @@ export class BulkClaimComponent {
exceedsLimit = false;
@Input() basketLimit ;
tooltip = `
<div>
<div class="uk-margin-bottom">Up to 100 DOIs</div>
<div><span class="uk-text-bold">CSV format:</span> <br>&quot;DOI&quot;,&quot;ACCESS_MODE&quot;,&quot;DATE&quot;</div>
<br>
<div class="uk-text-small">
<div>- DOI is required</div>
<div>- Access mode: <br> OPEN, CLOSED, EMBARGO</div>
<div>- Embargo end date:<br> YYYY-MM-DD </div>
</div>
</div>`;
<div class="uk-padding-small uk-padding-remove-right uk-padding-remove-left">
<div >
<div><span class="uk-text-bold">CSV format:</span> <br>&quot;DOI&quot;,&quot;ACCESS_MODE&quot;,&quot;DATE&quot;</div>
<br>
<div class=" uk-text-small">
<div>- DOI is required</div>
<div>- Access mode: <br> OPEN, CLOSED, EMBARGO</div>
<div>- Embargo end date:<br> YYYY-MM-DD </div>
</div>
</div>
</div>`;
constructor(private _searchCrossrefService: SearchCrossrefService, private _searchDataciteService: SearchDataciteService) {
this.filesToUpload = [];
}
@ -133,11 +132,11 @@ export class BulkClaimComponent {
}
});
}
upload() {
this.enableUpload = false;
this.showReport = false;
this.errorMessage = "";
console.log(this.filesToUpload);
if (this.filesToUpload.length == 0) {
this.errorMessage = "There is no selected file to upload.";
return;
@ -150,7 +149,7 @@ export class BulkClaimComponent {
}
this.loading.open();
this.makeFileRequest(this.properties.utilsService + '/upload', [], this.filesToUpload).then(async (result) => {
this.makeFileRequest(this.properties.utilsService + '/upload', [], this.filesToUpload).then((result) => {
const rows = (result as any).split('\n'); // I have used space, you can use any thing.
this.exceedsLimit = false;
let invalid_rows = 0;
@ -179,7 +178,6 @@ export class BulkClaimComponent {
this.allIds.push(id);
if (currentLength < this.basketLimit){
currentLength++;
await new Promise((resolve) => setTimeout(resolve, 100));
this.fetchResult(id, accessMode, Dates.getDateToString(embargoDate), i + 1);
}else{
this.exceedsLimit = true;
@ -228,7 +226,7 @@ export class BulkClaimComponent {
}
makeFileRequest(url: string, params: Array<string>, files: Array<File>) {
return new Promise<void>((resolve, reject) => {
return new Promise((resolve, reject) => {
const formData: any = new FormData();
const xhr = new XMLHttpRequest();
for (let i = 0; i < files.length; i++) {
@ -249,12 +247,11 @@ export class BulkClaimComponent {
}
fetchResult(id: string, accessMode: string, date: string, row: number) {
// this.subscriptions.push(this._searchCrossrefService.searchCrossrefByDOIs([id], this.properties, true, true).subscribe(
this.subscriptions.push(this._searchCrossrefService.searchCrossrefByDOI(id).subscribe(
this.subscriptions.push(this._searchCrossrefService.searchCrossrefByDOIs([id], this.properties, true).subscribe(
data => {
if (data.length > 0) {
const result:ClaimEntity = data[0];
const result:ClaimEntity = data[1][0];
if (data[1].length > 0) {
this.foundIds.push(id);
result.result.accessRights = accessMode;
result.result.embargoEndDate = date;
@ -270,16 +267,11 @@ export class BulkClaimComponent {
}
},
err => {
// console.log(err);
//console.log(err);
BulkClaimComponent.handleError("Error getting crossref by DOIs: " + id, err);
if(err.status == 404) {
this.searchInDatacite(id, accessMode, date, row);
} else {
this.notFoundIds.push(id);
this.notFoundIdsRow.push(row);
this.endOfFetching();
}
this.notFoundIds.push(id);
this.notFoundIdsRow.push(row);
this.endOfFetching();
}
));
}

View File

@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../../../openaireLibrary/shared/shared.module';
import { SharedModule } from '../../../shared/shared.module';
import {LoadingModalModule} from '../../../utils/modal/loadingModal.module';
import {BulkClaimComponent} from './bulkClaim.component';
import {SearchCrossrefServiceModule} from '../../claim-utils/service/searchCrossrefService.module';

View File

@ -1,5 +1,5 @@
import {Component, EventEmitter, Input, Output, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Component, Input, Output, EventEmitter, ViewChild} from '@angular/core';
import {Router, ActivatedRoute} from '@angular/router';
import {ClaimsService} from '../../claim-utils/service/claims.service';
import {ModalLoading} from '../../../utils/modal/loading.component';
import {AlertModal} from '../../../utils/modal/alert';
@ -14,56 +14,48 @@ import {
Message
} from "../../claim-utils/claimHelper.class";
import {UserManagementService} from "../../../services/user-management.service";
import {Subscriber, timer} from "rxjs";
import {map} from "rxjs/operators";
import {LogService} from "../../../utils/log/log.service";
import {Subscriber} from "rxjs";
@Component({
selector: 'claim-insert',
template: `
<div (click)="insert()" class="uk-card-footer uk-flex uk-flex-center clickable"
[class.uk-tile-primary]="(results.length > 0 && (sources.length > 0 || inlineEntity))"
[class.uk-background-muted]="!(results.length > 0 && (sources.length > 0 || inlineEntity))"
[class.uk-disabled]="!(results.length > 0 && (sources.length > 0 || inlineEntity))">
<button class="uk-flex uk-flex-middle uk-button uk-button-text"
[class.uk-disabled]="!(results.length > 0 && (sources.length > 0 || inlineEntity))"
[disabled]="!(results.length > 0 && (sources.length > 0 || inlineEntity))">
<icon name="link" visuallyHidden="link" [flex]="true"></icon>
<div class="uk-width-expand uk-margin-small-left">CONFIRM LINKING</div>
</button>
</div>
<modal-loading [message]="'Please wait...'">
<div *ngIf="claimsJob">
<div *ngIf="claimsJob && claimsJob.insertedIds.length <1" class="uk-text-meta uk-text-small">
Initiating process....</div>
<div *ngIf="claimsJob && claimsJob.insertedIds.length >0" class="uk-text-meta uk-text-small">
{{claimsJob.insertedIds.length}} out of {{claims2Insert}} links created.</div>
<div *ngIf="feedRecordsJob && feedRecordsJob.insertedIds.length >0" class="uk-text-meta uk-text-small">
{{feedRecordsJob.insertedIds.length}} out of {{records2Insert}} records added in the index...</div>
<div *ngIf="claimsJob.status != 'COMPLETE'" class="uk-text-meta uk-text-small">
Please don't close the window, process is ongoing...</div>
<div class="uk-width-1-1">
<modal-loading [message]="'Please wait...'"></modal-loading>
<modal-alert (alertOutput)="confirmClose()">
<h4 class="modal-title uk-text-bold " id="myModalLabel">Confirmation notice</h4>
<p>All the links you provided will be published in the OpenAIRE platform. <br>
Please make sure that the information is valid.<br>
<span class="uk-text-bold">In some cases, links take some time to be published.</span><br>
For more information please check the linking status in My-Links page.
</p>
<p>
Do you confirm the information you provide is valid?
</p>
</modal-alert>
<div class="uk-clearfix">
<div>
<div *ngIf="!claiming " (click)="insert()" style="width: 350px;"
[class]="getButtonClass()">CONFIRM LINKING
<span [class]="(defaultColors?'':' uk-margin-small-top ')+'uk-icon uk-float-right uk-text-bold uk-margin-small-right'">
<svg width="30" height="30" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
icon="chevron-right" ratio="1.5"><polyline fill="none" stroke="#000" stroke-width="1.03"
points="7 4 13 10 7 16"></polyline></svg>
</span>
</div>
</div>
</div>
</modal-loading>
<modal-alert (alertOutput)="confirmClose()">
<h4 class="modal-title uk-text-bold " id="myModalLabel">Confirmation notice</h4>
<p>All the links you provided will be published in the OpenAIRE platform. <br>
Please make sure that the information is valid.<br>
<span class="uk-text-bold">In some cases, links take some time to be published.</span><br>
For more information please check the linking status in My-Links page.
</p>
<p>
Do you confirm the information you provide is valid?
</p>
</modal-alert>
</div>
`
})
export class ClaimInsertComponent {
constructor(private claimService: ClaimsService, private _router: Router, private route: ActivatedRoute,
private userManagementService: UserManagementService, private _logService: LogService) {
private userManagementService: UserManagementService) {
}
subscriptions = [];
timerSubscription;
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
@ -75,31 +67,6 @@ export class ClaimInsertComponent {
this.subscriptions.push(this.route.queryParams.subscribe(params => {
this.params = params;
}));
if(localStorage.getItem(this.localStoragePrefix + "claimsJob")){
this.claimsJob = JSON.parse(localStorage.getItem(this.localStoragePrefix + "claimsJob"));
this.feedRecordsJob = JSON.parse(localStorage.getItem(this.localStoragePrefix + "feedRecordsJob"));
if(this.claimsJob.status != "COMPLETE"){
this.claiming = true;
let loadingTimerSubscription = timer(0, 1000).pipe(
map(() => {
if(this.loading) {
this.loading.open();
loadingTimerSubscription.unsubscribe();
}
})
).subscribe();
this.subscriptions.push(loadingTimerSubscription);
this.timerSubscription = timer(0, 10000).pipe(
map(() => {
this.getStatus(); // load data contains the http request
})
).subscribe();
this.subscriptions.push(this.timerSubscription);
}else{
this.claimsJob = null;
}
}
}
params = {};
@ -124,16 +91,15 @@ export class ClaimInsertComponent {
private errorInClaims: ClaimRecord2Insert[] = [];
private insertedRecords = [];
private errorInRecords = [];
public claimsJob;
public feedRecordsJob;
public claims2Insert;
public records2Insert
infoToLog = [];
public insert() {
this.confirmOpen();
this.confirmOpen();
}
saveAndNavigate(){
this.saveLocalStorage();
localStorage.setItem(this.localStoragePrefix + "results", JSON.stringify(this.results));
if (this.sources != null) {
localStorage.setItem(this.localStoragePrefix + "sources", JSON.stringify(this.sources));
}
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
@ -147,7 +113,6 @@ export class ClaimInsertComponent {
this.errorInClaims = [];
this.insertedRecords = [];
this.errorInRecords = [];
this.infoToLog = [];
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
if (!user) {
this.saveAndNavigate();
@ -156,14 +121,13 @@ export class ClaimInsertComponent {
this.loading.open();
let claims: ClaimRecord2Insert[] = [];
let directclaims: DirectIndexRecord[] = [];
let idSuffix = (new Date()).getTime() + "";
let dashboard = this.properties.environment+"_"+this.properties.dashboard + (this.communityId?("_"+this.communityId):'');
for (let j = 0; j < this.sources.length; j++) { // if an external result -> direct insert in the index
const result: ClaimEntity = this.sources[j];
if (result.result && ["crossref", "datacite", "orcid"].indexOf(result.result.source) != -1) {
directclaims.push({
"id": result.id,
"record": ClaimInsertComponent.createDirectClaim(result, this.results, idSuffix)
"record": ClaimInsertComponent.createDirectClaim(result, this.results)
});
}
}
@ -174,12 +138,12 @@ export class ClaimInsertComponent {
if (this.sources.length > 0) {
directclaims.push({
"id": entity.id,
"record": ClaimInsertComponent.createDirectClaim(entity, this.sources, idSuffix)
"record": ClaimInsertComponent.createDirectClaim(entity, this.sources)
});
} else if (this.inlineEntity && this.inlineEntity.type != "organization") {
} else if (this.inlineEntity) {
directclaims.push({
"id": entity.id,
"record": ClaimInsertComponent.createDirectClaim(entity, [this.inlineEntity], idSuffix)
"record": ClaimInsertComponent.createDirectClaim(entity, [this.inlineEntity])
});
}
@ -188,35 +152,28 @@ export class ClaimInsertComponent {
for (let j = 0; j < this.sources.length; j++) {
const result: ClaimEntity = this.sources[j]; // this is a research result
if (entity.result) {
claims.push(ClaimInsertComponent.createResultClaim(result, entity, user.email, dashboard, idSuffix));
claims.push(ClaimInsertComponent.createResultClaim(result, entity, user.email, dashboard));
} else if (entity.context) {
claims.push(ClaimInsertComponent.createContextClaim(result, entity, user.email, dashboard, idSuffix));
claims.push(ClaimInsertComponent.createContextClaim(result, entity, user.email, dashboard));
} else if (entity.project) {
claims.push(ClaimInsertComponent.createProjectClaim(result, entity, user.email, dashboard, idSuffix));
/* } else if (entity.organization) {
claims.push(ClaimInsertComponent.createOrganizationClaim(result, entity, user.email, dashboard, idSuffix));*/
claims.push(ClaimInsertComponent.createProjectClaim(result, entity, user.email, dashboard));
}
this.infoToLog.push([ result.title?result.title: result.id, entity.title?entity.title:entity.id]);
}
if (this.inlineEntity) {
this.infoToLog.push([ this.inlineEntity.title?this.inlineEntity.title: this.inlineEntity.id, entity.title?entity.title:entity.id]);
if (this.inlineEntity.result) {
if (entity.result) {
claims.push(ClaimInsertComponent.createResultClaim(this.inlineEntity, entity, user.email, dashboard, idSuffix));
claims.push(ClaimInsertComponent.createResultClaim(this.inlineEntity, entity, user.email, dashboard));
} else if (entity.context) {
claims.push(ClaimInsertComponent.createContextClaim(this.inlineEntity, entity, user.email, dashboard, idSuffix));
claims.push(ClaimInsertComponent.createContextClaim(this.inlineEntity, entity, user.email, dashboard));
} else if (entity.project) {
claims.push(ClaimInsertComponent.createProjectClaim(this.inlineEntity, entity, user.email, dashboard, idSuffix));
claims.push(ClaimInsertComponent.createProjectClaim(this.inlineEntity, entity, user.email, dashboard));
}
} else if (this.inlineEntity.project) {
if (entity.result) {
claims.push(ClaimInsertComponent.createProjectClaim(entity, this.inlineEntity, user.email, dashboard, idSuffix));
}
} else if (this.inlineEntity.organization) {
if (entity.result) {
claims.push(ClaimInsertComponent.createOrganizationClaim(entity, this.inlineEntity, user.email, dashboard, idSuffix));
claims.push(ClaimInsertComponent.createProjectClaim(entity, this.inlineEntity, user.email, dashboard));
}
}
}
@ -227,15 +184,12 @@ export class ClaimInsertComponent {
//first call direct index service - when call is done (success or error) call isertBulkClaims method to insert claims in DB
// console.log("directclaims");
// console.log(directclaims);
if (directclaims.length > 0/* && this.properties.environment != "development"*/){
if (directclaims.length > 0 && this.properties.environment != "development"){
this.subscriptions.push(this.claimService.insertDirectRecords(directclaims, this.properties.claimsAPIURL).subscribe(
data => {
this.feedRecordsJob = data.data;
this.records2Insert = directclaims.length;
// console.log(data);
// this.insertedRecords = data.insertedIds;
//
// this.errorInRecords = data.errorInClaims;
this.insertedRecords = data.insertedIds;
this.errorInRecords = data.errorInClaims;
this.isertBulkClaims(claims);
},
err => {
@ -243,12 +197,12 @@ export class ClaimInsertComponent {
if (err.code && err.code == 403) {
this.saveAndNavigate();
}
/* if (err.insertedIds && err.insertedIds.length > 0) {
if (err.insertedIds && err.insertedIds.length > 0) {
this.insertedRecords = err.insertedIds;
}
if (err.errorInClaims && err.errorInClaims.length > 0) {
this.errorInRecords = err.errorInClaims;
}*/
}
this.isertBulkClaims(claims);
ClaimInsertComponent.handleError("Error inserting direct records: " + JSON.stringify(directclaims), err);
@ -262,24 +216,30 @@ export class ClaimInsertComponent {
}
private isertBulkClaims(claims: ClaimRecord2Insert[]) {
console.log("claims");
console.log(claims);
this.errors.splice(0, this.errors.length);
this.subscriptions.push(this.claimService.insertBulkClaims(claims, this.properties.claimsAPIURL).subscribe(
data => {
this.claims2Insert = claims.length;
this.claimsJob = data.data;
if(this.properties.logServiceUrl) {
for(let info of this.infoToLog) {
this.subscriptions.push(this._logService.logLink(this.properties, info[0],info[1]).subscribe(res => {
}));
}
this.insertedClaims = data.insertedIds;
this.errorInClaims = data.errorInClaims;
//TODO remove - testing having errors in claims
// this.insertedClaims.pop();
// this.insertedClaims.pop();
// this.errorInClaims.push(claims[1]);
// this.insertedClaims.splice(0,this.insertedClaims.length);
// this.errorInClaims = claims;
//remove till here
if (claims.length != this.insertedClaims.length) {
let error: ClaimsErrorMessage = new ClaimsErrorMessage();
error.type = "claimServiceFail2Insert";
error.inserted = this.insertedClaims.length;
error.failed = this.errorInClaims.length;
this.createErrorMessagesPerEntity((this.insertedClaims.length == 0));
this.errors.push(error);
}
this.saveLocalStorage();
this.timerSubscription = timer(0, 10000).pipe(
map(() => {
this.getStatus(); // load data contains the http request
})
).subscribe();
this.subscriptions.push(this.timerSubscription);
this.afterclaimsInsertion();
},
err => {
err = err && err.error?err.error:err;
@ -382,27 +342,19 @@ export class ClaimInsertComponent {
}
private afterclaimsInsertion() {
this.claiming = false;
this.loading.close();
this.loading.close();
this.claiming = false;
if (this.errorInClaims.length == 0 && this.insertedClaims.length > 0) {
localStorage.removeItem(this.localStoragePrefix + "sources");
localStorage.removeItem(this.localStoragePrefix + "results");
localStorage.removeItem(this.localStoragePrefix + "claimsJob");
localStorage.removeItem(this.localStoragePrefix + "feedRecordsJob");
if(this.properties.myClaimsLink && this.properties.myClaimsLink.indexOf(".") == -1) {
this._router.navigate([this.properties.myClaimsLink], {queryParams: this.params});
}else if(this.properties.myClaimsLink && this.properties.myClaimsLink.indexOf(".") != -1) {
this._router.navigate([this.properties.myClaimsLink], {relativeTo: this.route});
}else{
this._router.navigate(["/"]);
}
this._router.navigate(['/myclaims'], {queryParams: this.params});
}
}
private static createContextClaim(resultEntity: ClaimEntity, contextEntity: ClaimEntity, user: any, dashboard:string, idSuffix:string): ClaimRecord2Insert {
private static createContextClaim(resultEntity: ClaimEntity, contextEntity: ClaimEntity, user: any, dashboard:string): ClaimRecord2Insert {
return {
claimedBy: user,
sourceId: contextEntity.context.concept.id,
@ -415,12 +367,11 @@ export class ClaimInsertComponent {
targetCollectedFrom: resultEntity.result.source,
targetAccessRights: resultEntity.result.accessRights,
targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(resultEntity),
claimedInDashboard : dashboard,
idSuffix : idSuffix
claimedInDashboard : dashboard
};
}
private static createProjectClaim(resultEntity: ClaimEntity, projectEntity: ClaimEntity, user: any, dashboard:string, idSuffix:string): ClaimRecord2Insert {
private static createProjectClaim(resultEntity: ClaimEntity, projectEntity: ClaimEntity, user: any, dashboard:string): ClaimRecord2Insert {
return {
claimedBy: user,
sourceId: projectEntity.id,
@ -433,29 +384,11 @@ export class ClaimInsertComponent {
targetCollectedFrom: resultEntity.result.source,
targetAccessRights: resultEntity.result.accessRights,
targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(resultEntity),
claimedInDashboard : dashboard,
idSuffix : idSuffix
};
}
private static createOrganizationClaim(resultEntity: ClaimEntity, organizationEntity: ClaimEntity, user: any, dashboard:string, idSuffix:string): ClaimRecord2Insert {
return {
claimedBy: user,
sourceId: organizationEntity.id,
sourceType: "organization",
sourceCollectedFrom: "openaire",
sourceAccessRights: "OPEN",
sourceEmbargoEndDate: "",
targetId: resultEntity.id,
targetType: resultEntity.type,
targetCollectedFrom: resultEntity.result.source,
targetAccessRights: resultEntity.result.accessRights,
targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(resultEntity),
claimedInDashboard : dashboard,
idSuffix : idSuffix
claimedInDashboard : dashboard
};
}
private static createResultClaim(inlineResult: ClaimEntity, resultEntity: ClaimEntity, user: string, dashboard:string, idSuffix:string): ClaimRecord2Insert {
private static createResultClaim(inlineResult: ClaimEntity, resultEntity: ClaimEntity, user: string, dashboard:string): ClaimRecord2Insert {
return {
claimedBy: user,
@ -469,9 +402,7 @@ export class ClaimInsertComponent {
targetCollectedFrom: inlineResult.result.source,
targetAccessRights: inlineResult.result.accessRights,
targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(inlineResult),
claimedInDashboard : dashboard,
idSuffix : idSuffix
claimedInDashboard : dashboard
};
}
@ -481,13 +412,12 @@ export class ClaimInsertComponent {
}
return ""
}
static createOpenAIREId(id, idSuffix:string):string {
return id.indexOf( "::" ) == -1 ? ("userclaim___::" + Md5.hashStr(id + idSuffix)):id;
}
static createDirectClaim(resultEntity: ClaimEntity, results: ClaimEntity[], idSuffix:string) {
static createDirectClaim(resultEntity: ClaimEntity, results: ClaimEntity[]) {
let entity = {};
entity["originalId"] = this.createOpenAIREId(resultEntity.id, idSuffix);
entity["openaireId"] = this.createOpenAIREId(resultEntity.id, idSuffix);
const md5_id = Md5.hashStr(resultEntity.id);
entity["originalId"] = "userclaim___::" + md5_id;
entity["openaireId"] = "userclaim___::" + md5_id;
entity["title"] = resultEntity.title;
entity["title"] = (Array.isArray(resultEntity.title) && resultEntity.title.length > 0) ? resultEntity.title[0] : resultEntity.title;
@ -536,7 +466,7 @@ export class ClaimInsertComponent {
entity["linksToProjects"] = [];
}
let project: ClaimEntity = results[i];
entity["linksToProjects"].push("info:eu-repo/grantAgreement/" + project.project.funderShortname + "/" + project.project.fundingLevel0 + "/" + project.project.code + "/" + project.project.jurisdiction + "/" + project.title + "/" + project.project.acronym);
entity["linksToProjects"].push("info:eu-repo/grantAgreement/" + project.project.funderName + "/" + project.project.fundingLevel0 + "/" + project.project.code + "/" + project.project.jurisdiction + "/" + project.title + "/" + project.project.acronym);
} else if (results[i].context) {
@ -594,76 +524,10 @@ export class ClaimInsertComponent {
}
if(this.defaultColors){
buttonClass+=" linksbaskettitles uk-padding-small ";
}else{
buttonClass+=" uk-button uk-button-large ";
}
return buttonClass + "uk-text-center ";
}
getStatus(){
if(this.feedRecordsJob && ! (this.feedRecordsJob.status == "COMPLETE" || this.feedRecordsJob.status == "FAILED") ) {
this.subscriptions.push(this.claimService.getStatus(this.feedRecordsJob.id, this.properties.claimsAPIURL).subscribe(data => {
this.feedRecordsJob = data.data;
if (this.feedRecordsJob.status == "COMPLETE" || this.feedRecordsJob.status == "FAILED") {
this.insertedRecords = this.feedRecordsJob.insertedIds;
this.errorInRecords = this.feedRecordsJob.errorInClaims;
}
}, err => {
let error: ClaimsErrorMessage = new ClaimsErrorMessage();
error.type = "jobError";
this.createErrorMessagesPerEntity((this.insertedClaims.length == 0));
this.errors.push(error);
this.afterclaimsInsertion();
this.feedRecordsJob = null;
localStorage.removeItem(this.localStoragePrefix + "feedRecordsJob");
}
));
}
if(this.claimsJob) {
this.subscriptions.push(this.claimService.getStatus(this.claimsJob.id, this.properties.claimsAPIURL).subscribe(data => {
this.claimsJob = data.data;
if ((this.claimsJob.status == "COMPLETE" || this.claimsJob.status == "FAILED") &&
( !this.feedRecordsJob || (this.feedRecordsJob.status == "COMPLETE" || data.data.status == "FAILED"))) {
this.insertedClaims = this.claimsJob.insertedIds;
this.errorInClaims = this.claimsJob.errorInClaims;
if (this.claims2Insert != this.insertedClaims.length) {
let error: ClaimsErrorMessage = new ClaimsErrorMessage();
error.type = "claimServiceFail2Insert";
error.inserted = this.insertedClaims.length;
error.failed = this.errorInClaims.length;
this.createErrorMessagesPerEntity((this.insertedClaims.length == 0));
this.errors.push(error);
}
this.afterclaimsInsertion();
this.timerSubscription.unsubscribe();
}
}, err => {
let error: ClaimsErrorMessage = new ClaimsErrorMessage();
error.type = "jobError";
this.createErrorMessagesPerEntity((this.insertedClaims.length == 0));
this.errors.push(error);
this.afterclaimsInsertion();
this.claimsJob = null;
localStorage.removeItem(this.localStoragePrefix + "claimsJob");
}
));
}
}
saveLocalStorage(){
if (this.results != null) {
localStorage.setItem(this.localStoragePrefix + "results", JSON.stringify(this.results));
}
if (this.sources != null) {
localStorage.setItem(this.localStoragePrefix + "sources", JSON.stringify(this.sources));
}
if (this.claimsJob != null) {
localStorage.setItem(this.localStoragePrefix + "claimsJob", JSON.stringify(this.claimsJob));
}
if (this.feedRecordsJob != null) {
localStorage.setItem(this.localStoragePrefix + "feedRecordsJob", JSON.stringify(this.feedRecordsJob));
}
}
}

View File

@ -1,16 +1,14 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../../../openaireLibrary/shared/shared.module';
import { SharedModule } from '../../../shared/shared.module';
import {AlertModalModule} from '../../../utils/modal/alertModal.module';
import {LoadingModalModule} from '../../../utils/modal/loadingModal.module';
import {ClaimInsertComponent} from './insertClaim.component';
import {ClaimServiceModule} from '../../claim-utils/service/claimsService.module';
import {IconsModule} from "../../../utils/icons/icons.module";
import {LogServiceModule} from "../../../utils/log/LogService.module";
@NgModule({
imports: [
SharedModule, AlertModalModule, LoadingModalModule, ClaimServiceModule, IconsModule, LogServiceModule
SharedModule, AlertModalModule, LoadingModalModule, ClaimServiceModule
],
declarations: [ClaimInsertComponent],
exports:[ ClaimInsertComponent]

View File

@ -1,263 +1,353 @@
<ng-template #destinations_basket>
<div *ngIf="(results.length)> 0 || showOptions.show=='result'" class="uk-padding-small uk-padding-remove-horizontal" style="min-height: 17px;">
<start-over *ngIf=" (results.length)> 0"
[results]="results" [localStoragePrefix]="localStoragePrefix+'results'"
message="all results (projects, communities, research results)"
class="uk-float-right"></start-over>
<bulk-claim *ngIf="showOptions.show=='result'" [results]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit"></bulk-claim>
</div>
<div class="uk-padding-small uk-padding-remove-horizontal">
<div *ngIf="results.length >= basketLimit "
class="uk-alert uk-alert-warning uk-text-center">
Basket reached the size limit. No more entities can be added.
</div>
<claim-selected-results sectionTitle="Selected Results" [results]="results"
[localStoragePrefix]="localStoragePrefix+'results'" type="target">
</claim-selected-results>
<div *ngIf="(results.length) == 0 " class=" uk-text-center">
No entities to link with the sources. Start adding entities from the left panel.
</div>
<metadata-preview *ngIf="showOptions.show=='claim' && properties" class="uk-margin-top"
[results]="results" [sources]="sources"
[localStoragePrefix]="localStoragePrefix" [inlineEntity]="inlineEntity"
[showOptions]="showOptions" [properties]=properties [pageContents]="pageContents"
[defaultColors]="(communityId?false:true)" [communityId]="communityId"
>
</metadata-preview>
<div id="tm-main" class="uk-section uk-padding-remove-top tm-middle" *ngIf="showOptions.show != 'claim'">
<div class="uk-grid">
<div class="tm-main uk-width-1-1@s uk-width-1-1@m uk-width-1-1@l uk-row-first ">
<schema2jsonld *ngIf="url" [URL]="url" name="Link your research outcomes" type="other"></schema2jsonld>
<div [class]="((showOptions.show == 'claim')?'':' uk-margin-top ')+' uk-container uk-container-large '">
<div>
<!-- <div class="uk-width-1-1">
<helper position="top"></helper>
</div> -->
<div class="uk-grid helper-grid">
<!-- <helper position="left" styleName=" uk-width-1-5 uk-padding-left"></helper>-->
<div class="uk-width-expand">
</div>
</ng-template>
<div *ngIf="properties" class="uk-section uk-section-default white-box-with-border uk-padding-small uk-padding-remove-top">
<div style=""
[class]="((showOptions.show == 'claim')?'':' uk-margin-top ')+' uk-container uk-container-large '">
<div id="basketStickTop"></div>
<div class="uk-grid" *ngIf="showOptions.show!='claim'" >
<div class="uk-width-2-3">
<div class="uk-margin-small-bottom">
<div class="linking uk-background-default">
<div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom">
<div class="uk-padding-small uk-padding-remove-horizontal">
<breadcrumbs *ngIf="!inlineEntity" [breadcrumbs]="breadcrumbs"></breadcrumbs>
<!-- [routerLink]="inlineEntity.result?.url.split('?')[0]"-->
<!-- [queryParams]="routerHelper.createQueryParam(inlineEntity.result?.url.split('?')[1].split('=')[0], inlineEntity.id)"-->
<a *ngIf="inlineEntity && inlineEntity.result"
(click)="back()"
class="uk-button uk-button-link uk-text-transform-none uk-flex uk-flex-middle">
<icon name="west" [flex]="true"></icon>
<span class="uk-margin-small-left">Back to {{getEntityName(inlineEntity.type, false)}}</span>
</a>
<a *ngIf="inlineEntity && inlineEntity.project"
[routerLink]="inlineEntity.project?.url?.split('?')[0]"
[queryParams]="routerHelper.createQueryParam(inlineEntity.project?.url.split('?')[1].split('=')[0], inlineEntity.id)"
class="uk-button uk-button-link uk-text-transform-none uk-flex uk-flex-middle">
<icon name="west" [flex]="true"></icon>
<span class="uk-margin-small-left">Back to {{getEntityName(inlineEntity.type, false)}}</span>
</a>
</div>
</div>
<div *ngIf="!inlineEntity" uk-sticky="offset: 65; end: #pageBottom; media: @m" class="uk-blur-background">
<div class="uk-section-xsmall">
<stepper>
<step [status]="stepStatus('source')" stepId="source" stepNumber="1"
[stepText]="'Find Sources'" (stepChanged)="stepHasChanged($event)"
[active]="this.showOptions.show" [showStepLine]="false"></step>
<step [status]="stepStatus('target')" stepId="target" [stepNumber]="2"
[stepText]="'Link Sources to Entities'"
(stepChanged)="stepHasChanged($event)" [active]="this.showOptions.show"
[showStepLine]="true"></step>
<step [status]="stepStatus('claim')" stepId="claim" [stepNumber]="3"
[stepText]="'Summarize and finish'"
(stepChanged)="stepHasChanged($event)" [active]="this.showOptions.show"
[showStepLine]="true"></step>
</stepper>
</div>
</div>
<div id="pageTop"></div>
<metadata-preview *ngIf="showOptions.show=='claim' && properties" class="uk-margin-top"
[results]="results" [sources]="sources"
[localStoragePrefix]="localStoragePrefix" [inlineEntity]="inlineEntity"
[showOptions]="showOptions" [properties]=properties [pageContents]="pageContents"
[defaultColors]="!communityId" [communityId]="communityId" [claimsProperties]="claimsProperties"
>
</metadata-preview>
<div id="tm-main" class="uk-section uk-padding-remove-top" *ngIf="showOptions.show != 'claim'">
<div>
<schema2jsonld *ngIf="url" [URL]="url" name="Link your {{openaireEntities.RESULTS}}" type="other"></schema2jsonld>
<div class="uk-container uk-container-large">
<div *ngIf="properties && claimsProperties" class="uk-section uk-padding-remove-top">
<div class="uk-container uk-container-large">
<div class="uk-grid basketContainer" *ngIf="showOptions.show!='claim'" uk-grid>
<div class="uk-width-2-3@m uk-position-z-index uk-flex-first@m uk-flex-last uk-margin-medium-top">
<h2 *ngIf="inlineEntity && claimsProperties.INLINE_ENTITY.show" class="uk-text-center">Link source to</h2>
<div *ngIf="inlineEntity && claimsProperties.INLINE_ENTITY.guideText" class="uk-text-center">{{claimsProperties.INLINE_ENTITY.guideText}}</div>
<div *ngIf="showOptions.show=='source'">
<claim-result-search-form [selectedResults]="sources" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'sources'"
[basketLimit]="basketLimit" [centerAlign]="!!inlineEntity"
></claim-result-search-form>
</div>
<div *ngIf="showOptions.show=='project'">
<claim-projects-search-form [selectedProjects]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions"
[centerAlign]="!!inlineEntity"
></claim-projects-search-form>
</div>
<div *ngIf="showOptions.show=='context'">
<claim-contexts-search-form [communityId]=communityId [results]="results" [sources]="sources"
[properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions"
[centerAlign]="!!inlineEntity"
></claim-contexts-search-form>
</div>
<div *ngIf="showOptions.show=='result'">
<claim-result-search-form [selectedResults]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'"
[basketLimit]="basketLimit" [showOptions]="showOptions"
[centerAlign]="!!inlineEntity"
></claim-result-search-form>
</div>
</div>
<!-- Basket-->
<div *ngIf="showOptions.show != 'claim'" class="uk-width-1-3@m uk-flex-last@m uk-flex-first uk-margin-medium-top">
<div id="basket" uk-sticky="offset: 220; end: !*; media: @m" style="z-index: 0!important;">
<div class="uk-card uk-card-default linkingBasket">
<div class="uk-card-body uk-padding-small">
<div>
<ng-container *ngIf="inlineEntity">
<div *ngIf="claimsProperties.INLINE_ENTITY.show" class="uk-margin-small-bottom">
<div class="uk-text-emphasis uk-text-bolder">{{claimsProperties.BASKET.source_title}}</div>
<claim-selected-results [results]="[inlineEntity]"
[localStoragePrefix]="localStoragePrefix+'sources'" class=""
[enableRemove]="false" type="source">
</claim-selected-results>
<!-- <div *ngIf="showOptions.show!='source' && showOptions.show != 'claim' && showOptions.linkToEntities.length > 1">-->
<!-- <mat-form-field class="matSelectionFormField">-->
<!-- <mat-label>Sort by:</mat-label>-->
<!-- <mat-select [(ngModel)]="showOptions.show" class="uk-width-auto uk-text-bold matSelection"-->
<!-- *ngIf="showOptions.linkToEntities.length > 1"-->
<!-- [disableOptionCentering]="true"-->
<!-- panelClass="matSelectionPanel">-->
<!-- <mat-option *ngIf="showOptions.linkToEntities.indexOf('project')!=-1 "-->
<!-- value="project">PROJECTS</mat-option>-->
<!-- <mat-option *ngIf="showOptions.linkToEntities.indexOf('result')!=-1 " value="result">RESEARCH-->
<!-- RESULTS</mat-option>-->
<!-- <mat-option *ngIf="showOptions.linkToEntities.indexOf('context')!=-1 " value="context">COMMUNITIES-->
<!-- </mat-option>-->
<!-- </mat-select>-->
<!-- </mat-form-field>-->
<!-- </div>-->
<span *ngIf="showOptions.show!='source' && showOptions.show != 'claim' && showOptions.linkToEntities.length > 1"
class="uk-flex-inline uk-flex-middle uk-width-3-5@m uk-width-1-1@s">
<span class="uk-width-1-4 uk-text-muted uk-text-large">LINK TO </span>
<mat-select [(ngModel)]="showOptions.show" class="uk-width-3-4@m matSelection"
*ngIf="showOptions.linkToEntities.length > 1"
[disableOptionCentering]="true"
panelClass="matSelectionPanel">
<mat-option *ngIf="showOptions.linkToEntities.indexOf('project')!=-1 "
value="project">PROJECTS</mat-option>
<mat-option *ngIf="showOptions.linkToEntities.indexOf('result')!=-1 " value="result">RESEARCH
RESULTS</mat-option>
<mat-option *ngIf="showOptions.linkToEntities.indexOf('context')!=-1 " value="context">COMMUNITIES
</mat-option>
</mat-select>
</span>
<span *ngIf="showOptions.show!='source' && showOptions.show != 'claim' && showOptions.linkToEntities.length ==1">
<span>LINK TO </span>
<span class=" uk-width-auto uk-text-bold">
<span *ngIf="showOptions.linkToEntities.indexOf('project')!=-1 "
value="project">PROJECTS</span>
<span *ngIf="showOptions.linkToEntities.indexOf('result')!=-1 " value="result">RESEARCH
RESULTS</span>
<span *ngIf="showOptions.linkToEntities.indexOf('context')!=-1 " value="context">COMMUNITIES
</span>
</span>
</span>
<span *ngIf="showOptions.show=='source'" class="uk-text-bold">
ADD LINKING SOURCES
</span>
</div>
<div *ngIf="showOptions.show=='source'">
<claim-result-search-form [selectedResults]="sources" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'sources'" [basketLimit]="basketLimit"
></claim-result-search-form>
</div>
<div *ngIf="showOptions.show=='project'">
<claim-projects-search-form [selectedProjects]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'" [basketLimit]="basketLimit"
></claim-projects-search-form>
</div>
<div *ngIf="showOptions.show=='context'">
<claim-contexts-search-form [communityId]=communityId [results]="results" [sources]="sources"
[properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'" [basketLimit]="basketLimit"
></claim-contexts-search-form>
</div>
<div *ngIf="showOptions.show=='result'">
<claim-result-search-form [selectedResults]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'" [basketLimit]="basketLimit"
></claim-result-search-form>
</div>
</div>
<!-- Basket-->
<div *ngIf="showOptions.show != 'claim'" class="uk-width-1-3" style="" >
<div id="basket" uk-sticky=" offset: 130; top:#basketStickTop; bottom: #basketStickBottom;"
style="z-index: 0">
<h6 class="linksbasketheader uk-margin-bottom uk-text-bold">
LINKS BASKET
</h6>
<div class="linksbasket uk-inline uk-width-1-1" style="">
<div *ngIf="inlineEntity == null">
<div class="linksbaskettitles uk-padding-small uk-animation-toggle"
(click)="showOptions.showBasketSources()"
[style.cursor]="(showOptions.show!='source'?'pointer':'default')">
<div class="uk-h6 uk-margin-remove portal-color" >
SOURCES ({{(sources.length) | number}})
<span *ngIf="showOptions.show!='source' && !showOptions.basketShowSources"
class="uk-icon"><svg width="20"
height="20"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
icon="chevron-left"
ratio="1"><polyline
fill="none" stroke="#000" stroke-width="1.03" points="13 16 7 10 13 4"></polyline></svg></span>
<span *ngIf="showOptions.show!='source' && showOptions.basketShowSources"
class="uk-icon"><svg width="20"
height="20"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
icon="chevron-down"
ratio="1"><polyline
fill="none" stroke="#000" stroke-width="1.03" points="16 7 10 13 4 7"></polyline></svg></span>
</div>
Research results to link
</div>
<div *ngIf="claimsProperties.INLINE_ENTITY.show" class="uk-padding-small uk-padding-remove-horizontal"><hr class="uk-margin-remove"/></div>
<div *ngIf="showOptions.basketShowSources"
class=" uk-margin-remove-top uk-height-medium uk-overflow-auto ">
<div class="uk-background-muted uk-padding-small " style="min-height: 17px;">
<div *ngIf="showOptions.show != 'source'" class="uk-text-center">
<a (click)="showOptions.showSource()">
<!--span class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="plus" ratio="1"><rect x="9" y="1" width="1" height="17"></rect><rect x="1" y="9" width="17" height="1"></rect></svg></span-->
Edit sources</a>
</div>
<start-over *ngIf="showOptions.show == 'source' && (sources.length)> 0"
[results]="sources"
[localStoragePrefix]="localStoragePrefix+'sources'"
message="all sources" class="uk-float-right"></start-over>
<bulk-claim *ngIf="showOptions.show == 'source'" [results]="sources"
[properties]=properties
[localStoragePrefix]="localStoragePrefix+'sources'" [basketLimit]="basketLimit"
>
</bulk-claim>
</div>
<div class="uk-animation-slide-top-small uk-padding-small">
<div *ngIf="(sources.length) == 0 " class="uk-alert no-selected-message uk-text-center">
No Sources added yet. Start adding sources from the left panel. Or upload a DOI's CSV file.
</div>
<div *ngIf="sources.length >= basketLimit "
class="uk-alert uk-alert-warning uk-text-center">
Basket reached the size limit. No more sources can be added.
</div>
<claim-selected-results [results]="sources"
[localStoragePrefix]="localStoragePrefix+'sources'" class=""
[enableRemove]="showOptions.show == 'source'">
</claim-selected-results>
<div id="test1"></div>
</div>
</div>
</div>
<div *ngIf="inlineEntity"
class="linkInlineEntity uk-padding-small">
<div class="uk-h6 linkInlineEntity uk-margin-small-bottom ">
SOURCE
</div>
<claim-title [entity]="inlineEntity" [slice]="true" [sliceSize]="45"
[shortVersion]="true"></claim-title>
<div class="uk-margin-small-top">
<div class="uk-text-emphasis uk-text-bolder">{{claimsProperties.BASKET.target_title}} <span *ngIf="results.length> 0">({{(results.length) | number}})</span></div>
<ng-container *ngTemplateOutlet="destinations_basket"></ng-container>
<span class="uk-label custom-label linkInlineEntityLabel"
title="Type">{{inlineEntity.type}}</span>
<span *ngIf="inlineEntity.project">
<span class="uk-label custom-label linkInlineEntityLabel"
title="Funder">{{inlineEntity.project.funderName}}</span>
<!-- <span class="uk-label custom-label " title="Type">{{inlineEntity.type}}</span>-->
</span>
<span *ngIf="inlineEntity.result">
<span class="uk-label custom-label linkInlineEntityLabel "
title="Access mode">{{inlineEntity.result.accessRights}}</span>
</span>
</div>
</ng-container>
<ng-container *ngIf="!inlineEntity">
<ul class="uk-tab" uk-tab>
<li [class.uk-active]="showOptions.basketShowSources"
(click)="showOptions.basketswitchToSources()">
<a>
Sources to link ({{(sources.length) |number}})
</a>
</li>
<li [class.uk-disabled]="sources.length == 0"
[class.uk-active]="showOptions.basketShowLinksTo">
<a (click)="showOptions.basketswitchToLinkTo()">Link to <span
*ngIf="results.length> 0">({{(results.length) | number}})</span>
</a>
</li>
</ul>
<div *ngIf="showOptions.basketShowSources">
<div class="uk-height-max-medium uk-overflow-auto uk-padding uk-padding-remove-left uk-padding-remove-vertical">
<div *ngIf="showOptions.show == 'source'" class="uk-padding-small uk-padding-remove-horizontal" style="min-height:17px;">
<start-over *ngIf="showOptions.show == 'source' && sources.length> 0"
[results]="sources"
[localStoragePrefix]="localStoragePrefix+'sources'"
message="all sources" class="uk-float-right"></start-over>
<bulk-claim *ngIf="showOptions.show == 'source'" [results]="sources"
[properties]=properties
[localStoragePrefix]="localStoragePrefix+'sources'" [basketLimit]="basketLimit"
>
</bulk-claim>
</div>
<div *ngIf="showOptions.show !='source'">
<div class=" linksbaskettitles uk-padding-small uk-animation-toggle" (click)="showOptions.basketShowLinksTo=!showOptions.basketShowLinksTo;
showOptions.basketShowSources=!showOptions.basketShowLinksTo ">
<div *ngIf="!inlineEntity"> <!--Enable toggle -->
<span class="uk-h6 uk-margin-remove portal-color" >
LINK TO ({{(results.length) | number}})
<span *ngIf="!showOptions.basketShowLinksTo" class="uk-icon"><svg width="20"
height="20"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
icon="chevron-left"
ratio="1"><polyline
fill="none" stroke="#000" stroke-width="1.03"
points="13 16 7 10 13 4"></polyline></svg></span>
<span *ngIf="showOptions.basketShowLinksTo" class="uk-icon"><svg width="20"
height="20"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
icon="chevron-down"
ratio="1"><polyline
fill="none" stroke="#000" stroke-width="1.03"
points="16 7 10 13 4 7"></polyline></svg></span>
</span>
</div>
<div *ngIf="inlineEntity"> <!--Inline Entity - no toggle -->
<span class="uk-h6 uk-margin-remove portal-color">
LINK TO ({{(results.length) | number}})
</span>
</div>
</div>
<div class="uk-padding-small uk-padding-remove-horizontal">
<div *ngIf="sources.length == 0" class="uk-text-center uk-text-meta">
No Sources added yet. Start adding sources from the left panel. Or upload a DOI's CSV file.
</div>
<div *ngIf="sources.length >= basketLimit " class="uk-alert uk-alert-warning uk-text-center">
Basket reached the size limit. No more sources can be added.
</div>
<claim-selected-results *ngIf="sources.length > 0" [results]="sources"
[localStoragePrefix]="localStoragePrefix+'sources'" class=""
[enableRemove]="true" type="source">
</claim-selected-results>
</div>
<div class="linksBasketSubtitles">
Entities to link with the sources
</div>
</div>
<div *ngIf="showOptions.basketShowLinksTo">
<div class="uk-height-max-medium uk-overflow-auto uk-padding uk-padding-remove-left uk-padding-remove-vertical">
<ng-container *ngTemplateOutlet="destinations_basket"></ng-container>
<div *ngIf="showOptions.basketShowLinksTo"
class="uk-height-medium uk-overflow-auto">
<div *ngIf=" (results.length)> 0 || showOptions.show=='result'"
class="uk-background-muted uk-padding-small " style="min-height: 17px;">
<start-over *ngIf=" (results.length)> 0"
[results]="results" [localStoragePrefix]="localStoragePrefix+'results'"
message="all results (projects, communities, research results)"
class="uk-float-right"></start-over>
<bulk-claim *ngIf="showOptions.show=='result'" [results]="results" [properties]=properties
[localStoragePrefix]="localStoragePrefix+'results'" [basketLimit]="basketLimit"></bulk-claim>
</div>
<div class="uk-padding-small uk-animation-slide-top-small">
<div *ngIf="results.length >= basketLimit "
class="uk-alert uk-alert-warning uk-text-center">
Basket reached the size limit. No more entities can be added.
</div>
<claim-selected-results sectionTitle="Selected Results" [results]="results"
[localStoragePrefix]="localStoragePrefix+'results'">
</claim-selected-results>
<div *ngIf="(results.length) == 0 " class="uk-alert no-selected-message uk-text-center">
No entities to link with the sources. Start adding entities from the left panel.
</div>
</div>
</div>
</ng-container>
</div>
</div>
<div *ngIf="showOptions.show=='source'"
[class]="((sources.length)>0?'linksbaskettitlesPortalColor ':'uk-disabled')+ ' linksbaskettitles uk-padding-small'"
(click)="openSelectionModal(); ">
<!--show = linkTo; basketShowSources=false;
basketShowLinksTo=true;-->
<div class="uk-h6 uk-margin-remove portal-color">CONTINUE TO - LINK TO <span
*ngIf="results.length > 0">({{(results.length) | number}})</span>
<span class="uk-icon uk-float-right uk-text-bold uk-margin-small-right">
<svg width="30" height="30" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
icon="chevron-right" ratio="1.5"><polyline fill="none" stroke="#000" stroke-width="1.03"
points="7 4 13 10 7 16"></polyline></svg>
</span>
</div>
<div class="linksBasketSubtitles">
Entities to link with the sources
</div>
</div>
<div *ngIf="showOptions.show!='source'"
[class]="((results.length)>0?'linksbaskettitlesPortalColor ':'uk-disabled')+ ' linksbaskettitles uk-margin-small-top uk-padding-small'"
style="height:auto !important; " (click)="showOptions.show = 'claim'; scrollUp();">
<div class="uk-margin-remove portal-color uk-text-center">
FINISH LINKING
<span class="uk-icon uk-float-right uk-text-bold uk-margin-small-right">
<svg width="30" height="30" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
icon="chevron-right" ratio="1.5"><polyline fill="none" stroke="#000" stroke-width="1.03"
points="7 4 13 10 7 16"></polyline></svg>
</span>
</div>
</div>
</div>
<div *ngIf="showOptions.show == 'source'"
class="uk-card-footer uk-flex uk-flex-center clickable"
[class.uk-tile-primary]="sources.length > 0"
[class.uk-background-muted]="sources.length == 0"
[class.uk-disabled]="sources.length == 0"
(click)="stepHasChanged('target')">
<button class="uk-flex uk-flex-middle uk-button uk-button-text"
[class.uk-disabled]="sources.length == 0" [disabled]="sources.length == 0">
<icon name="link" visuallyHidden="link" [flex]="true"></icon>
<div class="uk-width-expand uk-margin-small-left">STEP 2 - LINK SOURCES TO ENTITIES</div>
</button>
</div>
<div *ngIf="showOptions.show != 'source'"
class="uk-card-footer uk-flex uk-flex-center clickable"
[class.uk-tile-primary]="results.length > 0"
[class.uk-background-muted]="results.length == 0"
[class.uk-disabled]="results.length == 0" (click)="stepHasChanged('claim')">
<button class="uk-flex uk-flex-middle uk-button uk-button-text"
[class.uk-disabled]="results.length == 0" [disabled]="results.length == 0">
<icon *ngIf="inlineEntity" name="link" visuallyHidden="link" [flex]="true"></icon>
<div class="uk-width-expand uk-margin-small-left"><ng-container *ngIf="!inlineEntity">STEP {{inlineEntity ? '2' : '3'}} - </ng-container>SUMMARISE</div>
</button>
</div>
</div>
<div id="basketStickBottom"></div>
<helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0" [texts]="pageContents['bottom']"></helper>
</div>
<!-- <helper position="right" styleName=" uk-width-1-5"></helper>-->
</div>
<!-- <helper position="right" styleName=" uk-width-1-5"></helper>-->
<!-- <helper position="bottom"></helper>-->
</div>
<helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0"
[texts]="pageContents['bottom']"></helper>
</div>
</div>
</div>
</div>
</div>
<div id="pageBottom"></div>
<modal-alert (alertOutput)="closeSelectionModal($event)">
<div class="uk-grid uk-text-center uk-padding uk-child-width-1-3">
<div *ngIf="showOptions.linkToEntities.indexOf('project')!=-1 " (click)="closeSelectionModal('project')" class="clickable">
<button class="uk-icon-button">
<span class="uk-icon">
<svg height="20" icon="album" ratio="1" viewBox="0 0 20 20" width="20"
xmlns="http://www.w3.org/2000/svg"><rect height="1" width="10" x="5" y="2"></rect><rect
height="1" width="14" x="3" y="4"></rect><rect fill="none" height="11" stroke="#000"
width="17" x="1.5"
y="6.5"></rect></svg></span>
</button>
<div>Projects</div>
</div>
<div *ngIf="showOptions.linkToEntities.indexOf('result')!=-1 " (click)="closeSelectionModal('result')"
class="clickable">
<button class="uk-icon-button">
<span class="uk-icon">
<svg height="20" icon="copy" ratio="1" viewBox="0 0 20 20" width="20"
xmlns="http://www.w3.org/2000/svg"><rect fill="none" height="16" stroke="#000"
width="12" x="3.5" y="2.5"></rect><polyline
fill="none" points="5 0.5 17.5 0.5 17.5 17" stroke="#000"></polyline></svg>
</span>
</button>
<div>Research results</div>
</div>
<div *ngIf="showOptions.linkToEntities.indexOf('context')!=-1 " (click)="closeSelectionModal('context')"
class="clickable">
<button class="uk-icon-button">
<span class="uk-icon">
<svg height="20" icon="users" ratio="1" viewBox="0 0 20 20" width="20"
xmlns="http://www.w3.org/2000/svg"><circle cx="7.7" cy="8.6" fill="none" r="3.5"
stroke="#000" stroke-width="1.1"></circle><path
d="M1,18.1 C1.7,14.6 4.4,12.1 7.6,12.1 C10.9,12.1 13.7,14.8 14.3,18.3" fill="none"
stroke="#000" stroke-width="1.1"></path><path
d="M11.4,4 C12.8,2.4 15.4,2.8 16.3,4.7 C17.2,6.6 15.7,8.9 13.6,8.9 C16.5,8.9 18.8,11.3 19.2,14.1"
fill="none" stroke="#000" stroke-width="1.1"></path></svg></span>
</button>
<div>Communities</div>
</div>
</div>
</modal-alert>
</div>
<modal-alert (alertOutput)="closeSelectionModal($event)" >
<div class="uk-grid uk-text-center uk-margin-expand uk-padding uk-child-width-1-3">
<div *ngIf="showOptions.linkToEntities.indexOf('project')!=-1 " (click)="closeSelectionModal('project')"
style="cursor:pointer;">
<button class="uk-icon-button portal-button">
<span class="uk-icon">
<svg height="20" icon="album" ratio="1" viewBox="0 0 20 20" width="20"
xmlns="http://www.w3.org/2000/svg"><rect height="1" width="10" x="5" y="2"></rect><rect
height="1" width="14" x="3" y="4"></rect><rect fill="none" height="11" stroke="#000"
width="17" x="1.5" y="6.5"></rect></svg></span>
</button>
<div>Projects</div>
</div>
<div *ngIf="showOptions.linkToEntities.indexOf('result')!=-1 " (click)="closeSelectionModal('result')"
style="cursor:pointer;">
<button class="uk-icon-button portal-button">
<span class="uk-icon">
<svg height="20" icon="copy" ratio="1" viewBox="0 0 20 20" width="20"
xmlns="http://www.w3.org/2000/svg"><rect fill="none" height="16" stroke="#000"
width="12" x="3.5" y="2.5"></rect><polyline
fill="none" points="5 0.5 17.5 0.5 17.5 17" stroke="#000"></polyline></svg></span>
</button>
<div>Research results</div>
</div>
<div *ngIf="showOptions.linkToEntities.indexOf('context')!=-1 " (click)="closeSelectionModal('context')"
style="cursor:pointer;">
<button class="uk-icon-button portal-button">
<span class="uk-icon">
<svg height="20" icon="users" ratio="1" viewBox="0 0 20 20" width="20"
xmlns="http://www.w3.org/2000/svg"><circle cx="7.7" cy="8.6" fill="none" r="3.5"
stroke="#000" stroke-width="1.1"></circle><path
d="M1,18.1 C1.7,14.6 4.4,12.1 7.6,12.1 C10.9,12.1 13.7,14.8 14.3,18.3" fill="none"
stroke="#000" stroke-width="1.1"></path><path
d="M11.4,4 C12.8,2.4 15.4,2.8 16.3,4.7 C17.2,6.6 15.7,8.9 13.6,8.9 C16.5,8.9 18.8,11.3 19.2,14.1"
fill="none" stroke="#000" stroke-width="1.1"></path></svg></span>
</button>
<div>Communities</div>
</div>
</div>
</modal-alert>

View File

@ -1,4 +1,4 @@
import {ChangeDetectorRef, Component, Input, ViewChild} from '@angular/core';
import {Component, Input, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Meta, Title} from '@angular/platform-browser';
import {EnvProperties} from '../../utils/properties/env-properties';
@ -11,21 +11,17 @@ import {HelperService} from "../../utils/helper/helper.service";
import {PiwikService} from "../../utils/piwik/piwik.service";
import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {StringUtils} from "../../utils/string-utils.class";
import {RouterHelper} from "../../utils/routerHelper.class";
import { Location } from '@angular/common';
import {LoginErrorCodes} from "../../login/utils/guardHelper.class";
import {UserManagementService} from "../../services/user-management.service";
import {ClaimsProperties} from "../claim-utils/claims.properties";
declare var UIkit:any;
@Component({
selector: 'linking-generic',
templateUrl: 'linkingGeneric.component.html'
})
export class LinkingGenericComponent {
@Input() pageTitle: string = "Create links between research objects";
@Input() piwikSiteId = null;
@Input() pageTitle: string = " Create links between research objects";
piwiksub:any;
@Input() communityId:string= null;
@ -42,43 +38,28 @@ export class LinkingGenericComponent {
// show linkToEntities /values: result, project, context
@Input() sources:ClaimEntity[] =[];
properties:EnvProperties = properties;
public openaireEntities = OpenaireEntities;
properties:EnvProperties;
@Input() localStoragePrefix:string = "linking_";
url=null;
@ViewChild(AlertModal) alert;
public pageContents = null;
@Input() breadcrumbs: Breadcrumb[] = [];
public routerHelper: RouterHelper = new RouterHelper();
@Input() claimsProperties:ClaimsProperties = new ClaimsProperties();
constructor (private _router: Router, private route: ActivatedRoute, private entitySearch:EntitiesSearchService,
private _meta: Meta, private _title: Title, private _piwikService:PiwikService,
private seoService: SEOService, private helper: HelperService, private cdr: ChangeDetectorRef,
private location: Location, private userManagementService: UserManagementService) {
private seoService: SEOService, private helper: HelperService ) {
}
subscriptions = [];
ngOnInit() {
/* if(!this.claimsProperties){
this.claimsProperties = new ClaimsProperties();
}*/
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
if (!user) {
this.saveStateAndRedirectLogin();
}
}));
if(this.breadcrumbs.length === 0) {
this.breadcrumbs.push({name: 'home', route: '/'});
this.breadcrumbs.push({name: "Link", route: null});
}
this.showOptions.show = 'source';
this.showOptions.initSelectOptions(this.claimsProperties);
if(this.inlineEntity){
this.showOptions.showLinkTo();
// this.showOptions.basketShowLinksTo = true;
this.showOptions.basketShowSources = false;
this.showOptions.basketShowLinksTo = true;
this.showOptions.show = this.showOptions.linkTo;
}
this.properties = properties;
this.url = this.properties.domain + this.properties.baseLink+this._router.url;
var description = "Linking is a functionality provided by OpenAIRE, in order to link research results with a project, a research community or other research results.";
@ -88,13 +69,13 @@ export class LinkingGenericComponent {
this.seoService.createLinkForCanonicalURL(this.url, false);
this.subscriptions.push(this._piwikService.trackView(this.properties, this.pageTitle).subscribe());
if(this.properties.enablePiwikTrack && (typeof document !== 'undefined')){
this.subscriptions.push(this._piwikService.trackView(this.properties, this.pageTitle, this.piwikSiteId).subscribe());
}
if(properties.adminToolsPortalType !== "explore") {
this.helper.getPageHelpContents(this.properties, this.communityId, this._router.url).subscribe(contents => {
this.pageContents = contents;
})
}
if( typeof localStorage !== 'undefined') {
@ -106,11 +87,6 @@ export class LinkingGenericComponent {
if(localStorage.getItem(this.localStoragePrefix + "sources")){
this.sources = JSON.parse(localStorage.getItem(this.localStoragePrefix + "sources"));
}
if(localStorage.getItem(this.localStoragePrefix + "claimsJob")){
let job = JSON.parse(localStorage.getItem(this.localStoragePrefix + "claimsJob"));
if(job.status != "COMPLETE"){
this.showOptions.show = 'claim'; }
}
}
}
@ -165,78 +141,4 @@ export class LinkingGenericComponent {
private updateUrl(url:string) {
this._meta.updateTag({content:url},"property='og:url'");
}
stepHasChanged(stepId){
if(stepId == 'source'){
// console.log("show source")
this.showOptions.showSource();
}else if(stepId == 'target'){
// console.log("show target")
this.showOptions.show = this.showOptions.linkTo;
this.showOptions.showLinkTo();
}else if(stepId == 'claim'){
// console.log("show target")
this.showOptions.show = 'claim';
}
this.cdr.detectChanges();
HelperFunctions.scroll(true);
// console.log('stepHasChanged', stepId, this.showOptions.show)
}
stepStatus(stepId){
if(stepId == 'source'){
if(this.showOptions.show == 'source'){
return 'active';
}else if(this.sources.length > 0){
return 'done';
}else{
return 'default';
}
}else if(stepId=='target'){
if(this.showOptions.show != 'source' && this.showOptions.show != 'claim'){
return 'active';
}else if(this.results.length > 0){
return 'done';
}else if(this.sources.length == 0 && !this.inlineEntity){
return 'disabled';
}else{
return 'default';
}
}else if(stepId=='claim'){
if(this.showOptions.show == 'claim'){
return 'active';
}else if(this.results.length > 0 && (this.inlineEntity || this.sources.length > 0)){
return 'default';
}else if(!(this.results.length > 0 && (this.inlineEntity || this.sources.length > 0))){
return 'disabled';
}
}
}
private getEntityName (entityType:string, plural:boolean) {
return StringUtils.getEntityName(entityType, plural);
}
back(): void {
if(typeof document !== 'undefined') {
this.location.back();
}
}
saveStateAndRedirectLogin() {
if (this.results != null) {
localStorage.setItem(this.localStoragePrefix + "results", JSON.stringify(this.results));
}
if (this.sources != null) {
localStorage.setItem(this.localStoragePrefix + "sources", JSON.stringify(this.sources));
}
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
}
}

View File

@ -1,45 +1,41 @@
import {NgModule} from '@angular/core';
import {MatSelectModule} from "@angular/material/select";
import { NgModule } from '@angular/core';
import { MatSelectModule } from "@angular/material/select";
import {SharedModule} from '../../../openaireLibrary/shared/shared.module';
import { SharedModule } from '../../shared/shared.module';
import {SelectedProjectsModule} from './selected/selectedProjects.module';
import {SelectedContextsModule} from './selected/selectedContexts.module';
import {SelectedPublicationsModule} from './selected/selectedResults.module';
import {LinkingGenericComponent} from './linkingGeneric.component';
import {StartOverModule} from '../claim-utils/startOver.module';
import {LoginGuard} from'../../login/loginGuard.guard';
import {PreviousRouteRecorder} from '../../utils/piwik/previousRouteRecorder.guard';
import {ClaimContextSearchFormModule} from '../claim-utils/claimContextSearchForm.module';
import {ClaimProjectsSearchFormModule} from '../claim-utils/claimProjectSearchForm.module';
import {BulkClaimModule} from './bulkClaim/bulkClaim.module';
import {ClaimResultSearchFormModule} from '../claim-utils/claimResultSearchForm.module';
import {HelperModule} from '../../utils/helper/helper.module';
import {IsRouteEnabled} from '../../error/isRouteEnabled.guard';
import {Schema2jsonldModule} from '../../sharedComponents/schema2jsonld/schema2jsonld.module';
import {SEOServiceModule} from '../../sharedComponents/SEO/SEOService.module';
import { SEOServiceModule } from '../../sharedComponents/SEO/SEOService.module';
import {MetadataPreviewModule} from './selected/metadataPreview.module';
import {ClaimEntitiesMetadataModule} from "./selected/ClaimEntitiesMetadata.module";
import {AlertModalModule} from '../../utils/modal/alertModal.module';
import {BreadcrumbsModule} from "../../utils/breadcrumbs/breadcrumbs.module";
import {StepperModule} from "../../sharedComponents/stepper/stepper.module";
import {IconsModule} from "../../utils/icons/icons.module";
import {IconsService} from "../../utils/icons/icons.service";
import {link} from "../../utils/icons/icons";
import {PiwikServiceModule} from "../../utils/piwik/piwikService.module";
@NgModule({
imports: [
SharedModule, SelectedProjectsModule, SelectedContextsModule,
SelectedPublicationsModule,
StartOverModule,
StartOverModule,
ClaimContextSearchFormModule, ClaimProjectsSearchFormModule, BulkClaimModule, ClaimResultSearchFormModule,
HelperModule, Schema2jsonldModule, SEOServiceModule, MetadataPreviewModule, ClaimEntitiesMetadataModule, AlertModalModule,
MatSelectModule, BreadcrumbsModule, StepperModule, IconsModule
PiwikServiceModule,
MatSelectModule
],
providers: [],
providers:[LoginGuard, PreviousRouteRecorder, IsRouteEnabled],
declarations: [
LinkingGenericComponent
], exports: [
LinkingGenericComponent]
], exports:[
LinkingGenericComponent ]
})
export class LinkingGenericModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([link]);
}
}
export class LinkingGenericModule { }

View File

@ -1,23 +1,15 @@
import {NgModule} from '@angular/core';
import {SharedModule} from '../../../../openaireLibrary/shared/shared.module';
import {SharedModule} from '../../../shared/shared.module';
import {ClaimEntityTitleComponent} from "./ClaimEntityTitle.component";
import {ClaimEntityResultMetadataComponent} from "./ClaimEntityResultMetadata.component";
import {ClaimEntityProjectMetadataComponent} from "./ClaimEntityProjectMetadata.component";
import {IconsService} from "../../../utils/icons/icons.service";
import {coins} from "../../../utils/icons/icons";
import {IconsModule} from "../../../utils/icons/icons.module";
@NgModule({
imports: [
SharedModule,
IconsModule
SharedModule
],
declarations: [
ClaimEntityTitleComponent, ClaimEntityResultMetadataComponent, ClaimEntityProjectMetadataComponent
], exports:[ ClaimEntityTitleComponent, ClaimEntityResultMetadataComponent, ClaimEntityProjectMetadataComponent]
})
export class ClaimEntitiesMetadataModule {
constructor(private _iconsService:IconsService) {
this._iconsService.registerIcons([coins])
}
}
export class ClaimEntitiesMetadataModule { }

View File

@ -1,11 +0,0 @@
@import (reference) "~src/assets/openaire-theme/less/_import-variables";
.claim-entity-metadata {
& > *:not(:last-child):not(.other-separator)::after {
content: "\2022";
font-weight: normal;
margin-left: @global-xsmall-margin;
margin-right: @global-xsmall-margin;
}
}

View File

@ -3,37 +3,25 @@ import {ClaimEntity} from '../../claim-utils/claimHelper.class';
@Component({
selector: 'claim-project-metadata',
template: `
<ng-container *ngIf="entity.type == 'project' && entity.project">
<div *ngIf="!shortVersion" class="claim-entity-metadata uk-flex-inline uk-flex-wrap uk-text-xsmall uk-text-emphasis"
[class.uk-margin-xsmall-top]="!shortVersion">
<span class="uk-text-capitalize">
{{entity.type == 'project' && entity.project.code == 'unidentified'?'funder':entity.type}}
</span>
<span *ngIf="entity.project.startDate || entity.project.endDate">
{{(entity.project.startDate) ? entity.project.startDate : 'Unknown'}}{{'-' + ((entity.project.endDate) ? entity.project.endDate : 'Unknown')}}
</span>
template:
`
<div *ngIf="entity.type == 'project' && entity.project" class="uk-grid uk-margin-remove-top uk-text-small">
<div class="uk-width-1-2">
<div *ngIf="entity.project.funderName">
<span class="uk-text-muted">Funder </span>{{entity.project.funderName}}
</div>
</div>
<div *ngIf="shortVersion && entity.type == 'project' && entity.project.code == 'unidentified'" class="claim-entity-metadata uk-flex-inline uk-flex-wrap uk-text-xsmall uk-text-emphasis"
[class.uk-margin-xsmall-top]="!shortVersion">
<span class="uk-text-capitalize">
funder
</span>
</div>
<div *ngIf="entity.project.code!='unidentified'" class="uk-text-small uk-flex uk-flex-wrap" [style.grid-gap]="shortVersion?'0px':'10px'"
[class.uk-margin-small-top]="!shortVersion">
<div class="uk-width-1-2">
<div *ngIf="entity.project.code">
<span class="uk-text-meta">Project Code: </span>{{entity.project.code}}
<span class="uk-text-muted">GrandId </span>{{entity.project.code}}
</div>
<div *ngIf="entity.project.funderName || entity.project.funderShortname">
<span class="uk-text-meta">Funding: </span>{{entity.project.funderName?entity.project.funderName:entity.project.funderShortname}}
<div *ngIf=" !shortVersion && (entity.project.startDate || entity.project.endDate)">
<span
class="uk-text-muted">Duration </span>{{(entity.project.startDate) ? entity.project.startDate : 'Unknown'}}{{'-' + ((entity.project.endDate) ? entity.project.endDate : 'Unknown')}}
</div>
</div>
</ng-container>
`,
styleUrls: ['ClaimEntityMetadata.component.less']
</div>
`
})

View File

@ -3,38 +3,33 @@ import {ClaimEntity} from '../../claim-utils/claimHelper.class';
@Component({
selector: 'claim-result-metadata',
template: `
template:
`
<div *ngIf="entity.result">
<!-- display all existing data similar to entity-metadata -->
<div *ngIf="!shortVersion" class="claim-entity-metadata uk-flex-inline uk-flex-wrap uk-text-xsmall uk-text-emphasis uk-margin-xsmall-top">
<span class="uk-text-capitalize uk-text-italic">
{{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}}
</span>
<span *ngIf="entity.result.publisher!=null">
{{entity.result.publisher}}
</span>
<span *ngIf="entity.result.date">
<span [class]="(getProjectDurationMessage(entity)?'uk-text-warning':'')">{{entity.result.date}}</span>
</span>
<span *ngIf="entity.result.journal!=null">
{{entity.result.journal}}
</span>
<div *ngIf="entity.result.editors && entity.result.editors.length > 0">
{{sliceArray(entity.result.editors)}}
</div>
</div>
<div *ngIf="entity.result.authors && entity.result.authors.length > 0" class="uk-flex uk-flex-wrap uk-text-small uk-text-emphasis uk-text-italic"
[class.uk-margin-small-top]="!shortVersion">
<div *ngIf="entity.result.authors && entity.result.authors.length >0 " class="uk-text-small">
<span class="uk-text-muted">Authors </span>
{{sliceArray(entity.result.authors)}}
</div>
<div class="uk-text-small uk-margin-top">
<span *ngIf="getProjectDurationMessage(entity)" [class]="(getProjectDurationMessage(entity)?'uk-text-warning':'')">
{{getProjectDurationMessage(entity)}}
</span>
<div *ngIf="!shortVersion && entity.result.editors&& entity.result.editors.length > 0" class="uk-text-small">
<span class="uk-text-muted">Editors </span>
{{sliceArray(entity.result.editors)}}
</div>
<div *ngIf="!shortVersion" class="uk-grid uk-margin-remove uk-text-small">
<div class="uk-width-1-2 uk-padding-remove-left">
<span *ngIf="entity.result.publisher!=null"><span
class="uk-text-muted">Publisher</span> {{entity.result.publisher}}</span>
<span *ngIf="entity.result.journal!=null"><span
class="uk-text-muted">Journal</span> {{entity.result.journal}}</span>
</div>
<div class="uk-width-1-2">
<span *ngIf="entity.result.date"><span class="uk-text-muted">Published in </span> <span
[class]="(getProjectDurationMessage(entity)?'uk-text-warning':'')">{{entity.result.date}}</span></span>
<div [class]="(getProjectDurationMessage(entity)?'uk-text-warning':'')">{{getProjectDurationMessage(entity)}}
</div>
</div>
</div>
</div>
`,
styleUrls: ['ClaimEntityMetadata.component.less']
`
})

View File

@ -1,94 +1,66 @@
import {Component, Input} from '@angular/core';
import {ClaimEntity} from '../../claim-utils/claimHelper.class';
import {StringUtils} from "../../../utils/string-utils.class";
@Component({
selector: 'claim-title',
template: `
<div class="uk-grid uk-flex uk-flex-middle">
<span *ngIf="showIcon" class="uk-flex uk-margin-xsmall-right">
<icon *ngIf="entity.result" class=" uk-text-small uk-text-meta" name="insert_drive_file">
</icon>
<icon *ngIf="entity.project && entity.project.code !='unidentified'" class=" uk-text-small uk-text-meta" name="assignment_turned_in">
</icon>
<icon *ngIf="entity.project && entity.project.code =='unidentified'" class="uk-text-small uk-text-meta" name="coins" [ratio]="1.4">
</icon>
<icon *ngIf="entity.organization" class=" uk-text-small uk-text-meta" name="account_balance">
</icon>
<icon *ngIf="entity.type=='community'" class=" uk-text-small uk-text-meta" style="margin-right: 2px;" name="people">
</icon>
</span>
<div class="uk-width-expand multi-line-ellipsis lines-3" style="word-break: break-word;"
[class.uk-padding-remove-left]="showIcon" [class.uk-text-truncate]="shortVersion">
<div class="uk-margin-remove uk-text-break uk-inline-block"
[class.uk-h6]="!shortVersion" [class.uk-text-bold]="shortVersion">
<a *ngIf="entity.result && entity.result.url" target="_blank" [href]="entity.result.url"
class="uk-link uk-text-decoration-none uk-width-expand">
{{entity.title ? sliceString(entity.title) : '[No title available]'}}
template:
`
<span class="uk-text-bold">
<a *ngIf="entity.result && entity.result.url" target="_blank" [href]="entity.result.url"
class="uk-link">{{entity.title ? sliceString(entity.title) : '[No title available]'}}</a>
<span
*ngIf="(entity.result && !entity.result.url)">{{entity.title ? sliceString(entity.title) : '[No title available]'}}</span>
<span *ngIf="entity.type=='project' && entity.project">
<a *ngIf="entity.project && entity.project.url" target="_blank" [href]="entity.project.url"
class="uk-link">
<span *ngIf="!shortVersion">
{{(entity.project.acronym ? '[' + entity.project.acronym + '] ' : '') + entity.title}}
</span>
<span *ngIf="shortVersion">
{{(entity.project.acronym ? sliceString(entity.project.acronym):sliceString(entity.title))}}
</span>
</a>
<span *ngIf="(entity.result && !entity.result.url)">
{{entity.title ? sliceString(entity.title) : '[No title available]'}}
</span>
<span *ngIf="entity.type=='project' && entity.project && entity.project.code =='unidentified'">
<span *ngIf="!shortVersion">
{{(entity.project.funderShortname ? '[' + entity.project.funderShortname + '] ' : '') + entity.project.funderName}}
</span>
<span *ngIf="shortVersion">
{{sliceString(entity.project.funderName)}}
</span>
</span>
<span *ngIf="entity.type=='project' && entity.project && entity.project.code!='unidentified'">
<a *ngIf="entity.project && entity.project.url" target="_blank" [href]="entity.project.url"
class="uk-link uk-text-decoration-none uk-width-expand">
<span *ngIf="!shortVersion">
{{(entity.project.acronym ? '[' + entity.project.acronym + '] ' : '') + entity.title}}
</span>
<span *ngIf="shortVersion">
{{(entity.project.acronym ? sliceString(entity.project.acronym):sliceString(entity.title))}}
</span>
</a>
<span *ngIf="(entity.project && !entity.project.url)">
<span *ngIf="!shortVersion">
{{(entity.project.acronym ? '[' + entity.project.acronym + '] ' : '') + entity.title}}
</span>
<span *ngIf="shortVersion">
{{(entity.project.acronym ? sliceString(entity.project.acronym):sliceString(entity.title))}}
</span>
</span>
</span>
<span *ngIf="entity.type=='organization' && entity.organization">
{{sliceString(entity.title)}}
</span>
<span *ngIf="entity.type=='community' && entity.context">
<span *ngIf=" entity.context.community != entity.context.concept.label">
{{entity.context.community }} > {{entity.context.category}} >
</span>
<span>
{{entity.context.concept.label}}
</span>
</span>
</div>
</div>
</div>
<span
*ngIf="(entity.project && !entity.project.url)">
<span *ngIf="!shortVersion">
{{(entity.project.acronym ? '[' + entity.project.acronym + '] ' : '') + entity.title}}
</span>
<span *ngIf="shortVersion">
{{(entity.project.acronym ? sliceString(entity.project.acronym):sliceString(entity.title))}}
</span>
</span>
</span>
<span *ngIf="entity.type=='community' && entity.context">
<span *ngIf=" entity.context.community != entity.context.concept.label">
{{entity.context.community }} > {{entity.context.category}} >
</span>
<span> {{entity.context.concept.label}}</span>
</span>
</span>
`
})
export class ClaimEntityTitleComponent {
@Input() entity: ClaimEntity;
@Input() slice:boolean = false;
@Input() sliceSize:number = 45;
@Input() shortVersion: boolean = false;
@Input() showIcon: boolean = false;
ngOnInit() {
}
}
sliceString(mystr:string): string {
if(this.slice){
// return StringUtils.sliceString(mystr,this.sliceSize);
}
return mystr;
if(this.slice){
return StringUtils.sliceString(mystr,this.sliceSize);
}
return mystr;
}
}

View File

@ -1,314 +1,452 @@
<div class="uk-section uk-margin-small-top uk-padding-remove-top">
<div class="uk-container uk-container-large">
<div *ngIf="properties" class="uk-section uk-padding-remove-top">
<div class="uk-margin-top">
<div class="uk-grid" uk-grid>
<div class="uk-width-expand">
<div class="uk-card uk-card-default">
<div class="uk-card-body">
<div class="uk-grid uk-grid-divider uk-child-width-1-1@s" uk-grid [class.uk-child-width-1-2@m] = "claimsProperties.INLINE_ENTITY.show" >
<!-- Sources-->
<div *ngIf="claimsProperties.INLINE_ENTITY.show">
<div class=" uk-margin uk-animation-toggle">
<span class="uk-h6 "> {{claimsProperties.METADATA_PREVIEW.source_title}} ({{sources.length + (inlineEntity ? 1 : 0) | number}})
</span>
<a *ngIf="!inlineEntity" class="uk-float-right uk-text-small" (click)="showOptions.showSource() "> <span
uk-icon="pencil" class="uk-margin-xsmall-right"></span>{{claimsProperties.METADATA_PREVIEW.edit_source_title}}</a>
</div>
<ul *ngIf="inlineEntity" class="uk-list uk-animation-fade uk-list-divider">
<li>
<div class="uk-grid uk-text-small uk-margin-top">
<div class="uk-text-muted uk-width-1-2 uk-flex uk-flex-middle">
<span class="material-icons uk-text-small uk-text-meta">insert_drive_file</span>
{{(!inlineEntity.result) ? inlineEntity.type : ((inlineEntity.result && inlineEntity.result.source == 'openaire') ? inlineEntity.type : (inlineEntity.result && inlineEntity.result.source + ' result'))}}
</div>
<div *ngIf="inlineEntity.errorMessages.length > 0"
class="uk-text-danger uk-width-1-2"> Link couldn't be saved
</div>
</div>
<!-- <div class="uk-text-muted">-->
<!-- {{(!inlineEntity.result) ? inlineEntity.type : ((inlineEntity.result && inlineEntity.result.source == 'openaire') ? inlineEntity.type : (inlineEntity.result && inlineEntity.result.source + ' result'))}}-->
<!-- </div>-->
<div class="">
<claim-title [shortVersion]="true" [entity]="inlineEntity" [showIcon]="false"></claim-title>
</div>
<claim-result-metadata [entity]="inlineEntity"></claim-result-metadata>
<claim-project-metadata [entity]="inlineEntity"></claim-project-metadata>
</li>
</ul>
<div *ngIf="!inlineEntity && sources.length == 0 ">
<div class="uk-alert dangerBorder no-selected-message uk-text-center">
<span class="uk-text-bold uk-text-danger"> SOURCES cannot be empty.</span><br>
Start by adding your linking sources first, go to <a (click)="showOptions.showSource() "
class="uk-link">
step 1</a>.
</div>
</div>
<ul *ngIf="!inlineEntity && sources.length > 0 " class="uk-list uk-animation-fade uk-list-divider">
<li *ngFor=" let entity of sources ">
<div class="uk-grid uk-text-small uk-margin-top">
<!-- <div class="uk-text-muted uk-width-1-2 uk-flex uk-flex-middle">
<span class="material-icons uk-text-small uk-text-meta">insert_drive_file</span>
{{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}}
</div> -->
<div *ngIf="entity.errorMessages.length > 0"
class="uk-text-danger uk-width-1-2"> Link couldn't be saved
</div>
</div>
<div class="uk-grid uk-margin-remove-top uk-margin-bottom">
<div class="uk-width-expand ">
<claim-title [shortVersion]="true" [entity]="entity" [showIcon]="false"></claim-title>
<claim-result-metadata [entity]="entity"></claim-result-metadata>
<claim-project-metadata [entity]="entity"></claim-project-metadata>
<div *ngIf="entity.result && entity.result.source && entity.result.source!='openaire' "
class="uk-grid uk-margin-remove-left uk-margin-small-top uk-text-small">
<div class="uk-width-1-2 uk-padding-remove-left">
<!-- <span class="uk-text-muted">Type </span>-->
<!-- <mat-select [(ngModel)]="entity.type" name="{{'select_type_'+entity.id}}"-->
<!-- class="uk-select uk-width-small matSelection"-->
<!-- [disableOptionCentering]="true"-->
<!-- panelClass="entitiesSelectionPanel">-->
<!-- <mat-option [value]="'publication'"-->
<!-- (click)="onTypeChanged('publication',entity, false)">Publication-->
<!-- </mat-option>-->
<!-- <mat-option [value]="'dataset'"-->
<!-- (click)="onTypeChanged('dataset',entity, false)">Research data-->
<!-- </mat-option>-->
<!-- <mat-option [value]="'software'" (click)="onTypeChanged('software',entity, false)">Software-->
<!-- </mat-option>-->
<!-- <mat-option [value]="'other'"-->
<!-- (click)="onTypeChanged('other',entity, false)">Other research product-->
<!-- </mat-option>-->
<!-- </mat-select>-->
<mat-form-field class="matSelectionFormField">
<mat-label>Type</mat-label>
<mat-select [(ngModel)]="entity.type" name="{{'select_type_'+entity.id}}"
class="matSelection"
[disableOptionCentering]="true"
panelClass="entitiesSelectionPanel">
<mat-option [value]="'publication'"
(click)="onTypeChanged('publication',entity, false)">Publication
</mat-option>
<mat-option [value]="'dataset'"
(click)="onTypeChanged('dataset',entity, false)">Research data
</mat-option>
<mat-option [value]="'software'" (click)="onTypeChanged('software',entity, false)">
Software
</mat-option>
<mat-option [value]="'other'"
(click)="onTypeChanged('other',entity, false)">Other research product
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="uk-width-1-2">
<div class="uk-grid">
<!-- <span class="uk-text-muted uk-margin-small-top uk-padding-remove-left">Access mode</span>-->
<mat-form-field class="matSelectionFormField">
<mat-label>Access mode</mat-label>
<mat-select [(ngModel)]="entity.result.accessRights"
name="{{'select_rights_'+entity.id}}"
class="uk-padding-remove-left matSelection"
[disableOptionCentering]="true"
panelClass="matSelectionPanel">
<mat-option *ngFor="let type of accessTypes" [value]="type"
(click)="accessRightsTypeChanged(type,entity, false)">{{type}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field *ngIf="entity.result.accessRights== 'EMBARGO'">
<input matInput [matDatepicker]="picker" placeholder="Choose embargo end date"
(click)="picker.open()" [ngModel]="embargoEndDates[entity.id+'_source']"
(dateInput)="onDateChanged($event, entity, false)"
(dateChange)="onDateChanged($event, entity, false)">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker [startAt]="embargoEndDates[entity.id+'_source']"
ng-model-options="{ timezone: 'utc' }"></mat-datepicker>
</mat-form-field>
</div>
<div *ngIf="entity.result.accessRights== 'EMBARGO' && getEmbargoEndDateMessage(entity)"
[class]="(getEmbargoEndDateMessage(entity)?'uk-text-warning':'')">{{getEmbargoEndDateMessage(entity)}}
</div>
</div>
</div>
</div>
<div class=" uk-margin-auto-vertical uk-padding-remove-left uk-margin-small-left">
<a class=" uk-link "
(click)="remove(entity, false)">
<span uk-icon="close"> </span>
</a>
</div>
</div>
</li>
</ul>
</div>
<!-- Results-->
<div class=" ">
<div class=" uk-margin uk-grid">
<span class=" uk-h6 uk-width-expand"> {{claimsProperties.METADATA_PREVIEW.target_title}} ({{results.length | number}})</span>
<div class="uk-width-auto uk-flex">
<icon [name]="claimsProperties.METADATA_PREVIEW.edit_target_icon" [flex]="true"></icon>
<a class=" uk-margin-left-xsmall uk-text-small" (click)="showOptions.showLinkTo()">
{{claimsProperties.METADATA_PREVIEW.edit_target_title}}</a>
</div>
</div>
<div *ngIf="results.length == 0">
<div class="uk-alert dangerBorder no-selected-message uk-text-center">
<span class="uk-text-bold uk-text-danger"> LINK TO list cannot be empty.</span><br>
Start by adding sources to link to first, go to <a (click)="showOptions.showLinkTo() "
class="uk-link">
step 2</a>.
</div>
</div>
<ul *ngIf="results.length > 0 " class="uk-list uk-animation-fade uk-list-divider">
<li *ngFor=" let entity of results "
style="z-index: 0 !important;">
<div class="uk-grid uk-text-small uk-margin-top">
<!-- <div class="uk-text-muted uk-width-1-2 uk-flex uk-flex-middle">
<span *ngIf="entity.result" class="material-icons uk-text-small uk-text-meta">insert_drive_file
</span>
<span *ngIf="entity.project"
class="material-icons uk-text-small uk-text-meta">assignment_turned_in
</span>
<span *ngIf="entity.type=='community'"
class="material-icons uk-text-small uk-text-meta">people
</span>
{{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}}
</div> -->
<div *ngIf="entity.errorMessages.length > 0"
class="uk-text-danger uk-width-1-2"> Link couldn't be saved
</div>
</div>
<div class="uk-grid uk-margin-remove-top uk-margin-bottom">
<div class="uk-width-expand">
<claim-title [shortVersion]="true" [entity]="entity" [showIcon]="false"></claim-title>
<claim-result-metadata [entity]="entity"></claim-result-metadata>
<claim-project-metadata [entity]="entity"></claim-project-metadata>
</div>
<div class="uk-margin-auto-vertical uk-padding-remove-left uk-margin-small-left">
<a class="uk-link "
(click)="remove(entity, true)">
<span uk-icon="close"> </span>
</a>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
<claim-insert [results]="results" [sources]="sources" [inlineEntity]="inlineEntity"
[properties]=properties [localStoragePrefix]=localStoragePrefix
class=" " [errors]="errors" (insertFinished)="runValidation(false); updateLocalStorage();"
[defaultColors]="defaultColors" [communityId]="communityId">
</claim-insert>
</div>
<div class="uk-width-1-3" *ngIf="errors.length > 0 || warnings.length > 0">
<!-- Errors and Warning -->
<div *ngIf="errors.length > 0" class=" uk-margin uk-h6 uk-text-danger uk-animation-toggle">
ERRORS ({{errors.length | number}})
</div>
<div *ngIf="errors.length > 0 " class="">
<div *ngFor=" let message of errors " class="uk-alert uk-alert-danger">
<div *ngIf="message.type == 'claimServiceFail2Insert'">
<div class="">
<span class=" uk-text-bold"> Fail to save {{message.failed|number}}
{{message.failed > 1 ? 'links.' : 'link.'}}</span>
<br>
<div
*ngIf="message.inserted>0">But {{message.inserted|number}}
link{{message.inserted > 1 ? 's' : ''}} was
successfully inserted.
<div>
<a routerLinkActive="router-link-active" routerLink="/myclaims">Manage your links here</a>
</div>
</div>
</div>
</div>
<div *ngIf="message.type == 'claimServiceFail'">
<div class="">
<span class=" uk-text-bold"> An error occured while saving your links.</span>
<br>
None of the links saved.
</div>
</div>
<div *ngIf="message.type == 'jobError'">
<div class="">
<span class=" uk-text-bold">The saving status of your links can't be fetched. Please check your links or start over. </span>
<br>
<a routerLinkActive="router-link-active" routerLink="/myclaims">Manage your links here</a>
</div>
</div>
</div>
</div>
<div *ngIf="warnings.length > 0"
class=" uk-margin uk-h6 uk-text-warning uk-animation-toggle"> WARNINGS
({{warnings.length
| number}})
</div>
<div *ngIf="warnings.length > 0 " class="">
<div *ngFor=" let message of warnings " class="uk-alert uk-alert-warning">
<div *ngIf="message.type == 'embargoEndDate'">
<div class="uk-text-bold">
Embargo date must be later than published date in
</div>
<div class="">
{{message.resultTitle}}
</div>
</div>
<div *ngIf="message.type == 'projectDuration'">
<div class="uk-text-bold">
Published date must be in the project's date boundaries
(from {{message.projectInfo.startDate}}{{(message.projectInfo.endDate) ? (' to ' + (addStringToNumber(message.projectInfo.endDate, 5))) : ''}}
) in
</div>
<div class="">
{{message.resultTitle}}
</div>
<div class="uk-text-muted uk-text-small">
with link to
</div>
<div class="">
{{message.projectInfo.title}}
</div>
<div><span class="uk-text-muted uk-text-small">
Project boundaries: </span>({{message.projectInfo.startDate}}{{(message.projectInfo.endDate) ? (' - ' + (message.projectInfo.endDate) + ') +5 years') : ')'}}
</div>
</div>
</div>
</div>
</div>
<div class="uk-section uk-padding-remove-top uk-padding-remove-bottom ">
<div
[class]="((defaultColors)?'linkingToolbar':'communityPanelBackground')+' uk-padding-small'">
<div class="uk-container uk-container-large uk-margin-small-top uk-padding-small">
<div class="uk-grid">
<div class="uk-padding-remove-left uk-margin-auto-vertical back uk-link">
<span
(click)="showOptions.showLinkTo()"
style="cursor:pointer">
<span class="uk-icon">
<svg width="30" height="30" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="chevron-left"
ratio="1.5"><polyline fill="none" stroke="#000" stroke-width="1.03"
points="13 16 7 10 13 4"></polyline></svg></span>
BACK
</span>
</div>
<modal-alert (alertOutput)="confirmClose()">
</modal-alert>
<div class="uk-width-expand">
<h6 class="uk-text-bold">
LINKING CONFIRMATION
</h6>
Confirm that the links you provided are all correct
</div>
<claim-insert [results]="results" [sources]="sources" [inlineEntity]="inlineEntity"
[properties]=properties [localStoragePrefix]=localStoragePrefix
class=" " [errors]="errors" (insertFinished)="runValidation(false); updateLocalStorage();"
[defaultColors]="defaultColors" [communityId]="communityId">
</claim-insert>
</div>
</div>
</div>
<helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0"
[texts]="pageContents['bottom']"></helper>
</div>
<div id="tm-main" class="uk-section uk-margin-small-top tm-middle uk-padding-remove-top">
<div class="tm-main uk-width-1-1@s uk-width-1-1@m uk-width-1-1@l uk-row-first ">
<div class="uk-container uk-container-large">
<div *ngIf="properties" class="uk-section uk-section-default uk-padding-remove-top">
<div class="uk-margin-top">
<div class="uk-grid">
<div class="uk-width-expand">
<div>
<div class=" uk-margin uk-h6 uk-text-primary uk-animation-toggle"
(click)="showSources=!showSources; ">
SOURCES ({{sources.length + (inlineEntity ? 1 : 0) | number}})
<span *ngIf="!showSources" class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg" icon="chevron-left"
ratio="1"><polyline fill="none" stroke="#000"
stroke-width="1.03"
points="13 16 7 10 13 4"></polyline></svg></span>
<span *ngIf="showSources" class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg" icon="chevron-down"
ratio="1"><polyline fill="none" stroke="#000"
stroke-width="1.03"
points="16 7 10 13 4 7"></polyline></svg></span>
</div>
<ul *ngIf="inlineEntity && showSources" class="uk-list uk-animation-fade">
<li
[class]="((inlineEntity.warningMessages.length > 0)?' warningBorder ':'')+
+((inlineEntity.errorMessages.length > 0)?' dangerBorder ':'') +
' uk-alert'" >
<div class="uk-grid uk-text-small">
<div class="uk-text-muted uk-width-1-2">
{{(!inlineEntity.result) ? inlineEntity.type : ((inlineEntity.result && inlineEntity.result.source == 'openaire') ? inlineEntity.type : (inlineEntity.result && inlineEntity.result.source + ' result'))}}
</div>
<div *ngIf="inlineEntity.errorMessages.length > 0"
class="uk-text-danger uk-width-1-2"> Link couldn't be saved
</div>
</div>
<!-- <div class="uk-text-muted">-->
<!-- {{(!inlineEntity.result) ? inlineEntity.type : ((inlineEntity.result && inlineEntity.result.source == 'openaire') ? inlineEntity.type : (inlineEntity.result && inlineEntity.result.source + ' result'))}}-->
<!-- </div>-->
<div>
<claim-title [entity]="inlineEntity"></claim-title>
</div>
<claim-result-metadata [entity]="inlineEntity"></claim-result-metadata>
<claim-project-metadata [entity]="inlineEntity"></claim-project-metadata>
</li>
</ul>
<div *ngIf="!inlineEntity && sources.length == 0 && showSources">
<div class="uk-alert dangerBorder no-selected-message uk-text-center">
<span class="uk-text-bold uk-text-danger"> SOURCES cannot be empty.</span>
Start by adding your linking sources first, go to <a (click)="showOptions.showSource() " class="uk-link">
sources
page</a>.
</div>
</div>
<ul *ngIf="!inlineEntity && sources.length > 0 && showSources" class="uk-list uk-animation-fade">
<li *ngFor=" let entity of sources "
[class]="((entity.warningMessages.length > 0)?' warningBorder ':'')+
+((entity.errorMessages.length > 0)?' dangerBorder ':'') +
' uk-alert'">
<!-- <div class="uk-text-muted">-->
<!-- {{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}}-->
<!-- </div>-->
<div class="uk-grid uk-text-small">
<div class="uk-text-muted uk-width-1-2">
{{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}}
</div>
<div *ngIf="entity.errorMessages.length > 0"
class="uk-text-danger uk-width-1-2"> Link couldn't be saved
</div>
</div>
<div class="uk-grid uk-margin-remove-top">
<div class="uk-width-expand">
<claim-title [entity]="entity"></claim-title>
<claim-result-metadata [entity]="entity"></claim-result-metadata>
<claim-project-metadata [entity]="entity"></claim-project-metadata>
<div *ngIf="entity.result && entity.result.source && entity.result.source!='openaire' "
class="uk-grid uk-margin-remove-left uk-margin-small-top uk-text-small">
<div class="uk-width-1-2 uk-padding-remove-left">
<!-- <span class="uk-text-muted">Type </span>-->
<!-- <mat-select [(ngModel)]="entity.type" name="{{'select_type_'+entity.id}}"-->
<!-- class="uk-select uk-width-small matSelection"-->
<!-- [disableOptionCentering]="true"-->
<!-- panelClass="entitiesSelectionPanel">-->
<!-- <mat-option [value]="'publication'"-->
<!-- (click)="onTypeChanged('publication',entity, false)">Publication-->
<!-- </mat-option>-->
<!-- <mat-option [value]="'dataset'"-->
<!-- (click)="onTypeChanged('dataset',entity, false)">Research data-->
<!-- </mat-option>-->
<!-- <mat-option [value]="'software'" (click)="onTypeChanged('software',entity, false)">Software-->
<!-- </mat-option>-->
<!-- <mat-option [value]="'other'"-->
<!-- (click)="onTypeChanged('other',entity, false)">Other research product-->
<!-- </mat-option>-->
<!-- </mat-select>-->
<mat-form-field class="matSelectionFormField">
<mat-label>Type</mat-label>
<mat-select [(ngModel)]="entity.type" name="{{'select_type_'+entity.id}}"
class="matSelection"
[disableOptionCentering]="true"
panelClass="entitiesSelectionPanel">
<mat-option [value]="'publication'"
(click)="onTypeChanged('publication',entity, false)">Publication
</mat-option>
<mat-option [value]="'dataset'"
(click)="onTypeChanged('dataset',entity, false)">Research data
</mat-option>
<mat-option [value]="'software'" (click)="onTypeChanged('software',entity, false)">Software
</mat-option>
<mat-option [value]="'other'"
(click)="onTypeChanged('other',entity, false)">Other research product
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="uk-width-1-2">
<div class="uk-grid">
<!-- <span class="uk-text-muted uk-margin-small-top uk-padding-remove-left">Access mode</span>-->
<mat-form-field class="matSelectionFormField">
<mat-label>Access mode </mat-label>
<mat-select [(ngModel)]="entity.result.accessRights" name="{{'select_rights_'+entity.id}}"
class="uk-padding-remove-left matSelection"
[disableOptionCentering]="true"
panelClass="matSelectionPanel">
<mat-option *ngFor="let type of accessTypes" [value]="type"
(click)="accessRightsTypeChanged(type,entity, false)">{{type}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field *ngIf="entity.result.accessRights== 'EMBARGO'">
<input matInput [matDatepicker]="picker" placeholder="Choose embargo end date"
(click)="picker.open()" [ngModel]="embargoEndDates[entity.id+'_source']"
(dateInput)="onDateChanged($event, entity, false)" (dateChange)="onDateChanged($event, entity, false)">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker [startAt]="embargoEndDates[entity.id+'_source']" ng-model-options="{ timezone: 'utc' }"></mat-datepicker>
</mat-form-field>
</div>
<div *ngIf="entity.result.accessRights== 'EMBARGO' && getEmbargoEndDateMessage(entity)"
[class]="(getEmbargoEndDateMessage(entity)?'uk-text-warning':'')">{{getEmbargoEndDateMessage(entity)}}
</div>
</div>
</div>
</div>
<div class=" uk-margin-auto-vertical uk-padding-remove-left uk-margin-small-left">
<a class=" uk-icon-button "
(click)="remove(entity, false)">
<span class="uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="minus"
ratio="1"><rect height="1" width="18" y="9" x="1"></rect></svg>
</span>
</a>
</div>
</div>
</li>
</ul>
</div>
<!-- Results-->
<div>
<div class=" uk-margin uk-h6 uk-text-primary "
(click)="showLinksTo=!showLinksTo; ">
LINK TO ({{results.length | number}})
<span *ngIf="!showLinksTo" class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
icon="chevron-left" ratio="1"><polyline
fill="none" stroke="#000" stroke-width="1.03" points="13 16 7 10 13 4"></polyline></svg></span>
<span *ngIf="showLinksTo" class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
icon="chevron-down" ratio="1"><polyline
fill="none" stroke="#000" stroke-width="1.03" points="16 7 10 13 4 7"></polyline></svg></span>
</div>
<div *ngIf="results.length == 0 && showLinksTo">
<div class="uk-alert dangerBorder no-selected-message uk-text-center">
<span class="uk-text-bold uk-text-danger"> LINK TO list cannot be empty.</span>
Select an entity type to link to:
<div class="uk-grid uk-text-center uk-margin-expand uk-padding-small uk-child-width-1-3 uk-width-large uk-margin-auto ">
<div *ngIf="showOptions.linkToEntities.indexOf('project')!=-1 "
(click)="goTo('project')"
style="cursor:pointer;">
<button class="uk-icon-button portal-button">
<span class="uk-icon">
<svg height="20" icon="album" ratio="1" viewBox="0 0 20 20" width="20"
xmlns="http://www.w3.org/2000/svg"><rect height="1" width="10" x="5" y="2"></rect><rect
height="1" width="14" x="3" y="4"></rect><rect fill="none" height="11" stroke="#000"
width="17" x="1.5" y="6.5"></rect></svg></span>
</button>
<div>Projects</div>
</div>
<div *ngIf="showOptions.linkToEntities.indexOf('result')!=-1 " (click)="goTo('result')"
style="cursor:pointer;">
<button class="uk-icon-button portal-button">
<span class="uk-icon">
<svg height="20" icon="copy" ratio="1" viewBox="0 0 20 20" width="20"
xmlns="http://www.w3.org/2000/svg"><rect fill="none" height="16" stroke="#000"
width="12" x="3.5" y="2.5"></rect><polyline
fill="none" points="5 0.5 17.5 0.5 17.5 17" stroke="#000"></polyline></svg></span>
</button>
<div>Research results</div>
</div>
<div *ngIf="showOptions.linkToEntities.indexOf('context')!=-1 "
(click)="goTo('context')"
style="cursor:pointer;">
<button class="uk-icon-button portal-button">
<span class="uk-icon">
<svg height="20" icon="users" ratio="1" viewBox="0 0 20 20" width="20"
xmlns="http://www.w3.org/2000/svg"><circle cx="7.7" cy="8.6" fill="none" r="3.5"
stroke="#000" stroke-width="1.1"></circle><path
d="M1,18.1 C1.7,14.6 4.4,12.1 7.6,12.1 C10.9,12.1 13.7,14.8 14.3,18.3" fill="none"
stroke="#000" stroke-width="1.1"></path><path
d="M11.4,4 C12.8,2.4 15.4,2.8 16.3,4.7 C17.2,6.6 15.7,8.9 13.6,8.9 C16.5,8.9 18.8,11.3 19.2,14.1"
fill="none" stroke="#000" stroke-width="1.1"></path></svg></span>
</button>
<div>Communities</div>
</div>
</div>
</div>
</div>
<ul *ngIf="results.length > 0 && showLinksTo" class="uk-list uk-animation-fade">
<li *ngFor=" let entity of results "
[class]="((entity.warningMessages.length > 0)?' warningBorder ':'')+
+((entity.errorMessages.length > 0)?' dangerBorder ':'') +
' uk-alert'" style="z-index: 0 !important;">
<div class="uk-grid uk-text-small">
<div class="uk-text-muted uk-width-1-2">
{{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}}
</div>
<div *ngIf="entity.errorMessages.length > 0"
class="uk-text-danger uk-width-1-2"> Link couldn't be saved
</div>
</div>
<div class="uk-grid uk-margin-remove-top">
<div class="uk-width-expand">
<claim-title [entity]="entity"></claim-title>
<claim-result-metadata [entity]="entity"></claim-result-metadata>
<claim-project-metadata [entity]="entity"></claim-project-metadata>
<div *ngIf="entity.result && entity.result.source && entity.result.source!='openaire' "
class="uk-grid uk-text-small uk-margin-remove-left uk-margin-small-top">
<div class="uk-width-1-2 uk-padding-remove-left">
<!-- <span class="uk-text-muted">Type </span>-->
<mat-form-field class="matSelectionFormField">
<mat-label>Type</mat-label>
<mat-select [(ngModel)]="entity.type" name="{{'select_type_'+entity.id}}"
class=" matSelection"
[disableOptionCentering]="true"
panelClass="matSelectionPanel">
<mat-option [value]="'publication'"
(click)="onTypeChanged('publication',entity, false)">Publication
</mat-option>
<mat-option [value]="'dataset'"
(click)="onTypeChanged('dataset',entity, false)">Research data
</mat-option>
<mat-option [value]="'software'" (click)="onTypeChanged('software',entity, false)">Software
</mat-option>
<mat-option [value]="'other'"
(click)="onTypeChanged('other',entity, false)">Other research product
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="uk-width-1-2">
<div class="uk-grid">
<!-- <span class="uk-text-muted uk-margin-small-top uk-padding-remove-left">Access mode</span>-->
<mat-form-field class="matSelectionFormField">
<mat-label>Access mode </mat-label>
<mat-select [(ngModel)]="entity.result.accessRights" name="{{'select_rights_'+entity.id}}"
class=" uk-padding-remove-left matSelection"
[disableOptionCentering]="true"
panelClass="matSelectionPanel">
<mat-option *ngFor="let type of accessTypes" [value]="type"
(click)="accessRightsTypeChanged(type,entity, true)">{{type}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field *ngIf="entity.result.accessRights== 'EMBARGO'">
<input matInput [matDatepicker]="picker" placeholder="Choose embargo end date"
(click)="picker.open()" [ngModel]="embargoEndDates[entity.id+'_result']"
(dateInput)="onDateChanged($event, entity, true)"
(dateChange)="onDateChanged($event, entity, true)">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker [startAt]="embargoEndDates[entity.id+'_result']" ng-model-options="{ timezone: 'utc' }"></mat-datepicker>
</mat-form-field>
</div>
<div *ngIf="entity.result.accessRights== 'EMBARGO' && getEmbargoEndDateMessage(entity)"
[class]="(getEmbargoEndDateMessage(entity)?'uk-text-warning':'')">{{getEmbargoEndDateMessage(entity)}}
</div>
</div>
</div>
</div>
<div class="uk-margin-auto-vertical uk-padding-remove-left uk-margin-small-left">
<a class="uk-icon-button "
(click)="remove(entity, true)">
<span class="uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="minus"
ratio="1"><rect height="1" width="18" y="9" x="1"></rect></svg>
</span>
</a>
</div>
</div>
</li>
</ul>
</div>
</div>
<div class="uk-width-1-3" *ngIf="errors.length > 0 || warnings.length > 0">
<!-- Errors and Warning -->
<div *ngIf="errors.length > 0" class=" uk-margin uk-h6 uk-text-primary uk-animation-toggle"
(click)="showErrors=!showErrors ">
ERRORS ({{errors.length | number}})
<span *ngIf="!showErrors" class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
icon="chevron-left" ratio="1"><polyline
fill="none" stroke="#000" stroke-width="1.03" points="13 16 7 10 13 4"></polyline></svg></span>
<span *ngIf="showErrors" class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
icon="chevron-down" ratio="1"><polyline
fill="none" stroke="#000" stroke-width="1.03" points="16 7 10 13 4 7"></polyline></svg></span>
</div>
<div *ngIf="errors.length > 0 && showErrors" class=" uk-animation-fade">
<div *ngFor=" let message of errors " class="uk-alert dangerBorder">
<div *ngIf="message.type == 'claimServiceFail2Insert'">
<div class="">
<span class="uk-text-danger uk-text-bold"> Fail to save {{message.failed|number}}
{{message.failed > 1 ? 'links.' : 'link.'}}</span>
<br>
<div
*ngIf="message.inserted>0">But {{message.inserted|number}} link{{message.inserted > 1 ? 's' : ''}} was
successfully inserted.
<div>
<a routerLinkActive="router-link-active" routerLink="/myclaims">Manage your links here</a>
</div>
</div>
</div>
</div>
<div *ngIf="message.type == 'claimServiceFail'">
<div class="">
<span class="uk-text-danger uk-text-bold"> An error occured while saving your links.</span>
<br>
None of the links saved.
</div>
</div>
</div>
</div>
<div *ngIf="warnings.length > 0"
class=" uk-margin uk-h6 uk-text-primary uk-animation-toggle"
(click)="showWarnings=!showWarnings "> WARNINGS
({{warnings.length
| number}})
<span *ngIf="!showWarnings" class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
icon="chevron-left" ratio="1"><polyline
fill="none" stroke="#000" stroke-width="1.03" points="13 16 7 10 13 4"></polyline></svg></span>
<span *ngIf="showWarnings" class="uk-icon"><svg width="20" height="20" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
icon="chevron-down" ratio="1"><polyline
fill="none" stroke="#000" stroke-width="1.03" points="16 7 10 13 4 7"></polyline></svg></span>
</div>
<div *ngIf="warnings.length > 0 && showWarnings " class=" uk-animation-fade">
<div *ngFor=" let message of warnings " class="uk-alert warningBorder">
<div *ngIf="message.type == 'embargoEndDate'">
<div class="uk-text-warning uk-text-bold">
Embargo date must be later than published date in
</div>
<div class="">
{{message.resultTitle}}
</div>
</div>
<div *ngIf="message.type == 'projectDuration'">
<div class="uk-text-warning uk-text-bold">
Published date must be in the project's date boundaries
(from {{message.projectInfo.startDate}}{{(message.projectInfo.endDate) ? (' to ' + (addStringToNumber(message.projectInfo.endDate, 5))) : ''}}) in
</div>
<div class="">
{{message.resultTitle}}
</div>
<div class="uk-text-muted uk-text-small">
with link to
</div>
<div class="">
{{message.projectInfo.title}}
</div>
<div><span class="uk-text-muted uk-text-small">
Project boundaries: </span>({{message.projectInfo.startDate}}{{(message.projectInfo.endDate) ? (' - ' + (message.projectInfo.endDate) + ') +5 years') : ')'}}
</div>
</div>
</div>
</div>
</div>
<modal-alert (alertOutput)="confirmClose()">
</modal-alert>
</div>
</div>
</div>
<helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0" [texts]="pageContents['bottom']"></helper>
</div>
</div>
</div>

View File

@ -4,7 +4,6 @@ import {ClaimEntity, ClaimsErrorMessage, Message, ShowOptions} from '../../claim
import {EnvProperties} from "../../../utils/properties/env-properties";
import {Dates} from "../../../utils/string-utils.class";
import {HelperFunctions} from "../../../utils/HelperFunctions.class";
import {ClaimsProperties} from "../../claim-utils/claims.properties";
@Component({
selector: 'metadata-preview',
@ -13,10 +12,10 @@ import {ClaimsProperties} from "../../claim-utils/claims.properties";
})
export class MetadataPreviewComponent {
/* showSources = true;
showLinksTo = true;*/
// showErrors = true;
// showWarnings = true;
showSources = true;
showLinksTo = true;
showErrors = true;
showWarnings = true;
@Input() results: ClaimEntity[];
@Input() sources: ClaimEntity[];
@Input() title: string = "Research Results";
@ -29,7 +28,6 @@ export class MetadataPreviewComponent {
@ViewChild(AlertModal) alertApplyAll;
@Input() localStoragePrefix: string = "";
@Input() communityId:string= null;
@Input() claimsProperties:ClaimsProperties;
errors:ClaimsErrorMessage[] = [];
warnings:Message[] = [];
public commonAccessRights = "OPEN"; // for access rights- changes when user apply a change to every entity
@ -42,10 +40,10 @@ export class MetadataPreviewComponent {
ngOnInit() {
this.setEmbargoEndDates();
/* if (this.inlineEntity) {
if (this.inlineEntity) {
this.showSources = true;
this.showLinksTo = true;
}*/
}
this.runValidation(true);
}
setEmbargoEndDates(){

View File

@ -1,5 +1,5 @@
import {NgModule} from '@angular/core';
import {SharedModule} from '../../../../openaireLibrary/shared/shared.module';
import {SharedModule} from '../../../shared/shared.module';
import {MetadataPreviewComponent} from './metadataPreview.component';
import {AlertModalModule} from '../../../utils/modal/alertModal.module';
import {ClaimEntitiesMetadataModule} from "./ClaimEntitiesMetadata.module";
@ -10,8 +10,6 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import {HelperModule} from "../../../utils/helper/helper.module";
import {SelectedPublicationsModule} from "./selectedResults.module";
import {IconsModule} from "../../../utils/icons/icons.module";
@NgModule({
imports: [
@ -19,8 +17,8 @@ import {IconsModule} from "../../../utils/icons/icons.module";
AlertModalModule,
ClaimEntitiesMetadataModule,
InsertClaimsModule,
MatDatepickerModule, MatNativeDateModule, MatFormFieldModule, MatInputModule, MatSelectModule,
HelperModule, SelectedPublicationsModule, IconsModule
MatDatepickerModule, MatNativeDateModule, MatFormFieldModule, MatInputModule, MatSelectModule,
HelperModule
],
declarations: [MetadataPreviewComponent],
exports:[MetadataPreviewComponent]

View File

@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../../../openaireLibrary/shared/shared.module';
import { SharedModule } from '../../../shared/shared.module';
import {ClaimSelectedContextsComponent} from './selectedContexts.component';
@NgModule({

View File

@ -2,7 +2,7 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { SharedModule } from '../../../../openaireLibrary/shared/shared.module';
import { SharedModule } from '../../../shared/shared.module';
import {ClaimSelectedProjectsComponent} from './selectedProjects.component';
@NgModule({

View File

@ -1,27 +1,19 @@
<ul *ngIf="results.length > 0 " class="uk-list uk-list-divider">
<li *ngFor=" let entity of results " class="">
<!--<div class="uk-text-muted">
<li *ngFor=" let entity of results " >
<div class="uk-text-muted">
{{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}}
</div>-->
<div class="uk-grid uk-flex uk-flex-middle uk-margin-small-top uk-margin-small-bottom uk-margin-remove-left">
<!--<div >
<span *ngIf="type == 'source' || entity.result" class="material-icons uk-text-small uk-text-meta">insert_drive_file
</span>
<span *ngIf="type == 'target' && entity.project"
class="material-icons uk-text-small uk-text-meta">assignment_turned_in
</span>
<span *ngIf="entity.type=='community'"
class="material-icons uk-text-small uk-text-meta">people
</span>
</div>-->
<div class="uk-width-expand uk-padding-remove-left uk-margin-small-left">
<claim-title [entity]="entity" [slice]="true" [sliceSize]="45" [shortVersion]="shortVersion" [showIcon]="true"></claim-title>
<claim-result-metadata [entity]="entity" [slice]="true" [sliceSize]="5" [shortVersion]="shortVersion"></claim-result-metadata>
<claim-project-metadata [entity]="entity" [slice]="true" [sliceSize]="5" [shortVersion]="shortVersion"></claim-project-metadata>
</div>
<div class="uk-grid">
<div class="uk-width-expand">
<claim-title [entity]="entity" [slice]="true" [sliceSize]="45" [shortVersion]="true"></claim-title>
<claim-result-metadata [entity]="entity" [slice]="true" [sliceSize]="5" [shortVersion]="true"></claim-result-metadata>
<claim-project-metadata [entity]="entity" [slice]="true" [sliceSize]="5" [shortVersion]="true"></claim-project-metadata>
</div>
<div class="uk-margin-auto-vertical uk-padding-remove-left uk-margin-small-left" *ngIf="enableRemove">
<a class=" uk-link " (click)="remove(entity)" >
<span uk-icon="close"> </span>
<a class=" uk-icon-button " (click)="remove(entity)" >
<span class="uk-icon" >
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="minus" ratio="1"><rect height="1" width="18" y="9" x="1"></rect></svg>
</span>
</a>
</div>
</div>

View File

@ -1,6 +1,6 @@
import {Component, Input} from '@angular/core';
import {ClaimEntity} from '../../claim-utils/claimHelper.class';
declare var UIkit: any;
@Component({
selector: 'claim-selected-results',
templateUrl: 'selectedResults.component.html'
@ -11,8 +11,7 @@ export class ClaimSelectedResultsComponent {
@Input() sectionTitle: string = "Research Results";
@Input() localStoragePrefix: string = "";
@Input() enableRemove:boolean = true;
@Input() type: "source" | "target";
@Input() shortVersion:boolean = true;
ngOnInit() {
}
@ -24,11 +23,6 @@ export class ClaimSelectedResultsComponent {
if (this.results != null) {
localStorage.setItem(this.localStoragePrefix, JSON.stringify(this.results));
}
UIkit.notification(item.type + ' removed from your basket!', {
status: 'warning',
timeout: 4000,
pos: 'bottom-right'
});
}
}

View File

@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../../../openaireLibrary/shared/shared.module';
import { SharedModule } from '../../../shared/shared.module';
import {ClaimSelectedResultsComponent} from './selectedResults.component';
import {AlertModalModule} from '../../../utils/modal/alertModal.module';
import { MyDatePickerModule } from '../../../utils/my-date-picker/my-date-picker.module';

View File

@ -8,19 +8,25 @@ import {Subscriber} from "rxjs";
@Component({
selector: 'my-claims',
template: `
<div class="uk-section">
<div class="uk-container uk-container-large">
<h1 class="uk-h2 uk-margin-remove">
My links
</h1>
<div class="uk-text-meta">
Manage your links in OpenAIRE
</div>
<div class="uk-margin-top">
<displayClaims *ngIf="user" [user]="user" [enableDelete]=true [myClaims]=true [isAdmin]=false [showUserEmail]=false
[claimsInfoURL]=claimsInfoURL [communityId]=communityId
pageTitle="My links">
</displayClaims>
<div id="tm-main" class=" uk-section uk-padding-remove-top tm-middle">
<div class="uk-grid uk-margin-small-top" >
<div class="tm-main uk-width-1-1@s uk-width-1-1@m uk-width-1-1@l uk-row-first ">
<div class="uk-container uk-container-large">
<div class="uk-article-title custom-article-title">
My links
</div>
<div class=" ">
Manage your links in OpenAIRE
</div>
<div>
<displayClaims *ngIf="user" [user]="user" [enableDelete]=true [myClaims]=true [isAdmin]=false [showUserEmail]=false
[claimsInfoURL]=claimsInfoURL [communityId]=communityId
[piwikSiteId]="piwikSiteId" pageTitle="My links">
</displayClaims>
</div>
</div>
</div>
</div>
</div>
@ -30,6 +36,8 @@ import {Subscriber} from "rxjs";
export class MyClaimsComponent {
@Input() claimsInfoURL: string;
@Input() communityId:string;
@Input() piwikSiteId = null;
@Input() userInfoURL: string;
public user: User = null;
constructor(private userManagementService: UserManagementService, private _router: Router) {}

View File

@ -1,8 +1,11 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../../openaireLibrary/shared/shared.module';
import { SharedModule } from '../../shared/shared.module';
import { MyClaimsComponent } from './myClaims.component';
import {DisplayClaimsModule} from '../claim-utils/displayClaims/displayClaims.module';
import {LoginGuard} from'../../login/loginGuard.guard';
import {PreviousRouteRecorder} from '../../utils/piwik/previousRouteRecorder.guard';
import {IsRouteEnabled} from '../../error/isRouteEnabled.guard';
@NgModule({
imports: [
@ -10,7 +13,7 @@ import {DisplayClaimsModule} from '../claim-utils/displayClaims/displayClaims.mo
DisplayClaimsModule
],
providers:[],
providers:[LoginGuard, PreviousRouteRecorder, IsRouteEnabled],
declarations: [
MyClaimsComponent
], exports: [MyClaimsComponent]

View File

@ -3,29 +3,25 @@ import {HttpClient, HttpHeaders} from '@angular/common/http';
import {BehaviorSubject, Observable, Subscriber} from 'rxjs';
import {Affiliation} from '../../utils/entities/CuratorInfo';
import {properties} from "../../../../environments/environment";
import {AdvancedAsyncSubject} from "../../utils/AdvancedAsyncSubject";
@Injectable()
export class AffiliationService {
private affiliationsSubject: BehaviorSubject<Affiliation[]> = new BehaviorSubject([]);
sub;
constructor(private http: HttpClient) {
}
ngOnDestroy() {
this.clearSubscriptions();
}
clearSubscriptions() {
clearSubscriptions(){
if (this.sub instanceof Subscriber) {
this.sub.unsubscribe();
}
}
public initAffiliations(communityId: string): void {
this.sub = this.getAffiliations(communityId).subscribe((affiliations) => {
let url = properties.communityAPI + communityId + "/organizations";
this.sub = this.http.get<Affiliation[]>((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url).subscribe((affiliations) => {
this.affiliationsSubject.next(affiliations);
},
error => {
@ -37,11 +33,6 @@ export class AffiliationService {
return this.affiliationsSubject.asObservable();
}
public getAffiliations(communityId: string): Observable<Affiliation[]> {
let url = properties.communityAPI + communityId + "/organizations";
return this.http.get<Affiliation[]>((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url);
}
public updateAffiliation(url: string, affiliation: Affiliation) {
let headers = new HttpHeaders({'Content-Type': 'application/json', 'accept': 'application/json'});
return this.http.post<Affiliation>(url, JSON.stringify(affiliation), {headers: headers});

View File

@ -1,69 +0,0 @@
<ng-template #card let-organization="organization" let-fullView="fullView">
<div [class]="fullView?'uk-card-body uk-height-1-1 uk-flex uk-flex-column uk-flex-around':''">
<div class="affiliation-logo">
<img *ngIf="organization.logo_url"
[src]="organization.logo_url | urlPrefix"
alt="{{(organization.name)?organization.name:''}} logo"
class="uk-blend-multiply uk-height-max-xsmall" loading="lazy">
</div>
<div class="affiliation-name multi-line-ellipsis lines-3" *ngIf="organization.name && fullView">
<p class="uk-text-emphasis uk-text-bold uk-margin-remove">
{{organization.name}}
</p>
</div>
</div>
</ng-template>
<ng-container *ngIf="affiliations.length > 0">
<div *ngIf="showLoading" class="uk-animation-fade uk-width-1-1" role="alert">
<span class="loading-gif uk-align-center"></span>
</div>
<div *ngIf="longView"
class="uk-child-width-1-5@xl uk-child-width-1-4@l uk-child-width-1-3@m uk-child-width-1-2@s uk-text-center uk-grid"
uk-height-match="target: .affiliation-logo, .affiliation-name"
uk-scrollspy="cls: uk-animation-fade; target: .uk-card; repeat: false"
uk-grid>
<div *ngFor="let affiliation of affiliations;">
<div>
<div class="uk-card uk-card-default uk-card-hover affiliationCard">
<a *ngIf="affiliation.website_url" target="_blank" [href]="affiliation.website_url | urlPrefix" class="uk-link-reset">
<ng-container *ngTemplateOutlet="card; context: { organization: affiliation, fullView: true}"></ng-container>
</a>
<span *ngIf="!affiliation.website_url" class="uk-link-reset">
<ng-container *ngTemplateOutlet="card; context: { organization: affiliation, fullView: true}"></ng-container>
</span>
</div>
</div>
</div>
</div>
<div *ngIf="affiliations.length > 0 && communityFirstPage && !longView" class="uk-grid uk-grid-large" uk-grid>
<div class="uk-width-auto@m uk-width-1-1@s">
<h2 class="uk-h1">
Supporting <br> Organizations
</h2>
<a class="uk-display-inline-block uk-text-uppercase uk-button uk-button-text uk-text-default uk-margin-top"
routerLinkActive="router-link-active" routerLink="/organizations">
<span class="uk-flex uk-flex-middle">
<span>Browse all</span>
</span>
</a>
</div>
<div class="uk-width-expand@m uk-width-1-1@s">
<div class="uk-grid uk-grid-large uk-child-width-1-3@m uk-child-width-1-2@s supportingOrganizations" uk-grid>
<div *ngFor="let affiliation of affiliations.slice(0,9);">
<a *ngIf="affiliation.website_url" target="_blank" [href]="affiliation.website_url | urlPrefix" class="uk-link-reset">
<ng-container *ngTemplateOutlet="card; context: {organization: affiliation, fullView: false}"></ng-container>
</a>
<span *ngIf="!affiliation.website_url" class="uk-link-reset">
<ng-container *ngTemplateOutlet="card; context: {organization: affiliation, fullView: false}"></ng-container>
</span>
</div>
</div>
</div>
</div>
</ng-container>
<!--<div *ngIf="affiliations.length == 0 && longView" class="uk-animation-fade uk-alert uk-alert-primary" role="alert">-->
<!-- No affiliations available-->
<!--</div>-->

View File

@ -1,18 +0,0 @@
.affiliationCard {
width: 260px !important;
height: 260px !important;
}
.supportingOrganizations a {
img, svg {
-webkit-filter: grayscale(1);
filter: grayscale(1);
transition-duration: 0.3s;
}
&:hover img, svg {
-webkit-filter: grayscale(0);
filter: grayscale(0);
transition-duration: 0.3s;
}
}

View File

@ -1,68 +0,0 @@
import {Component, Input} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {EnvProperties} from '../../utils/properties/env-properties';
import {AffiliationService} from "./affiliation.service";
import {Affiliation} from "../../utils/entities/CuratorInfo";
import {ConnectHelper} from "../connectHelper";
import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {ConfigurationService} from "../../utils/configuration/configuration.service";
import {CommunityService} from "../community/community.service";
@Component({
selector: 'affiliations',
templateUrl: './affiliations.component.html',
styleUrls: ['./affiliations.component.less']
})
export class AffiliationsComponent {
@Input() getAffiliationsFromAPI: boolean = false;
@Input() longView: boolean = false;
@Input() communityFirstPage: boolean = false;
@Input() affiliationsInSlider: number = 5;
@Input() affiliations: Affiliation[] = [];
@Input() sliderOptions = '';
@Input() arrows = true;
public showLoading: boolean = false;
public communityId: string;
public properties: EnvProperties = properties;
private subscriptions = [];
constructor(private route: ActivatedRoute, private affiliationService: AffiliationService, private config: ConfigurationService) {
}
public ngOnInit() {
this.subscriptions.push(this.config.portalAsObservable.subscribe(
res => {
// this.portal = res;
this.communityId = res.pid
},
error => {
console.log(error);
}
));
if (this.getAffiliationsFromAPI) {
this.showLoading = true;
this.affiliationService.initAffiliations(this.communityId);
this.subscriptions.push(this.affiliationService.affiliations.subscribe(
affiliations => {
this.affiliations = affiliations.filter((affiliation) => this.longView || !!affiliation['logo_url']);
this.showLoading = false;
},
error => {
console.error("Affiliations Component: Error getting affiliations for community with id: " + this.communityId, error);
this.showLoading = false;
}
));
}
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
}
});
this.affiliationService.clearSubscriptions();
}
}

View File

@ -1,26 +0,0 @@
import {NgModule} from '@angular/core';
import {PreviousRouteRecorder} from '../../utils/piwik/previousRouteRecorder.guard';
import {IsRouteEnabled} from '../../error/isRouteEnabled.guard'
import {RouterModule} from '@angular/router';
import {AffiliationsComponent} from './affiliations.component';
import {CommonModule} from "@angular/common";
import {UrlPrefixModule} from "../../utils/pipes/url-prefix.module";
import {AffiliationService} from "./affiliation.service";
@NgModule({
imports: [
CommonModule, RouterModule, UrlPrefixModule
],
declarations: [
AffiliationsComponent
],
providers:[PreviousRouteRecorder, IsRouteEnabled, AffiliationService],
exports: [
AffiliationsComponent
]
})
export class AffiliationsModule{}

View File

@ -5,12 +5,11 @@ import { EnvProperties} from '../../utils/properties/env-properties';
import {ConnectHelper} from '../connectHelper';
import {SearchCommunityDataprovidersService} from '../contentProviders/searchDataproviders.service';
import {properties} from "../../../../environments/environment";
import {OpenaireEntities} from "../../utils/properties/searchFields";
@Component({
selector: 'approved-by-community',
template: `
<span *ngIf="approved" class="uk-align-right uk-label custom-label uk-label-success">{{openaireEntities.COMMUNITY}} Approved</span>
<span *ngIf="approved" class="uk-align-right uk-label custom-label uk-label-success">Community Approved</span>
`
})
@ -21,12 +20,12 @@ export class ApprovedByCommunityComponent {
public approved:boolean = false;
private communityContentProviders = [];
properties:EnvProperties = properties;
public openaireEntities = OpenaireEntities;
properties:EnvProperties;
constructor (private route: ActivatedRoute, private _searchDataprovidersService: SearchCommunityDataprovidersService) {}
public ngOnInit() {
this.properties =properties;
this.route.queryParams.subscribe(
communityId => {
this.communityId = ConnectHelper.getCommunityFromDomain(this.properties.domain);
@ -41,7 +40,7 @@ export class ApprovedByCommunityComponent {
this.approved = this.checkApproval();
},
error => {
this.handleError("Error getting "+OpenaireEntities.DATASOURCES+" for "+OpenaireEntities.COMMUNITY+" with id: "+this.communityId, error);
this.handleError("Error getting content providers for community with id: "+this.communityId, error);
}
);
}
@ -59,6 +58,6 @@ export class ApprovedByCommunityComponent {
}
private handleError(message: string, error) {
console.error("Approved by "+OpenaireEntities.COMMUNITY+" (component): "+message, error);
console.error("Approved by Community (component): "+message, error);
}
}

View File

@ -56,11 +56,12 @@ export class CommunitiesService {
result['description'] = resData.description;
result['date'] = resData.creationDate;
result['status'] = 'all';
result['claim'] = resData.claim;
result['membership'] = resData.membership;
if (resData.hasOwnProperty('status')) {
result['status'] = resData.status;
result.validateStatus();
const status = ['all', 'hidden', 'manager'];
if (status.indexOf(result['status']) === -1) {
result['status'] = 'hidden';
}
}
if (resData.type != null) {
result['type'] = resData.type;

View File

@ -1,104 +1,22 @@
import {properties} from "../../../../environments/environment";
export class Layout {
_id: string;
portalPid: string;
layoutOptions: CustomizationOptions;
date;
constructor(community, options: CustomizationOptions) {
_id:string;
portalPid:string;
layoutOptions:CustomizationOptions;
constructor(community, options:CustomizationOptions){
this.portalPid = community;
this.layoutOptions = options;
}
public static getVariables(options: CustomizationOptions): {} | null {
if (options) {
let variables = {};
if (options.identity) {
variables['@global-primary-background'] = Layout.convertRGBAtoRGB(options.identity.mainColor);
variables['@global-secondary-background'] = Layout.convertRGBAtoRGB(options.identity.secondaryColor);
}
if (options.backgrounds) {
variables['@general-search-form-background'] = Layout.convertRGBAtoRGB(options.backgrounds.form.color);
variables['@global-background'] = Layout.convertRGBAtoRGB(options.backgrounds.light.color);
variables['@hero-background-image'] = (options.backgrounds.form.imageFile ? (this.getUrl(properties.utilsService + '/download/' + options.backgrounds.form.imageFile)) : 'none');
variables['@hero-background-position'] = options.backgrounds.form.position;
variables['@hero-fonts-mode'] = options.backgrounds.form.fontsDarkMode == true ?'dark':'light';
}
if (options.buttons) {
//general
variables['@button-border-width'] = options.buttons.lightBackground.borderWidth + "px";
variables['@button-border-radius'] = options.buttons.lightBackground.borderRadius + "px";
// default -> on dark background todo check again when we have sucj=h buttons
variables['@button-default-background'] = Layout.convertRGBAtoRGB(options.buttons.darkBackground.backgroundColor);
variables['@button-default-color'] = Layout.convertRGBAtoRGB(options.buttons.darkBackground.color);
variables['@button-default-border'] = Layout.convertRGBAtoRGB(options.buttons.darkBackground.borderColor);
variables['@button-default-hover-background'] = Layout.convertRGBAtoRGB(options.buttons.darkBackground.onHover.backgroundColor);
variables['@button-default-hover-color'] = Layout.convertRGBAtoRGB(options.buttons.darkBackground.onHover.color);
variables['@button-default-hover-border'] = Layout.convertRGBAtoRGB(options.buttons.darkBackground.onHover.borderColor);
variables['@button-default-active-background'] = Layout.convertRGBAtoRGB(options.buttons.darkBackground.onHover.backgroundColor);
variables['@button-default-active-color'] = Layout.convertRGBAtoRGB(options.buttons.darkBackground.onHover.color);
variables['@button-default-active-border'] = Layout.convertRGBAtoRGB(options.buttons.darkBackground.onHover.borderColor);
// primary
variables['@button-primary-background'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.backgroundColor);
variables['@button-primary-color'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.color);
variables['@button-primary-border'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.borderColor);
variables['@button-primary-hover-background'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.onHover.backgroundColor);
variables['@button-primary-hover-color'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.onHover.color);
variables['@button-primary-hover-border'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.onHover.borderColor);
variables['@button-primary-active-background'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.onHover.backgroundColor);
variables['@button-primary-active-color'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.onHover.color);
variables['@button-primary-active-border'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.onHover.borderColor);
// secondary
variables['@button-secondary-background'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.color);
variables['@button-secondary-color'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.backgroundColor);
variables['@button-secondary-border'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.backgroundColor);
variables['@button-secondary-hover-background'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.backgroundColor);
variables['@button-secondary-hover-color'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.color);
variables['@button-secondary-hover-border'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.borderColor);
variables['@button-secondary-active-background'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.backgroundColor);
variables['@button-secondary-active-color'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.color);
variables['@button-secondary-active-border'] = Layout.convertRGBAtoRGB(options.buttons.lightBackground.borderColor);
}
return variables;
}
return null;
}
public static getUrl(url) {
return 'url("' + url + '")';
}
public static convertRGBAtoRGB(color: string): string {
if(color.includes('rgba')) {
const regexPattern = /rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)/;
const matches = color.match(regexPattern);
const [, r, g, b, a] = matches;
let R = parseInt(r)*parseFloat(a) + (1 - parseFloat(a))*255;
let G = parseInt(g)*parseFloat(a) + (1 - parseFloat(a))*255;
let B = parseInt(b)*parseFloat(a) + (1 - parseFloat(a))*255;
return 'rgb(' + R + ',' + G + ',' + B + ',' + ')';
} else {
return color;
}
}
}
export class CustomizationOptions {
identity: {
mainColor: string;
secondaryColor: string;
customCss: string;
};
identityIsCustom: boolean;
backgroundsIsCustom: boolean;
buttonsIsCustom: boolean;
identityIsCustom:boolean;
backgroundsAndButtonsIsCustom:boolean;
backgrounds: {
dark: {
color: string; //background
color: string; //background
}
light: {
color: string; //background
@ -107,8 +25,7 @@ export class CustomizationOptions {
color: string; //background
imageUrl: string;
imageFile: string;
position: string;
fontsDarkMode:boolean;
position:string;
}
};
buttons: {
@ -117,34 +34,31 @@ export class CustomizationOptions {
};
constructor(mainColor: string = null, secondaryColor: string = null) {
this.identity = {
this.identity= {
mainColor: mainColor ? mainColor : CustomizationOptions.getIdentity().mainColor,
secondaryColor: secondaryColor ? secondaryColor : CustomizationOptions.getIdentity().secondaryColor,
customCss: ""
secondaryColor : secondaryColor ? secondaryColor : CustomizationOptions.getIdentity().secondaryColor,
};
this.identityIsCustom = false;
this.backgroundsIsCustom = false;
this.buttonsIsCustom = false;
this.backgrounds = {
dark: {
this.backgroundsAndButtonsIsCustom = false;
this.backgrounds={
dark : {
color: this.identity.mainColor,
},
light: {
color: "#f9f9f9" //CustomizationOptions.getRGBA(this.identity.mainColor,0.05),
light : {
color: CustomizationOptions.getRGBA(this.identity.mainColor,0.05),
},
form: {
color: CustomizationOptions.getRGBA(this.identity.mainColor, 0.15),
imageUrl: null,
imageFile: null,
position: null,
fontsDarkMode: true
form : {
color: CustomizationOptions.getRGBA(this.identity.mainColor,0.15),
imageUrl : null,
imageFile : null,
position: null
}
};
this.buttons = {
darkBackground: {
isDefault: true,
isDefault:true,
backgroundColor: "#ffffff",
color: "#000000",
borderStyle: "solid",
@ -158,7 +72,7 @@ export class CustomizationOptions {
}
},
lightBackground: {
isDefault: true,
isDefault:true,
backgroundColor: this.identity.mainColor,
color: '#ffffff',
borderStyle: "solid",
@ -171,110 +85,93 @@ export class CustomizationOptions {
borderColor: this.identity.secondaryColor,
}
}
};
}
public static checkForObsoleteVersion(current: CustomizationOptions, communityId: string) {
if(communityId === 'connect') {
return null;
}
let defaultCO = new CustomizationOptions(CustomizationOptions.getIdentity(communityId).mainColor, CustomizationOptions.getIdentity(communityId).secondaryColor);
public static checkForObsoleteVersion(current:CustomizationOptions, communityId:string){
let defaultCO = new CustomizationOptions(CustomizationOptions.getIdentity(communityId).mainColor,CustomizationOptions.getIdentity(communityId).secondaryColor);
let updated = Object.assign({}, defaultCO);
if (!current) {
current = Object.assign({}, defaultCO);
} else {
if (current.identity && current.identity.mainColor && current.identity.secondaryColor) {
updated = new CustomizationOptions(current.identity.mainColor, current.identity.secondaryColor);
}
if(current.identity && !current.identity.customCss){
current.identity.customCss = defaultCO.identity.customCss;
}
if (!current.backgrounds) {
current.backgrounds = Object.assign({}, updated.backgrounds);
}
if (!current.backgrounds.dark) {
current.backgrounds.dark = Object.assign({}, updated.backgrounds.dark);
}
if (!current.backgrounds.light) {
current.backgrounds.light = Object.assign({}, updated.backgrounds.light);
}
if (!current.backgrounds.form) {
current.backgrounds.form = Object.assign({}, updated.backgrounds.form);
}
if (!current.backgrounds.form.position) {
current.backgrounds.form.position = "center bottom"
}
if (current.backgrounds.form.fontsDarkMode == undefined) {
current.backgrounds.form.fontsDarkMode = true;
}
if (!current.buttons) {
current.buttons = Object.assign({}, updated.buttons);
}
if (!current.buttons.darkBackground) {
current.buttons.darkBackground = Object.assign({}, updated.buttons.darkBackground);
}
if (!current.buttons.lightBackground) {
current.buttons.lightBackground = Object.assign({}, updated.buttons.lightBackground);
}
if (!current.hasOwnProperty('identityIsCustom')) {
current.identityIsCustom = (JSON.stringify(current.identity) != JSON.stringify(defaultCO.identity));
}
if (!current.hasOwnProperty('backgroundsAndButtonsIsCustom') || (!current.hasOwnProperty('backgroundsIsCustom') || (!current.hasOwnProperty('buttonsIsCustom')))) {
current.identityIsCustom = (JSON.stringify(current.backgrounds) !=
JSON.stringify(updated.backgrounds) || JSON.stringify(current.buttons) != JSON.stringify(updated.buttons));
}
if(current.identity && current.identity.mainColor && current.identity.secondaryColor ) {
updated = new CustomizationOptions(current.identity.mainColor, current.identity.secondaryColor);
}
if(!current.backgrounds){
current.backgrounds = Object.assign({}, updated.backgrounds);
}
if(!current.backgrounds.dark){
current.backgrounds.dark = Object.assign({}, updated.backgrounds.dark);
}
if(!current.backgrounds.light){
current.backgrounds.light = Object.assign({}, updated.backgrounds.light);
}
if(!current.backgrounds.form){
current.backgrounds.form = Object.assign({}, updated.backgrounds.form);
}
if(!current.backgrounds.form.position){
current.backgrounds.form.position = "center bottom"
}
if(!current.buttons){
current.buttons = Object.assign({}, updated.buttons);
}
if(!current.buttons.darkBackground){
current.buttons.darkBackground = Object.assign({}, updated.buttons.darkBackground);
}
if(!current.buttons.lightBackground){
current.buttons.lightBackground = Object.assign({}, updated.buttons.lightBackground);
}
if(!current.hasOwnProperty('identityIsCustom')){
current.identityIsCustom = (JSON.stringify(current.identity) != JSON.stringify(defaultCO.identity));
}
if(!current.hasOwnProperty('backgroundsAndButtonsIsCustom')){
current.identityIsCustom = (JSON.stringify(current.backgrounds) != JSON.stringify(updated.backgrounds) || JSON.stringify(current.buttons) != JSON.stringify(updated.buttons)) ;
}
return current;
}
public static getIdentity(community: string = null) {
let COLORS = {
default: {
mainColor: '#4687E6',
public static getIdentity(community:string=null){
let COLORS= {
default:{
mainColor:'#4687E6',
secondaryColor: '#2D72D6'
},
"covid-19": {
mainColor: "#03ADEE",
"covid-19":{
mainColor:"#03ADEE",
secondaryColor: "#F15157"
}
};
if (community && COLORS[community]) {
if(community && COLORS[community]){
return COLORS[community];
}
return COLORS.default;
}
public static getRGBA(color, A) {
if (color.indexOf("#") != -1) {
return 'rgba(' + parseInt(color.substring(1, 3), 16) + ',' + parseInt(color.substring(3, 5), 16) + ',' + parseInt(color.substring(5, 7), 16) + ',' + A + ')';
public static getRGBA(color, A){
if(color.indexOf("#")!=-1){
return 'rgba('+parseInt(color.substring(1,3),16)+','+parseInt(color.substring(3,5),16)+','+parseInt(color.substring(5,7),16)+','+A+')';
}
return color;
}
public static isForLightBackground(color: string) {
public static isForLightBackground(color:string){
let L, r, g, b, a = 1;
if (color.length == 7 || color.length == 9) {
if(color.length == 7 || color.length == 9) {
r = parseInt(color.substring(1, 3), 16);
g = parseInt(color.substring(3, 5), 16);
b = parseInt(color.substring(5, 7), 16);
if (color.length == 9) {
a = parseInt(color.substring(7, 9), 16);
if(color.length == 9) {
a = parseInt(color.substring(7, 9), 16);
}
} else if (color.length > 9) {
}else if(color.length > 9){
let array = color.split("rgba(")[1].split(")")[0].split(",");
r = parseInt(array[0]);
g = parseInt(array[1]);
b = parseInt(array[2]);
a = +array[3];
}
const brightness = r * 0.299 + g * 0.587 + b * 0.114 + (1 - a) * 255;
const brightness = r* 0.299 + g * 0.587 + b * 0.114 + (1 - a) * 255;
return (brightness < 186)
// return !(r*0.299 + g*0.587 + b*0.114 > 186);
/*for(let c of [r,g,b]){
c = c / 255.0;
@ -288,12 +185,11 @@ export class CustomizationOptions {
return L > 0.179// (L + 0.05) / (0.05) > (1.0 + 0.05) / (L + 0.05); //use #000000 else use #ffffff
*/
}
}
export class ButtonsCustomization {
isDefault: boolean;
}
export class ButtonsCustomization{
isDefault:boolean;
backgroundColor: string;
color: string;
borderStyle: string;

View File

@ -5,14 +5,13 @@ import {map} from "rxjs/operators";
import {BehaviorSubject, from, Observable, Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {StringUtils} from "../../utils/string-utils.class";
import {SelectionCriteria} from "../../utils/entities/contentProvider";
@Injectable({providedIn: 'root'})
export class CommunityService {
public community: BehaviorSubject<CommunityInfo> = new BehaviorSubject(null);
public communityId: string = null;
private promise: Promise<void> = null;
private promise: Promise<boolean> = null;
private subs = [];
constructor(private http: HttpClient) {}
@ -41,7 +40,7 @@ export class CommunityService {
getCommunity(communityId: string, refresh = false) {
if (this.communityId !== communityId || !this.community.value || refresh) {
this.communityId = communityId;
this.promise = new Promise<void>((resolve, reject) => {
this.promise = new Promise<any>((resolve, reject) => {
this.subs.push(this.getCommunityInfo(communityId).subscribe(community => {
this.community.next(community);
resolve();
@ -57,7 +56,6 @@ export class CommunityService {
async getCommunityAsync() {
await this.promise;
// this.clearSubscriptions();
return this.community.getValue();
}
@ -73,62 +71,57 @@ export class CommunityService {
return this.http.post(url, community, options);
}
public updateSubjects(subjects: string[], fos: string[], sdg: string[]) {
let communityInfo: CommunityInfo = this.community.value;
communityInfo.subjects = subjects;
communityInfo.fos = fos;
communityInfo.sdg = sdg;
this.community.next(communityInfo);
}
public updateAdvancedCriteria(selectionCriteria: SelectionCriteria) {
let communityInfo: CommunityInfo = this.community.value;
communityInfo.selectionCriteria = selectionCriteria;
this.community.next(communityInfo);
}
public parseCommunity(data: any): CommunityInfo {
const resData = Array.isArray(data) ? data[0] : data;
const community: CommunityInfo = new CommunityInfo();
community.title = resData.name;
community.shortTitle = resData.shortName;
community.displayTitle = resData.displayName?resData.displayName:resData.name;
community.displayShortTitle = resData.displayShortName?resData.displayShortName:resData.shortName;
community.communityId = resData.id;
community.queryId = resData.queryId;
community.logoUrl = resData.logoUrl;
community.description = resData.description;
community.date = resData.creationDate;
community.zenodoCommunity = resData.zenodoCommunity;
community.status = 'PUBLIC';
community.claim = resData.claim;
community.membership = resData.membership;
community.type = resData.type;
community.plan = resData.plan?resData.plan:"Default";
community.otherZenodoCommunities = resData.otherZenodoCommunities;
community['title'] = resData.name;
community['shortTitle'] = resData.shortName;
community['communityId'] = resData.id;
community['queryId'] = resData.queryId;
community['logoUrl'] = resData.logoUrl;
community['description'] = resData.description;
community['date'] = resData.creationDate;
community['zenodoCommunity'] = resData.zenodoCommunity;
community['status'] = 'all';
if (resData.hasOwnProperty('status')) {
community.status = resData.status;
community.validateStatus();
community['status'] = resData.status;
const status = ['all', 'hidden', 'manager'];
if (status.indexOf(community['status']) === -1) {
community['status'] = 'hidden';
}
}
if (resData.type != null) {
community['type'] = resData.type;
}
if (resData.managers != null) {
if (community['managers'] === undefined) {
community['managers'] = new Array<string>();
}
const managers = resData.managers;
const length = Array.isArray(managers) ? managers.length : 1;
for (let i = 0; i < length; i++) {
const manager = Array.isArray(managers) ? managers[i] : managers;
community.managers[i] = manager;
}
}
if (resData.subjects != null) {
community.subjects = Array.isArray(resData.subjects)?resData.subjects:[resData.subjects];
} else {
community.subjects = [];
}
if (resData.sdg != null) {
community.sdg = Array.isArray(resData.sdg)?resData.sdg:[resData.sdg];
} else {
community.sdg = [];
}
if (resData.fos != null) {
community.fos = Array.isArray(resData.fos)?resData.fos:[resData.fos];
} else {
community.fos = [];
}
if (resData.advancedConstraints != null) {
community.selectionCriteria = resData.advancedConstraints;
} else {
community.selectionCriteria = new SelectionCriteria();
if (community['subjects'] === undefined) {
community['subjects'] = new Array<string>();
}
const subjects = resData.subjects;
const length = Array.isArray(subjects) ? subjects.length : 1;
for (let i = 0; i < length; i++) {
const subject = Array.isArray(subjects) ? subjects[i] : subjects;
community.subjects[i] = subject;
}
}
return CommunityInfo.checkIsUpload(community);
}

View File

@ -1,11 +1,9 @@
import {StringUtils} from "../../utils/string-utils.class";
import {SelectionCriteria} from "../../utils/entities/contentProvider";
import {properties} from "../../../../environments/environment";
export class CommunityInfo {
title: string;
shortTitle:string;
displayTitle: string;
displayShortTitle:string;
communityId: string;
queryId: string;
type: string;
@ -15,19 +13,12 @@ export class CommunityInfo {
managers: string[];
date:Date;
subjects: string[];
status:"all" | "manager" | "hidden" | "PUBLIC" | "RESTRICTED" | "PRIVATE";
claim: "all" | "managersOnly" | "membersOnly";
membership: "open" | "byInvitation";
status:string;
zenodoCommunity:string;
otherZenodoCommunities: string[];
isUpload: boolean;
isSubscribed: boolean;
isManager: boolean;
fos: string[] = [];
sdg: string[] = []
selectionCriteria: SelectionCriteria;
plan: "Standard" | "Advanced" | "Premium" | "National" | "Default" ;
public static checkIsUpload(response: CommunityInfo | CommunityInfo[]): any | any[] {
if (Array.isArray(response)) {
response.forEach(value => {
@ -38,24 +29,5 @@ export class CommunityInfo {
}
return response;
}
public isOpen() {
return !(this.membership && this.membership === 'byInvitation');
}
public isPublic(){
return this.status == "all" || this.status == "PUBLIC";
}
public isRestricted(){
return this.status == "manager" || this.status == "RESTRICTED";
}
public isPrivate(){
return this.status == "hidden" || this.status == "PRIVATE";
}
public validateStatus(){
if(!(this.isPrivate() || this.isRestricted() || this.isPublic())){
this.status = "PRIVATE";
}
}
}
// export const prodReadyCommunities = ["dh-ch", "ee", "fam", "mes", "ni", "covid-19", "dariah", "epos", "egi"];

View File

@ -1,13 +1,20 @@
import {filter, map, mergeMap, take} from 'rxjs/operators';
import {Injectable} from '@angular/core';
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
import {
ActivatedRouteSnapshot,
CanActivate,
CanActivateChild,
Router,
RouterStateSnapshot,
UrlTree
} from '@angular/router';
import {Observable, of} from 'rxjs';
import {Session} from '../../login/utils/helper.class';
import {LoginErrorCodes} from '../../login/utils/guardHelper.class';
import {UserManagementService} from "../../services/user-management.service";
@Injectable()
export class ConnectAdminLoginGuard {
export class ConnectAdminLoginGuard implements CanActivate, CanActivateChild {
constructor(private router: Router,
private userManagementService: UserManagementService) {
@ -15,9 +22,8 @@ export class ConnectAdminLoginGuard {
check(community: string, path: string): Observable<boolean> | boolean {
let errorCode = LoginErrorCodes.NOT_LOGIN;
const authorized = this.userManagementService.getUserInfo().pipe(take(1), map(user => {
const authorized = this.userManagementService.getUserInfo(false).pipe(take(1), map(user => {
if (user) {
errorCode = LoginErrorCodes.NOT_ADMIN;
if (Session.isPortalAdministrator(user) || Session.isCommunityCurator(user) || Session.isManager('community', community, user)) {
return of(true);
}

View File

@ -22,7 +22,7 @@ export class ConnectCommunityGuard implements CanActivate, CanActivateChild {
check(community: string, url: string): Observable<boolean> | boolean {
return this.communityService.isCommunityType(community).pipe(take(1), tap(isCommunity => {
if (!isCommunity) {
this.router.navigate([properties.errorLink], {queryParams: {'page': url}});
this.router.navigate(['/error'], {queryParams: {'page': url}});
}
}));
}

View File

@ -10,7 +10,6 @@ import {
} from '@angular/router';
import {Observable, Subscription} from 'rxjs';
import {CommunityService} from '../community/community.service';
import {properties} from "../../../../environments/environment";
@Injectable()
export class ConnectRIGuard implements CanActivate, CanActivateChild {
@ -23,7 +22,7 @@ export class ConnectRIGuard implements CanActivate, CanActivateChild {
check(community: string, url: string): Observable<boolean> | boolean {
return this.communityService.isRIType(community).pipe(tap(authorized => {
if (!authorized) {
this.router.navigate([properties.errorLink], {queryParams: {'page': url}});
this.router.navigate(['/error'], {queryParams: {'page': url}});
}
}));
}

View File

@ -30,7 +30,7 @@ export class ConnectSubscriberGuard implements CanActivate, CanActivateChild {
} else {
community = ConnectHelper.getCommunityFromDomain(properties.domain);
}
const authorized = this.userManagementService.getUserInfo().pipe(take(1), map(user => {
const authorized = this.userManagementService.getUserInfo(false).pipe(take(1), map(user => {
if (user) {
if (Session.isSubscribedTo('community', community, user)) {
return of(true);

View File

@ -1,5 +1,11 @@
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, Router, RouterStateSnapshot, UrlTree} from '@angular/router';
import { Injectable } from '@angular/core';
import {
Router,
CanActivate,
ActivatedRouteSnapshot,
RouterStateSnapshot,
CanLoad, Route, UrlSegment, CanActivateChild, UrlTree
} from '@angular/router';
import {Observable} from 'rxjs';
import {ConnectHelper} from '../connectHelper';
@ -8,7 +14,7 @@ import {CommunityService} from "../community/community.service";
import {map} from "rxjs/operators";
@Injectable()
export class IsCommunity {
export class IsCommunity implements CanActivate, CanActivateChild {
constructor(private router: Router,
private communityService: CommunityService) {
@ -26,12 +32,12 @@ export class IsCommunity {
if(community) {
return true;
} else {
this.router.navigate([properties.errorLink], {queryParams: {page: state.url}});
this.router.navigate(['error'], {queryParams: {page: state.url}});
return false;
}
}));
} else {
this.router.navigate([properties.errorLink], {queryParams: {page: state.url}});
this.router.navigate(['error'], {queryParams: {page: state.url}});
return false;
}
}

View File

@ -1,15 +0,0 @@
import { NgModule} from '@angular/core';
import { RouterModule } from '@angular/router';
import {CuratorsComponent} from "./curators.component";
import {IsRouteEnabled} from "../../../error/isRouteEnabled.guard";
import {PreviousRouteRecorder} from "../../../utils/piwik/previousRouteRecorder.guard";
@NgModule({
imports: [
RouterModule.forChild([
{ path: '', component: CuratorsComponent, canActivate: [IsRouteEnabled], canDeactivate: [PreviousRouteRecorder]}
])
]
})
export class CuratorsRoutingModule {
}

View File

@ -1,152 +0,0 @@
<schema2jsonld *ngIf="url" [URL]="url" [name]="pageTitle" type="other"></schema2jsonld>
<ng-container *ngIf="longView else shortView">
<div style="min-height: 650px;">
<div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom">
<div class="uk-padding-small uk-padding-remove-horizontal">
<breadcrumbs [breadcrumbs]="breadcrumbs"></breadcrumbs>
</div>
</div>
<div class="uk-container uk-container-large uk-section uk-section-small">
<div *ngIf="showLoading" class="uk-margin-large uk-padding-large uk-padding-remove-horizontal">
<loading></loading>
</div>
<div *ngIf="!showLoading">
<h1 class="uk-margin-top">
Curators
</h1>
<div *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0" class="uk-margin-medium">
<helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0"
[texts]="pageContents['top']">
</helper>
</div>
<div *ngIf="curators" class="uk-margin-large-top">
<div *ngFor="let curator of curators let i=index;" class="uk-card uk-card-default uk-padding uk-margin-medium-bottom">
<div class="uk-grid" uk-grid>
<div class="uk-width-2-3@m uk-flex uk-flex-middle">
<div class="uk-width-small">
<img *ngIf="curator.photo && curator.photo !== ''" class="uk-border-circle" style="width: 150px; height: 150px;"
src="{{downloadUrl + curator.photo}}" alt="Curator Photo">
<img *ngIf="!curator.photo || curator.photo == ''" class="uk-border-circle" style="width: 150px; height: 150px;"
src="../../assets/common-assets/curator-default.png" alt="Curator Photo">
</div>
<div class="uk-width-expand">
<div class="uk-padding">
<h4 class="uk-margin-remove">{{curator.name}}</h4>
<div *ngIf="curator.bio" class="uk-margin-top uk-height-max-large uk-overflow-auto">
<div class="uk-text-muted uk-margin-small-bottom">
Biography
</div>
<div>
<div *ngIf="!viewingMore">{{format(curator.bio)}}</div>
<div *ngIf="viewingMore">{{curator.bio}}</div>
<div *ngIf="curator.bio.length >= maxCharacters" class="uk-text-right uk-margin-small-top">
<a *ngIf="curator.bio.length >= maxCharacters"
(click)="openFsModal(curator)">
View details
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="curator.affiliations && curator.affiliations.length > 0" class="uk-width-1-3@m uk-padding" style="border-left: 1px solid #eaeaea">
<div class="uk-text-muted uk-margin-bottom">
Affiliations
</div>
<div class="uk-grid uk-flex-middle uk-child-width-1-2" uk-grid>
<div *ngFor="let affiliation of curator.affiliations">
<span *ngIf="!affiliation.website_url">
<img [src]="affiliation.logo_url | urlPrefix" [alt]="affiliation.name">
</span>
<a *ngIf="affiliation.website_url"
target="_blank" [href]="affiliation.website_url | urlPrefix">
<img [src]="affiliation.logo_url | urlPrefix" [alt]="affiliation.name">
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="uk-margin-medium">
<helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0"
[texts]="pageContents['bottom']">
</helper>
</div>
</div>
</div>
</ng-container>
<!-- Short view for community's homepage -->
<ng-template #shortView>
<div *ngIf="curators && curators.length > 0" class="uk-grid" uk-grid>
<span class="uk-width-auto">
Curated by:
</span>
<div class="uk-width-expand uk-padding-remove uk-overflow-auto">
<div class="uk-height-max-medium uk-margin-xsmall-left">
<a routerLink="/curators">
<span *ngFor="let curator of curators.slice(0,curatorsLimit) let i=index;">
{{curator.name}}
<span *ngIf="i < curators.length-1 && i < curatorsLimit-1">, </span>
</span>
<span *ngIf="curators.length > curatorsLimit">
+{{curators.length-curatorsLimit}} more
</span>
</a>
</div>
</div>
</div>
</ng-template>
<fs-modal #fsModal classTitle="">
<div *ngIf="curatorInModal" class="uk-width-1-1 uk-height-1-1">
<div class="uk-container uk-container-large uk-section">
<div class="uk-margin-large-top uk-grid uk-grid-large" uk-grid>
<div class="uk-width-1-3@m">
<h2>
{{curatorInModal.name}}
</h2>
<img *ngIf="curatorInModal.photo && curatorInModal.photo !== ''" class="uk-width-2-3 uk-border-circle uk-margin-top uk-margin-bottom"
src="{{downloadUrl + curatorInModal.photo}}" alt="Curator Photo">
<img *ngIf="!curatorInModal.photo || curatorInModal.photo == ''" class="uk-width-2-3 uk-border-circle uk-margin-top uk-margin-bottom"
src="../../assets/common-assets/curator-default.png" alt="Curator Photo">
</div>
<div class="uk-width-2-3@m">
<ul class="uk-tab" uk-tab>
<li>
<a>Biography</a>
</li>
<li *ngIf="curatorInModal.affiliations && curatorInModal.affiliations.length > 0">
<a>Affiliations</a>
</li>
</ul>
<ul class="uk-switcher">
<li class="uk-padding uk-padding-remove-left">
<h5>
Biography
</h5>
<div>
{{curatorInModal.bio}}
</div>
</li>
<li *ngIf="curatorInModal.affiliations && curatorInModal.affiliations.length > 0" class="uk-padding uk-padding-remove-left">
<div class="uk-grid uk-flex-middle uk-child-width-1-3" uk-grid>
<div *ngFor="let affiliation of curatorInModal.affiliations">
<span *ngIf="!affiliation.website_url">
<img [src]="affiliation.logo_url | urlPrefix" [alt]="affiliation.name">
</span>
<a *ngIf="affiliation.website_url"
target="_blank" [href]="affiliation.website_url | urlPrefix">
<img [src]="affiliation.logo_url | urlPrefix" [alt]="affiliation.name">
</a>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</fs-modal>

View File

@ -1,154 +0,0 @@
import {Component, Input, ViewChild} from '@angular/core';
import {EnvProperties} from '../../../utils/properties/env-properties';
import {CuratorService} from "../../curators/curator.service";
import {Curator} from "../../../utils/entities/CuratorInfo";
import {ActivatedRoute, Router} from "@angular/router";
import {CommunityService} from "../../community/community.service";
import {HelperService} from "../../../utils/helper/helper.service";
import {Meta, Title} from "@angular/platform-browser";
import {SEOService} from "../../../sharedComponents/SEO/SEO.service";
import {PiwikService} from "../../../utils/piwik/piwik.service";
import {Breadcrumb} from "../../../utils/breadcrumbs/breadcrumbs.component";
import {Subscription} from "rxjs";
import {properties} from "../../../../../environments/environment";
import {UserRegistryService} from "../../../services/user-registry.service";
import {FullScreenModalComponent} from '../../../utils/modal/full-screen-modal/full-screen-modal.component';
import {CommunityInfo} from "../../community/communityInfo";
@Component({
selector: 'curators',
templateUrl: './curators.component.html'
})
export class CuratorsComponent {
@Input() longView = true;
community: CommunityInfo;
public downloadUrl = null;
public showLoading = true;
public curators: Curator[] = [];
public curatorsLimit: number = 5;
public numberOfCurators: number = 5;
public showMore = [];
public maxCharacters = 450;
public viewingMore: boolean = false;
public curatorInModal;
public properties: EnvProperties = properties;
public pageContents = null;
public divContents = null;
public url: string = null;
public pageTitle: string = "Curators";
public breadcrumbs: Breadcrumb[] = [{name: 'Home', route: '/'}, {name: 'About - Curators'}];
subs: Subscription[] = [];
@ViewChild('fsModal', { static: true }) fsModal: FullScreenModalComponent;
constructor(private route: ActivatedRoute,
private curatorsService: CuratorService,
private communityService: CommunityService,
private userRegistryService: UserRegistryService,
private _router: Router,
private helper: HelperService,
private _meta: Meta,
private _title: Title,
private seoService: SEOService,
private _piwikService: PiwikService) {
}
ngOnInit() {
this.showLoading = true;
this.downloadUrl = this.properties.utilsService + '/download/';
//if (properties.environment !== 'development') {
if (!this.longView) {
this.subs.push(this.communityService.getCommunityAsObservable().subscribe(community => {
if (community) {
this.community = community;
this.getCurators();
}
}));
} else {
this.subs.push(this.communityService.getCommunityAsObservable().subscribe(community => {
if (community) {
this.community = community;
this.subs.push(this._piwikService.trackView(this.properties, this.pageTitle).subscribe());
this.url = this.properties.domain + this._router.url;
this.seoService.createLinkForCanonicalURL(this.url);
this.updateUrl(this.url);
this.updateTitle(this.pageTitle);
this.updateDescription("OpenAIRE - Connect, Community Gateway, research community");
//this.getDivContents();
this.getPageContents();
this.getCurators();
}
}));
}
}
ngOnDestroy() {
for (let sub of this.subs) {
sub.unsubscribe();
}
}
private getCurators() {
this.subs.push(this.curatorsService.getCurators(this.community.communityId).subscribe(curators => {
this.curators = curators;
this.showLoading = false;
}, error => {
console.error(error);
this.curators = [];
this.showLoading = false;
}));
}
private getPageContents() {
this.subs.push(this.helper.getPageHelpContents(this.properties, this.community.communityId, this._router.url).subscribe(contents => {
this.pageContents = contents;
}));
}
private getDivContents() {
this.subs.push(this.helper.getDivHelpContents(this.properties, this.community.communityId, this._router.url).subscribe(contents => {
this.divContents = contents;
}));
}
format(name: string) {
if (name) {
return (((name).length > this.maxCharacters) ? (name.substring(0, (this.maxCharacters - ('...').length)) + '...') : name);
} else {
return null;
}
}
public viewMore() {
this.viewingMore = !this.viewingMore;
}
public openFsModal(curator) {
this.curatorInModal = curator;
this.fsModal.title = this.community.shortTitle + ' Curator';
this.fsModal.open();
}
private updateDescription(description: string) {
this._meta.updateTag({content: description}, "name='description'");
this._meta.updateTag({content: description}, "property='og:description'");
}
private updateTitle(title: string) {
var _title = ((title.length > 50) ? title.substring(0, 50) : title);
this._title.setTitle(_title);
this._meta.updateTag({content: _title}, "property='og:title'");
}
private updateUrl(url: string) {
this._meta.updateTag({content: url}, "property='og:url'");
}
}

View File

@ -1,35 +0,0 @@
import { NgModule} from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import {CuratorsComponent} from './curators.component';
import {CuratorService} from "../../curators/curator.service";
import {CuratorsRoutingModule} from "./curators-routing.module";
import {HelperModule} from "../../../utils/helper/helper.module";
import {Schema2jsonldModule} from "../../../sharedComponents/schema2jsonld/schema2jsonld.module";
import {SEOServiceModule} from "../../../sharedComponents/SEO/SEOService.module";
import {PiwikServiceModule} from "../../../utils/piwik/piwikService.module";
import {BreadcrumbsModule} from "../../../utils/breadcrumbs/breadcrumbs.module";
import {UrlPrefixModule} from "../../../utils/pipes/url-prefix.module";
import {LoadingModule} from '../../../utils/loading/loading.module';
import {FullScreenModalModule} from '../../../utils/modal/full-screen-modal/full-screen-modal.module';
import {AffiliationsModule} from "../../affiliations/affiliations.module";
@NgModule({
imports: [
CommonModule, FormsModule, RouterModule,
CuratorsRoutingModule, AffiliationsModule, HelperModule,
Schema2jsonldModule, SEOServiceModule, PiwikServiceModule,
BreadcrumbsModule, UrlPrefixModule, LoadingModule,
FullScreenModalModule
],
declarations: [
CuratorsComponent
],
providers: [CuratorService],
exports: [
CuratorsComponent
]
})
export class CuratorsModule {}

View File

@ -1,21 +1,15 @@
import {HttpParams} from '@angular/common/http';
import {properties} from "../../../environments/environment";
import {Session} from "../login/utils/helper.class";
import {CommunityInfo} from "./community/communityInfo";
export class ConnectHelper {
public static getCommunityFromDomain(domain: string): string{
if(properties.dashboard === 'irish') {
return properties.adminToolsCommunity;
}
if(properties.environment == "development" &&
(properties.adminToolsPortalType == "connect" || properties.adminToolsPortalType == "community"
|| properties.adminToolsPortalType == "aggregator" || properties.adminToolsPortalType == "eosc")) {
// domain = "covid-19.openaire.eu"; //for testing
if(properties.environment == "development") {
domain = "covid-19.openaire.eu"; //for testing
}
domain = domain.indexOf("//") != -1? domain.split("//")[1]:domain; //remove https:// prefix
if (domain.indexOf('eosc-portal.eu') != -1 || domain.indexOf('eosc-beyond.eu') != -1) {
if (domain.indexOf('eosc-portal.eu') != -1) {
return "eosc";
}
if (domain.indexOf('openaire.eu') === -1) {
@ -24,7 +18,7 @@ export class ConnectHelper {
if ( domain.indexOf('beta') !== -1) {
domain = domain.substr(domain.indexOf('.') + 1, domain.length);
domain = domain.substr(0, domain.indexOf('.'));
} else if (domain.indexOf('test.') !== -1 && !(properties.adminToolsPortalType == "connect" || properties.adminToolsPortalType == "community")) {
} else if (domain.indexOf('test.') !== -1) {
return null;
} else {
domain = domain.substr(0, domain.indexOf('.'));
@ -57,12 +51,7 @@ export class ConnectHelper {
}
public static isPrivate(community: CommunityInfo, user) {
return community && (community.isPrivate() || (community.isRestricted() && !(
Session.isPortalAdministrator(user) ||
Session.isCommunityCurator(user) ||
Session.isManager("community", community.communityId, user) ||
(!community.isOpen() && Session.isMember('community', community.communityId, user))
)))
public static isPrivate(community, user) {
return community && (community.status == "hidden" || (community.status == "manager" && !(Session.isPortalAdministrator(user) || Session.isCommunityCurator(user) || Session.isManager("community", community.communityId, user))))
}
}

View File

@ -6,13 +6,13 @@ import {map} from "rxjs/operators";
@Injectable()
export class SearchCommunityDataprovidersService {
constructor(private http: HttpClient ) {}
searchDataproviders (properties:EnvProperties, pid: string, deposit = false):any {
let url = properties.communityAPI+pid+"/datasources" + (deposit?'?deposit=true':'');
searchDataproviders (properties:EnvProperties, pid: string):any {
let url = properties.communityAPI+pid+"/contentproviders";
return this.http.get((properties.useCache)? (properties.cacheUrl+encodeURIComponent(url)): url);
}
countTotalDataproviders(properties:EnvProperties,pid:string) {
let url = properties.communityAPI+pid+"/datasources";
let url = properties.communityAPI+pid+"/contentproviders";
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => res['length']));
}

View File

@ -4,7 +4,6 @@ import {Observable} from 'rxjs';
import {Curator} from '../../utils/entities/CuratorInfo';
import {EnvProperties} from '../../utils/properties/env-properties';
import {CustomOptions} from "../../services/servicesUtils/customOptions.class";
import {properties} from '../../../../environments/environment';
@Injectable()
export class CuratorService {
@ -12,17 +11,17 @@ export class CuratorService {
constructor(private http: HttpClient) {
}
public getCurators(communityId: string): Observable<Curator[]> {
let url: string = properties.adminToolsAPIURL + communityId + '/curator';
public getCurators(properties: EnvProperties, communityId: string): Observable<Curator[]> {
let url: string = properties.adminToolsAPIURL + '/' + communityId + '/curator';
return this.http.get<Curator[]>((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url);
}
public updateCurator(curator: Curator) {
public updateCurator(properties: EnvProperties, curator: Curator) {
let url: string = properties.adminToolsAPIURL + "curator";
return this.http.post<Curator>(url, curator, CustomOptions.registryOptions());
}
public getCurator(): Observable<Curator> {
public getCurator(properties: EnvProperties): Observable<Curator> {
let url: string = properties.adminToolsAPIURL + 'curator';
return this.http.get<Curator>((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url, CustomOptions.registryOptions());
}

View File

@ -7,25 +7,15 @@ import {map} from "rxjs/operators";
export class SearchCommunityProjectsService {
constructor(private http: HttpClient ) {}
searchProjects (properties:EnvProperties, pid: string, page=1, size=500):any {
return this.searchProjectsWithPaging(properties,pid,page, size, null, null);
}
searchProjectsWithPaging (properties:EnvProperties, pid: string, page=1, size=500, searchFilter, funder, orderBy = "name"):any {
let params = funder ? ["funder="+ funder] :[];
if (searchFilter) {
params.push("searchFilter="+ searchFilter)
}
params.push("orderBy="+ orderBy);
let url = properties.communityAPI+pid+"/projects/"+ (page-1) + "/" + size + (params.length > 0?"?" + params.join("&"):"");
searchProjects (properties:EnvProperties, pid: string):any {
let url = properties.communityAPI+pid+"/projects";
return this.http.get((properties.useCache)? (properties.cacheUrl+encodeURIComponent(url)): url);
//.map(res => <any> res.json())
}
countTotalProjects(properties:EnvProperties,pid:string) {
let url = properties.communityAPI+pid+"/projects/0/1";
let url = properties.communityAPI+pid+"/projects";
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => res['totalElements']));
}
getProjectFunders(properties:EnvProperties,pid:string) {
let url = properties.communityAPI+pid+"/funders";
return this.http.get<string[]>((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url);
.pipe(map(res => res['length']));
}
}

View File

@ -0,0 +1,55 @@
<div *ngIf="!hidden" class="">
<div *ngIf="showSaveResetButtons" class="uk-article-title custom-article-title">
User Email Preferences for Claims Notifications
</div>
<div *ngIf="userValidMessage.length > 0" class = "uk-alert uk-alert-danger uk-animation-fade" role="alert">
{{userValidMessage}}
</div>
<div *ngIf="savedMessage.length > 0" class="uk-alert uk-alert-success uk-animation-fade" role="alert">
{{savedMessage}}
</div>
<errorMessages [status]="[status]" [type]="'notification preferences'"></errorMessages>
<div *ngFor="let notification of notifications; let i=index" >
<!-- <div class="uk-accordion-title">Email preferences for {{preferencesFor}}: <strong>{{notification.openaireName}}</strong></div>-->
<!-- <div class="uk-accordion-content">-->
<form class="uk-form-horizontal"><!-- [formGroup]="myForm"-->
<!--[ngClass]="{'has-error':!myForm.controls.notify.valid && myForm.controls.notify.dirty}"-->
<div class="uk-margin uk-grid">
<div class=" inherit-color uk-width-medium"
title="Get e-mail notification when there are new user links related your community">Notify
for new user links:</div>
<mat-slide-toggle [checked]="notification.notify"
(change)="($event.source.checked = notification.notify);changeNotify(notification, !notification.notify, i)"></mat-slide-toggle>
</div>
<div *ngIf="notification.notify" [class]="notification.notify ? 'uk-margin' :
'uk-margin cursor-not-allowed'">
<div class="uk-form-label inherit-color">Frequency:</div>
<div class="uk-form-controls">
<select [class]="notification.notify ? 'uk-select' : 'uk-select uk-disabled'" id="form-horizontal-select"
[(ngModel)]="notification.frequency" (ngModelChange)="changeFrequency(i)" name="select_frequency">
<option [ngValue]="24" >Daily</option>
<option [ngValue]="48" >Every two days</option>
<option [ngValue]="168">Weekly</option>
</select>
</div>
</div>
<div *ngIf="showSaveResetButtons" class="uk-float-right">
<button type="submit" class="uk-button uk-button-primary" (click)="saveNotification(i)">Save Changes</button>
<button type="submit" class="uk-button" (click)="restoreNotification(i)">Reset</button>
</div>
</form>
</div>
<!-- </div>-->
<!-- </ul>-->
</div>

View File

@ -0,0 +1,259 @@
import {Component, Input} from '@angular/core';
import {Location} from '@angular/common';
import {ActivatedRoute, Router} from '@angular/router';
import {Session} from '../../login/utils/helper.class';
import {EnvProperties} from '../../utils/properties/env-properties';
import {MailPrefsService} from './mailPrefs.service';
import {ConnectHelper} from '../connectHelper';
import {ErrorCodes} from '../../utils/properties/errorCodes';
import {ErrorMessagesComponent} from '../../utils/errorMessages.component';
import {LoginErrorCodes} from '../../login/utils/guardHelper.class';
import {properties} from "../../../../environments/environment";
import {Subscriber} from "rxjs";
declare var UIkit: any;
@Component({
selector: 'mailPrefs',
templateUrl: 'mailPrefs.component.html',
providers:[MailPrefsService]
})
export class MailPrefsComponent {
properties:EnvProperties;
subscriptions = [];
@Input() communityId: string;
public preferencesFor: string = "community";
public status: number;
public notifications = [];
public initialNotifications = [];
public prefsChanged = {};
public hidden: boolean = true;
//public showForbiddenMessage:boolean = false;
public userValidMessage:string = "";
public savedMessage: string = "";
private errorCodes: ErrorCodes;
private errorMessages: ErrorMessagesComponent;
@Input() showSaveResetButtons: boolean = true;
constructor (private _mailPrefsService: MailPrefsService, private route: ActivatedRoute, private _router:Router, private location: Location) {
this.errorCodes = new ErrorCodes();
this.errorMessages = new ErrorMessagesComponent();
this.status = this.errorCodes.LOADING;
}
ngOnInit() {
this.properties = properties;
this.subscriptions.push(this.route.params.subscribe(params => {
this.hidden = true;
console.debug(this.communityId);
if(!this.communityId){
this.communityId = ConnectHelper.getCommunityFromDomain(this.properties.domain);
}
if(!this.communityId) {
this.communityId = params['community'];
}
console.debug(this.communityId, params)
this.getEmailPreferences();
}));
}
getEmailPreferences() {
if(!Session.isLoggedIn()){
//this.userValidMessage = "User session has expired. Please login again.";
if(this.showSaveResetButtons) {
this._router.navigate(['/user-info'], { queryParams: { "errorCode": LoginErrorCodes.NOT_VALID, "redirectUrl": this._router.url} });
}
} else {
this.status = this.errorCodes.LOADING;
this.savedMessage = "";
if(this.communityId && this.communityId != "openaire") {
this.preferencesFor = "community";
this.subscriptions.push(this._mailPrefsService.getUserEmailPreferencesForCommunity(this.communityId, this.properties.claimsAPIURL).subscribe(
data => {
if(data.code == "204") {
this.status = this.errorCodes.NONE;
this.initialNotifications = [{notify: true, frequency:24, openaireId: this.communityId}];
} else {
this.initialNotifications = data.data;
}
this.notifications = JSON.parse(JSON.stringify( this.initialNotifications ));
this.status = this.errorCodes.DONE;
this.hidden = false;
},
err => {
this.hidden = false;
this.handleErrors(err);
this.handleError("Error getting user email preferences for community with id: "+this.communityId, err);
}
));
} else {
this.preferencesFor = "project";
this.subscriptions.push(this._mailPrefsService.getUserEmailPreferencesForOpenaire(this.properties.claimsAPIURL).subscribe(
data => {
if(data.code == "204") {
this.status = this.errorCodes.NONE;
} else {
this.initialNotifications = data.data;
this.notifications = JSON.parse(JSON.stringify( this.initialNotifications ));
//this.notifications = this.initialNotifications.map(x => Object.assign({}, x));
//this.notifications = this.initialNotifications;
this.status = this.errorCodes.DONE;
}
},
err => {
//console.info(err);
this.handleErrors(err);
this.handleError("Error getting user email preferences for openaire", err);
}
));
}
}
}
changeNotify(notification: any, checked: boolean, index: number) {
if(!Session.isLoggedIn()){
//this.userValidMessage = "User session has expired. Please login again.";
if(this.showSaveResetButtons) {
this._router.navigate(['/user-info'], { queryParams: { "errorCode": LoginErrorCodes.NOT_VALID, "redirectUrl": this._router.url} });
}
} else {
this.savedMessage = "";
this.status = this.errorCodes.DONE;
notification.notify = checked;
this.prefsChanged[index] = true;
}
}
changeFrequency(index: number) {
if(!Session.isLoggedIn()){
//this.userValidMessage = "User session has expired. Please login again.";
if(this.showSaveResetButtons) {
this._router.navigate(['/user-info'], { queryParams: { "errorCode": LoginErrorCodes.NOT_VALID, "redirectUrl": this._router.url} });
}
} else {
this.savedMessage = "";
this.status = this.errorCodes.DONE;
if(this.initialNotifications[index].frequency != this.notifications[index].frequency) {
this.prefsChanged[index] = true;
}
}
}
saveNotification(index: number) {
if(this.notifications.length > 0 && this.initialNotifications.length > 0) {
if(!Session.isLoggedIn()){
//this.userValidMessage = "User session has expired. Please login again.";
if(this.showSaveResetButtons) {
this._router.navigate(['/user-info'], { queryParams: { "errorCode": LoginErrorCodes.NOT_VALID, "redirectUrl": this._router.url} });
}
} else {
if(JSON.stringify(this.notifications[index]) != JSON.stringify(this.initialNotifications[index])) {
this.status = this.errorCodes.LOADING;
this.savedMessage = "";
this.subscriptions.push(this._mailPrefsService.saveUserEmailPreferences(this.notifications[index], this.properties.claimsAPIURL).subscribe(
data => {
this.initialNotifications[index] = JSON.parse(JSON.stringify( this.notifications[index] ));
this.status = this.errorCodes.DONE;
/*UIkit.notification({
message : '<strong>Your email preferences for '+this.notifications[index].openaireName+' have been successfully changed<strong>',
status : 'success',
timeout : 3000,
pos : 'top-center'
});*/
this.savedMessage = "Notification settings for claims saved!";
},
err => {
//console.log(err);
this.handleError("Error saving user email preferences: "+JSON.stringify(this.notifications[index]), err);
this.status = this.errorCodes.NOT_SAVED;
}
));
}
else {
/*UIkit.notification({
message : '<strong>No changes selected for '+this.notifications[index].openaireName+' email preferences<strong>',
status : 'primary',
timeout : 3000,
pos : 'top-center'
});*/
this.savedMessage = "Notification settings for claims saved!";
}
}
}
}
restoreNotification(index: number) {
if(!Session.isLoggedIn()){
//this.userValidMessage = "User session has expired. Please login again.";
if(this.showSaveResetButtons) {
this._router.navigate(['/user-info'], { queryParams: { "errorCode": LoginErrorCodes.NOT_VALID, "redirectUrl": this._router.url} });
}
} else {
if(this.notifications.length > 0 && this.initialNotifications.length > 0) {
this.status = this.errorCodes.LOADING;
this.savedMessage = "";
this.notifications[index] = JSON.parse(JSON.stringify( this.initialNotifications[index] ));
this.status = this.errorCodes.DONE;
this.prefsChanged[index] = false;
}
}
}
/*
prefsChanged(index: number) : boolean {
if(this.notifications.length > 0 && this.initialNotifications.length > 0) {
if(JSON.stringify(this.notifications[index]) != JSON.stringify(this.initialNotifications[index])) {
return true;
}
}
return false;
}
*/
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
}
});
}
handleErrors(err){
//this.showErrorMessage = true;
//try{
var code = "";
if(!err.status) {
var error = err.json();
code = error.code;
} else {
code = err.status;
}
this.status = this.errorMessages.getErrorCode(code);
}
private handleError(message: string, error) {
console.error("User mail notification preferences Page (for claims): "+message, error);
}
//}catch (e) {
//console.log("Couldn't parse answer as json")
//this.showErrorMessage = true;
//}
}

View File

@ -8,15 +8,46 @@ export class MailPrefsService {
constructor(private http: HttpClient ) {}
getUserEmailPreferencesForCommunity (communityId:string, apiUrl:string):any {
return this.http.get(apiUrl +"users/notification"+"?communityId="+communityId, CustomOptions.getAuthOptions())
let url = apiUrl +"users/notification"+"?communityId="+communityId;
return this.http.get(url, CustomOptions.getAuthOptions())
//.map(request => <any> request.json())
//.do(request => console.info("Get user email preferences for communityId= "+communityId ));
//.catch(this.handleError);
}
getUserEmailPreferencesForOpenaire (apiUrl:string):any {
return this.http.get(apiUrl +"users/notification", CustomOptions.getAuthOptions());
let url = apiUrl +"users/notification";
//var error: HttpErrorResponse = new HttpErrorResponse({"error": {"code": 204}, "status" : 204}); // doesn't work
//var response: Response = new Response({"body" : {"code":200, "data": []}, "status": 200, "headers": null, "url": "", "merge": null});
return this.http.get(url, CustomOptions.getAuthOptions())
//.timeoutWith(100, Observable.throw(response)) // goes to error
//.timeoutWith(100, Observable.of(response)) // goes to
//.do(request => console.info(request))
//.map(request => <any> request.json())
//.do(request => console.info("Get user email preferences for OpenAIRE" ));
//.catch(this.handleError);
}
saveUserEmailPreferences (notification: any, apiUrl: string) {
let body = JSON.stringify(notification);
return this.http.post(apiUrl +"users/notification/save", body, CustomOptions.getAuthOptionsWithBody());
let url = apiUrl +"users/notification/save";
let body = JSON.stringify( notification );
//console.warn('Json body: : '+body);
//let headers = new Headers({ 'Content-Type': 'application/json' });
//let options = new RequestOptions({ headers: headers });
return this.http.post(url, body, CustomOptions.getAuthOptionsWithBody())
//.map(res => res.json())
//.do(request => console.info("Insert Response:"+request.status) );
//.catch(this.handleError);
}
private handleError (error: HttpErrorResponse) {
// in a real world app, we may send the error to some remote logging infrastructure
// instead of just logging it to the console
console.log(error);
return throwError(error || 'Server error');
}
}

View File

@ -0,0 +1,23 @@
import { NgModule} from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MailPrefsComponent } from './mailPrefs.component';
import { MailPrefsService } from './mailPrefs.service';
import {ErrorMessagesModule} from '../../utils/errorMessages.module';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
@NgModule({
imports: [
CommonModule, RouterModule, FormsModule, ReactiveFormsModule, ErrorMessagesModule, MatSlideToggleModule
],
declarations: [
MailPrefsComponent
],
providers:[MailPrefsService],
exports: [
MailPrefsComponent
]
})
export class MailPrefsModule { }

View File

@ -0,0 +1,15 @@
import {Injectable} from '@angular/core';
import {HttpClient} from "@angular/common/http";
import{EnvProperties} from '../../utils/properties/env-properties';
@Injectable()
export class SearchZenodoCommunitiesService {
constructor(private http: HttpClient ) {}
searchZCommunities (properties:EnvProperties, pid: string):any {
let url = properties.communityAPI+pid+"/zenodocommunities";
return this.http.get((properties.useCache)? (properties.cacheUrl+encodeURIComponent(url)): url);
//.map(res => <any> res.json())
}
}

View File

@ -1,7 +1,9 @@
import { NgModule} from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import {SearchOrcidService} from "./searchOrcid.service";
import {SearchZenodoCommunitiesService} from './searchZenodoCommunities.service';
@NgModule({
@ -11,9 +13,9 @@ import {SearchOrcidService} from "./searchOrcid.service";
declarations: [
],
providers:[
SearchOrcidService
SearchZenodoCommunitiesService
],
exports: [
]
})
export class SearchOrcidServiceModule { }
export class SearchZenodoCommunitiesServiceModule { }

View File

@ -16,12 +16,12 @@ export class ZenodoCommunitiesService {
//.map(res => <any> res.json())
.pipe(map(res => [this.parseZenodoCommunities(res['hits'].hits),res['hits'].total]));
}
getZenodoCommunityById(properties:EnvProperties, id: string) {
let url = properties.zenodoCommunities + "/" + id;
getZenodoCommunityById(properties:EnvProperties, url: string, openaireId:string) {
return this.http.get((properties.useLongCache)? (properties.cacheUrl+encodeURIComponent(url)) : url)
//.map(res => <any> res.json())
.pipe(map(res => {
var community = this.parseZenodoCommunity(res);
community["openaireId"]=openaireId;
return community;
}));
}
@ -40,14 +40,14 @@ export class ZenodoCommunitiesService {
parseZenodoCommunity(resData:any):ZenodoCommunityInfo {
var result: ZenodoCommunityInfo = new ZenodoCommunityInfo();
let metadata = resData["metadata"];
result['title'] = metadata.title;
result['id'] = resData.slug;
result['description'] = metadata.description;
result['link'] = resData.links.self_html;
result['logoUrl'] = resData.links.logo;
result['title'] = resData.title;
result['id'] = resData.id;
result['description'] = resData.description;
result['link'] = resData.links.html;
result['logoUrl'] = resData.logo_url;
result['date'] = resData.updated;
result['page'] = metadata.page;
result['page'] = resData.page;
return result;
}

View File

@ -6,5 +6,5 @@ export class ZenodoCommunityInfo {
logoUrl: string;
date: Date;
page: string;
master:boolean = false;
openaireId:string;
}

View File

@ -0,0 +1,4 @@
.uk-text-danger {
color: #b50000!important;
font-size: 12px;
}

View File

@ -1,44 +1,90 @@
<h1 *ngIf="formTitle" class="uk-margin-auto">{{formTitle}}</h1>
<ng-content select="[page-title]"></ng-content>
<ng-content select="[page-description]"></ng-content>
<div class="uk-child-width-1-1 uk-grid uk-grid-margin-large" [attr.uk-scrollspy-class]="scrollspy?'':null"
[class.uk-grid-column-small]="smallForm" [class.uk-child-width-1-2@s]="!smallForm" [formGroup]="contactForm" uk-grid>
<div *ngIf="contactForm.get('name')" input placeholder="Name"
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('name')"></div>
<div *ngIf="contactForm.get('surname')" input placeholder="Surname"
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('surname')"></div>
<div *ngIf="contactForm.get('email')" input placeholder="Email"
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('email')"></div>
<div *ngIf="contactForm.get('job')" input placeholder="Job Title"
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('job')"></div>
<div *ngIf="contactForm.get('affiliation')" input placeholder="Affiliation"
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('affiliation')"></div>
<div *ngIf="contactForm.get('community')" input placeholder="Research Community or Infrastructure"
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('community')"></div>
<div *ngIf="contactForm.get('organization')" input placeholder="Organization"
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('organization')"></div>
<div *ngIf="contactForm.get('organizationType')" input type="select" placeholder="Organization Type"
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('organizationType')" [options]="organizationTypes"></div>
<div *ngIf="contactForm.get('subject')" class="uk-width-1-1" input placeholder="Subject"
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('subject')"></div>
<div *ngIf="contactForm.get('message')" class="uk-width-1-1" input type="textarea" rows="4" placeholder="Comments"
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('message')"></div>
<div *ngIf="contactForm.get('description')" class="uk-width-1-1" input type="textarea" rows="4" placeholder="Description"
[inputClass]="'flat' + (smallForm?' x-small':'')" [formInput]="contactForm.get('description')"></div>
<div *ngIf="contactForm.get('recaptcha')" class="uk-flex uk-flex-center" [class.uk-width-1-1]="smallForm" [class.uk-flex-last@s]="!smallForm">
<re-captcha #captchaElem (resolved)="handleRecaptcha($event)" [siteKey]="properties.reCaptchaSiteKey"></re-captcha>
</div>
<div class="uk-flex uk-flex-center" [class.uk-width-1-1]="smallForm" [class.uk-flex-column]="!smallForm">
<div class="uk-flex uk-flex-center" [class.uk-flex-left@s]="!smallForm">
<button class="uk-button uk-text-uppercase uk-flex uk-flex-middle"
[class.uk-disabled]="contactForm.invalid || sending"
[class.uk-button-primary]="!buttonClass && contactForm.valid"
[ngClass]="(contactForm.valid?buttonClass:'')"
(click)="send()">
{{sendButton}}
<span *ngIf="sending" class="uk-icon uk-margin-small-left"><loading [top_margin]="false" [size]="'small'"
[color]="null"></loading></span>
</button>
</div>
<h3 *ngIf="formTitle" class="uk-margin-auto">{{formTitle}}</h3>
<div *ngIf="errorMessage" class="uk-width-1-1 uk-alert uk-alert-danger uk-text-center"
role="alert">{{errorMessage}}</div>
<div class="uk-margin-top" uk-grid [formGroup]="contactForm">
<div class="uk-margin-small uk-width-1-1 uk-text-danger uk-text-bold uk-margin-remove-bottom">
*Required fields
</div>
<div *ngIf="contactForm.get('name')" class="uk-width-1-2@s uk-margin-medium-top">
<h6 class="uk-text-bold uk-margin-small-bottom">
Name <span class="uk-text-danger uk-text-bold">*</span>
</h6>
<input class="uk-input" type="text" placeholder="Your name" formControlName="name"
[class.uk-form-danger]="contactForm.get('name').invalid && contactForm.get('name').touched">
</div>
<div *ngIf="contactForm.get('surname')" class="uk-width-1-2@s uk-margin-medium-top">
<h6 class="uk-text-bold uk-margin-small-bottom">
Surname <span class="uk-text-danger uk-text-bold">*</span>
</h6>
<input class="uk-input" type="text" placeholder="Your surname" formControlName="surname"
[class.uk-form-danger]="contactForm.get('surname').invalid && contactForm.get('surname').touched">
</div>
<div *ngIf="contactForm.get('email')" class="uk-width-1-2@s uk-margin-medium-top">
<h6 class="uk-text-bold uk-margin-small-bottom">
Email <span class="uk-text-danger uk-text-bold">*</span>
</h6>
<input class="uk-input" type="text" placeholder="Preferably your work email" formControlName="email"
[class.uk-form-danger]="contactForm.get('email').invalid && contactForm.get('email').touched">
</div>
<div *ngIf="contactForm.get('job')" class="uk-width-1-2@s uk-margin-medium-top">
<h6 class="uk-text-bold uk-margin-small-bottom">
Job Title <span class="uk-text-danger uk-text-bold">*</span>
</h6>
<input class="uk-input" type="text" placeholder="Your job title" formControlName="job"
[class.uk-form-danger]="contactForm.get('job').invalid && contactForm.get('job').touched">
</div>
<div *ngIf="contactForm.get('affiliation')" class="uk-width-1-2@s uk-margin-medium-top">
<h6 class="uk-text-bold uk-margin-small-bottom">
Affiliation <span class="uk-text-danger uk-text-bold">*</span>
</h6>
<input class="uk-input" type="text" placeholder="Your affiliation" formControlName="affiliation"
[class.uk-form-danger]="contactForm.get('affiliation').invalid && contactForm.get('affiliation').touched">
</div>
<div *ngIf="contactForm.get('community')" class="uk-width-1-2@s uk-margin-medium-top">
<div class="uk-width-1-1">
<h6 class="uk-text-bold uk-margin-small-bottom uk-text-nowrap">Research Community or Infrastructure <span class="uk-text-danger uk-text-bold">*</span></h6>
</div>
<input class="uk-input uk-width-1" type="text" placeholder="Your community name" formControlName="community"
[class.uk-form-danger]="contactForm.get('community').invalid && contactForm.get('community').touched">
</div>
<div *ngIf="contactForm.get('organization')" class="uk-width-1-2@s uk-margin-medium-top">
<h6 class="uk-text-bold uk-margin-small-bottom">Organization <span class="uk-text-danger uk-text-bold">*</span></h6>
<input class="uk-input uk-width-1-1" type="text" placeholder="Your organization" formControlName="organization"
[class.uk-form-danger]="contactForm.get('organization').invalid && contactForm.get('organization').touched">
</div>
<div *ngIf="contactForm.get('organizationType')" class="uk-width-1-2@s uk-margin-medium-top">
<h6 class="uk-text-bold uk-margin-small-bottom">Organization Type <span class="uk-text-danger uk-text-bold">*</span></h6>
<select class="uk-select uk-width-1-1" formControlName="organizationType">
<option [value]="''" hidden selected>Select your organization type</option>
<option *ngFor="let option of organizationTypes" [value]="option">{{option}}</option>
</select>
</div>
<div *ngIf="contactForm.get('subject')" class="uk-width-1-1@s uk-margin-medium-top">
<h6 class="uk-text-bold uk-margin-small-bottom">Subject <span class="uk-text-danger uk-text-bold">*</span></h6>
<input class="uk-input uk-width-1-1" type="text" placeholder="Your subject" formControlName="subject"
[class.uk-form-danger]="contactForm.get('subject').invalid && contactForm.get('subject').touched">
</div>
<div *ngIf="contactForm.get('message')" class="uk-width-1-1 uk-margin-medium-top">
<h6 class="uk-text-bold uk-margin-small-bottom">
Message <span class="uk-text-danger uk-text-bold">*</span>
</h6>
<textarea rows="4" class="uk-textarea" placeholder="Your message" formControlName="message"
[class.uk-form-danger]="contactForm.get('message').invalid && contactForm.get('message').touched">
</textarea>
</div>
<div *ngIf="contactForm.get('description')" class="uk-width-1-1 uk-margin-medium-top">
<h6 class="uk-text-bold uk-margin-small-bottom">
Description <span class="uk-text-danger uk-text-bold">*</span>
</h6>
<textarea rows="4" class="uk-textarea" placeholder="Your description" formControlName="description"
[class.uk-form-danger]="contactForm.get('description').invalid && contactForm.get('description').touched">
</textarea>
</div>
<div *ngIf="contactForm.get('recaptcha')" class="uk-width-1-2@s uk-margin-top">
<re-captcha (resolved)="handleRecaptcha($event)" [(siteKey)]="properties.reCaptchaSiteKey">
</re-captcha>
</div>
<div class="uk-margin-medium-top uk-width-1-1">
<button class="uk-button" [class.portal-button]="!buttonClass" [ngClass]="buttonClass" (click)="send()">Send</button>
</div>
</div>

View File

@ -1,27 +1,28 @@
import {Component, EventEmitter, Input, Output, ViewChild} from '@angular/core';
import {FormGroup} from '@angular/forms';
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {UntypedFormGroup} from '@angular/forms';
import {EnvProperties} from "../utils/properties/env-properties";
import {properties} from "../../../environments/environment";
import {RecaptchaComponent} from "ng-recaptcha";
import {Observable} from "rxjs";
import {map, startWith} from "rxjs/operators";
@Component({
selector: 'contact-us',
templateUrl: './contact-us.component.html'
templateUrl: './contact-us.component.html',
styleUrls: ['contact-us.component.css']
})
export class ContactUsComponent {
@Input() public contactForm: FormGroup;
@Input() public formTitle: string;
@Input() public organizationTypes: string[];
@Input() public buttonClass: string;
@Input() public sendButton: string = "Send";
@Input() public smallForm: boolean = false;
@Input() public scrollspy: boolean = false;
@Input() public sending: boolean = false;
@Input()
public contactForm: UntypedFormGroup;
@Input() formTitle: string;
@Input() properties: EnvProperties;
@Output() sendEmitter: EventEmitter<any> = new EventEmitter<any>();
@ViewChild('captchaElem') captchaElem: RecaptchaComponent;
public properties: EnvProperties = properties;
@Input() errorMessage;
@Input()
public organizationTypes: string[];
@Input()
public right: boolean = true;
@Input()
public buttonClass: string;
public send() {
this.sendEmitter.emit({
@ -32,8 +33,4 @@ export class ContactUsComponent {
public handleRecaptcha(captchaResponse: string) {
this.contactForm.get('recaptcha').setValue(captchaResponse);
}
public resetRecaptcha() {
this.captchaElem.reset();
}
}

View File

@ -6,14 +6,11 @@ import {ContactUsComponent} from './contact-us.component';
import {ReactiveFormsModule} from "@angular/forms";
import {MatAutocompleteModule} from "@angular/material/autocomplete";
import {RecaptchaModule} from "ng-recaptcha";
import {SafeHtmlPipeModule} from "../utils/pipes/safeHTMLPipe.module";
import {LoadingModule} from "../utils/loading/loading.module";
import {InputModule} from "../sharedComponents/input/input.module";
@NgModule({
imports: [
CommonModule, RouterModule,
ReactiveFormsModule, MatAutocompleteModule, RecaptchaModule, SafeHtmlPipeModule, LoadingModule, InputModule],
ReactiveFormsModule, MatAutocompleteModule, RecaptchaModule],
declarations: [
ContactUsComponent
],

View File

@ -1,105 +1,108 @@
<div page-content>
<div page-content class="admin-pages">
<div header>
<admin-tabs tab="class"></admin-tabs>
<ul class="uk-subnav uk-subnav-pill uk-margin-medium-top">
<li [class.uk-active]="filterForm.get('type').value === 'all'" class="uk-margin-small-bottom"><a
(click)="filterForm.get('type').setValue('all')"><span
class="title">All portals</span></a></li>
<li *ngFor="let type of portalUtils.portalTypes; let i=index"
[class.uk-active]="filterForm.get('type').value === type.value" class="uk-margin-small-bottom"><a
(click)="filterForm.get('type').setValue(type.value)"><span
class="title">{{type.label}}</span></a></li>
</ul>
</div>
<div actions>
<div class="uk-section-xsmall">
<div class="uk-flex uk-flex-right@m uk-flex-center uk-flex-wrap uk-flex-middle uk-grid" uk-grid>
<div search-input [disabled]="showLoading" [expandable]="true" [searchControl]="filterForm.get('keyword')" searchInputClass="outer" placeholder="Search class" class="uk-width-1-3@xl uk-width-2-5@l uk-width-1-2@m uk-width-1-1"></div>
<admin-tabs tab="class" header></admin-tabs>
<div *ngIf="!showLoading" class="uk-grid" uk-grid>
<div class="uk-width-1-1">
<ul class="uk-subnav uk-subnav-pill">
<li [class.uk-active]="filterForm.get('type').value === 'all'" class="uk-margin-small-bottom"><a
(click)="filterForm.get('type').setValue('all')"><span
class="title">All portals</span></a></li>
<li *ngFor="let type of portalUtils.portalTypes; let i=index"
[class.uk-active]="filterForm.get('type').value === type.value" class="uk-margin-small-bottom"><a
(click)="filterForm.get('type').setValue(type.value)"><span
class="title">{{type.label}}</span></a></li>
</ul>
</div>
<div 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 #searchInputComponent search-input [control]="filterForm.controls.keyword" [showSearch]="false"
placeholder="Search class"
[selected]="selectedKeyword" (closeEmitter)="onSearchClose()" (resetEmitter)="reset()"
[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 class="show-options">
<button class="uk-button uk-button-secondary">Bulk Actions</button>
<div uk-dropdown="mode: click">
<ul class="uk-nav uk-dropdown-nav"
[attr.uk-tooltip]="getSelectedDivIds().length == 0 ? 'pos:left; cls: uk-active' : 'cls: uk-invisible'"
title="Select at least one class">
<li><a [class]="getSelectedDivIds().length == 0 ? 'uk-disabled' : ''"
(click)="confirmDeleteSelectedDivIds()"><i></i> Delete </a></li>
</ul>
</div>
</div>
<div>
<button class="uk-button uk-button-default uk-flex uk-flex-middle" (click)="newDivId()"
[disabled]="showLoading" [class.uk-disabled]="showLoading">
<icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left uk-text-bold uk-text-uppercase">Add class</span>
</button>
<a (click)="newDivId()"
class="uk-flex uk-flex-middle uk-text-uppercase">
<button class="large uk-icon-button uk-button-secondary">
<icon name="add"></icon>
</button>
<button class="uk-button uk-button-link uk-margin-small-left uk-text-secondary">Add class</button>
</a>
</div>
</div>
</div>
</div>
<div inner>
<div class="uk-section uk-section-small uk-position-relative" style="min-height: 60vh">
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
<div *ngIf="!showLoading">
<table *ngIf="checkboxes.length > 0"class="uk-table uk-table-striped uk-table-large">
<thead class="uk-card-header">
<tr>
<th
class="uk-width-small"><input id="allDivIdCheckbox" type="checkbox"
(change)="toggleCheckBoxes($event)"></th>
<th>Name</th>
<th *ngIf="!selectedCommunityPid">Portal Type</th>
<th>Page</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let check of checkboxes; let i=index">
<td><input id="{{check.divId._id}}" class="checkBox" type="checkbox"
name="divIdscb[]" value="{{check.divId._id}}" [(ngModel)]="check.checked">
</td>
<td>
<div class="name" href="#">{{check.divId.name}}</div>
</td>
<td *ngIf="!selectedCommunityPid">
<div class="portalType" href="#">{{check.divId.portalType}}</div>
</td>
<td>
<div class="pages" href="#">
<span *ngFor="let page of check.divId.pages let i=index">{{page.name}}<span
*ngIf="i<(check.divId.pages.length-1)">, </span></span>
</div>
</td>
<td>
<div class="actions" href="#">
<icon class="clickable" name="edit" (click)="editDivId(i)"></icon>
<icon class="clickable uk-margin-small-left" [customClass]="'uk-text-danger'" name="remove" (click)="confirmDeleteDivId(check.divId._id)"></icon>
</div>
</td>
</tr>
</tbody>
</table>
<div *ngIf="checkboxes.length == 0"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div>No classes found</div>
</div>
<ng-container *ngIf="!showLoading">
<div *ngIf="checkboxes.length == 0"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div>No classes found</div>
</div>
<table *ngIf="checkboxes.length > 0" class="uk-table uk-table-striped uk-table-large">
<thead>
<tr class="uk-child-width-1-5">
<th>
<label>
<input id="checkAll" type="checkbox" (click)="toggleCheckBoxes($event)" class="uk-checkbox"
[ngModel]="getSelectedDivIds().length ==checkboxes.length"/>
</label>
<span class="uk-margin-left">
<button class="uk-button uk-button-link" [class.uk-disabled]="getSelectedDivIds().length == 0" [disabled]="getSelectedDivIds().length == 0">
Bulk Actions ({{getSelectedDivIds().length}})
</button>
<div uk-dropdown="mode: click">
<ul class="uk-nav uk-dropdown-nav"
[attr.uk-tooltip]="getSelectedDivIds().length == 0 ? 'pos:left; cls: uk-active' : 'cls: uk-invisible'"
title="Select at least one entity">
<li>
<a (click)="confirmDeleteSelectedDivIds()"><i></i>Delete</a>
</li>
</ul>
</div>
</span>
</th>
<th>Name</th>
<th *ngIf="!selectedCommunityPid">Portal Type</th>
<th>Page</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let check of checkboxes; let i=index">
<td><input id="{{check.divId._id}}" class="uk-checkbox" type="checkbox"
name="divIdscb[]" value="{{check.divId._id}}" [(ngModel)]="check.checked">
</td>
<td>
<div class="name" href="#">{{check.divId.name}}</div>
</td>
<td *ngIf="!selectedCommunityPid">
<div class="portalType" href="#">{{check.divId.portalType}}</div>
</td>
<td>
<div class="pages" href="#">
<span *ngFor="let page of check.divId.pages let i=index">{{page.name}}<span
*ngIf="i<(check.divId.pages.length-1)">, </span></span>
</div>
</td>
<td>
<div class="uk-flex uk-flex-middle">
<icon class="clickable" [flex]="true" name="edit" [customClass]="'uk-text-primary'" (click)="editDivId(i)"></icon>
<icon class="clickable uk-margin-small-left" [flex]="true" [customClass]="'uk-text-danger'" name="delete" (click)="confirmDeleteDivId(check.divId._id)"></icon>
</div>
</td>
</tr>
</tbody>
</table>
</ng-container>
</div>
</div>
</div>
<modal-alert #editModal (alertOutput)="divIdSaveConfirmed($event)"
[okDisabled]="classForm && (classForm.invalid || !classForm.dirty)" classTitle="uk-background-primary uk-light">
[okDisabled]="classForm && (classForm.invalid || !classForm.dirty)">
<form *ngIf="classForm" [formGroup]="classForm" class="uk-grid uk-child-width-1-1" uk-grid>
<div input [formInput]="classForm.get('name')" placeholder="Class Name"></div>
<div input [formInput]="classForm.get('pages')" placeholder="Pages" [options]="allPages" type="chips"></div>
<div input [formInput]="classForm.get('portalType')" placeholder="Portal Type" [options]="portalUtils.portalTypes" type="select"></div>
<div dashboard-input [formInput]="classForm.get('name')"
type="text" label="Class Name" placeholder="Write a name">
</div>
<div dashboard-input [formInput]="classForm.get('pages')" placeholder="Add a page"
type="chips" [options]="allPages" label="Pages">
</div>
<div dashboard-input type="select" label="Portal Type" placeholder="Choose a type"
[formInput]="classForm.get('portalType')" [options]="portalUtils.portalTypes"></div>
</form>
</modal-alert>
<modal-alert #deleteModal [overflowBody]="false" (alertOutput)="confirmedDeleteDivIds($event)" classTitle="uk-background-primary uk-light"></modal-alert>
<modal-alert #deleteModal (alertOutput)="confirmedDeleteDivIds($event)"></modal-alert>

View File

@ -1,7 +1,7 @@
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from "@angular/router";
import {HelpContentService} from "../../services/help-content.service";
import {UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators} from "@angular/forms";
import {FormArray, FormBuilder, FormGroup, Validators} from "@angular/forms";
import {CheckDivId, DivId} from "../../utils/entities/adminTool/divId";
import {Page} from "../../utils/entities/adminTool/page";
import {EnvProperties} from '../../utils/properties/env-properties';
@ -11,39 +11,42 @@ import {properties} from "../../../../environments/environment";
import {PortalUtils} from "../portal/portalHelper";
import {AlertModal} from "../../utils/modal/alert";
import {Option} from "../../sharedComponents/input/input.component";
import {SearchInputComponent} from "../../sharedComponents/search-input/search-input.component";
import {Title} from "@angular/platform-browser";
import {ClearCacheService} from "../../services/clear-cache.service";
import {NotificationHandler} from "../../utils/notification-handler";
declare var UIkit;
@Component({
selector: 'divIds',
templateUrl: './divIds.component.html',
})
export class DivIdsComponent implements OnInit {
@ViewChild('editModal') editModal: AlertModal;
@ViewChild('deleteModal') deleteModal: AlertModal;
private selectedDivIds: string[] = [];
public checkboxes: CheckDivId[] = [];
public divIds: DivId[] = [];
public classForm: UntypedFormGroup;
public pagesCtrl: UntypedFormArray;
public classForm: FormGroup;
public pagesCtrl: FormArray;
private searchText: RegExp = new RegExp('');
public keyword: string = "";
public properties: EnvProperties = properties;
public formPages: Page[] = [];
public showLoading: boolean = true;
public filterForm: UntypedFormGroup;
public filterForm: FormGroup;
private subscriptions: any[] = [];
public allPages: Option[] = [];
selectedCommunityPid = null;
public portalUtils: PortalUtils = new PortalUtils();
private index: number;
public selectedKeyword: string;
@ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent;
constructor(private element: ElementRef, private route: ActivatedRoute, private _router: Router,
private title: Title,
private _helpContentService: HelpContentService, private _fb: UntypedFormBuilder,
private _clearCacheService: ClearCacheService) {
private _helpContentService: HelpContentService, private _fb: FormBuilder) {
}
ngOnInit() {
@ -80,7 +83,7 @@ export class DivIdsComponent implements OnInit {
getDivIds() {
this.showLoading = true;
this.subscriptions.push(this._helpContentService.getAllDivIdsFull().subscribe(
this.subscriptions.push(this._helpContentService.getAllDivIdsFull(this.properties.adminToolsAPIURL).subscribe(
divIds => {
this.divIds = divIds;
this.checkboxes = [];
@ -130,6 +133,8 @@ export class DivIdsComponent implements OnInit {
}
private confirmModalOpen() {
this.deleteModal.cancelButton = true;
this.deleteModal.okButton = true;
this.deleteModal.alertTitle = "Delete Confirmation";
this.deleteModal.message = "Are you sure you want to delete the selected class(es)?";
this.deleteModal.okButtonText = "Yes";
@ -138,12 +143,15 @@ export class DivIdsComponent implements OnInit {
public confirmedDeleteDivIds(data: any) {
this.showLoading = true;
this.subscriptions.push(this._helpContentService.deleteDivIds(this.selectedDivIds).subscribe(
this.subscriptions.push(this._helpContentService.deleteDivIds(this.selectedDivIds, this.properties.adminToolsAPIURL).subscribe(
_ => {
this.deleteDivIdsFromArray(this.selectedDivIds);
NotificationHandler.rise('Classes have been <b>successfully deleted</b>');
UIkit.notification('Classes have been <b>successfully deleted</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
this.showLoading = false;
//this._clearCacheService.clearCache("Class ids deleted");
},
error => this.handleUpdateError('System error deleting the selected classes', error)
));
@ -182,6 +190,8 @@ export class DivIdsComponent implements OnInit {
}
private divIdsModalOpen(title: string, yesBtn: string) {
this.editModal.cancelButton = true;
this.editModal.okButton = true;
this.editModal.okButtonLeft = false;
this.editModal.alertTitle = title;
this.editModal.okButtonText = yesBtn;
@ -190,21 +200,28 @@ export class DivIdsComponent implements OnInit {
public divIdSaveConfirmed(data: any) {
this.showLoading = true;
if (!this.classForm.getRawValue()._id) {
this.subscriptions.push(this._helpContentService.saveDivId(<DivId>this.classForm.getRawValue()).subscribe(
if (!this.classForm.value._id) {
this.subscriptions.push(this._helpContentService.saveDivId(<DivId>this.classForm.value, this.properties.adminToolsAPIURL).subscribe(
divId => {
this.divIdSavedSuccessfully(divId);
NotificationHandler.rise('Class <b>' + divId.name + '</b> has been <b>successfully created</b>');
//this._clearCacheService.clearCache("Class id saved");
UIkit.notification('Class <b>' + divId.name + '</b> has been <b>successfully created</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
},
error => this.handleUpdateError("System error creating class", error)
));
} else {
this.subscriptions.push(this._helpContentService.updateDivId(<DivId>this.classForm.getRawValue()).subscribe(
this.classForm.get('portalType').enable();
this.subscriptions.push(this._helpContentService.updateDivId(<DivId>this.classForm.value, this.properties.adminToolsAPIURL).subscribe(
divId => {
this.divIdUpdatedSuccessfully(divId);
NotificationHandler.rise('Class <b>' + divId.name + '</b> has been <b>successfully updated</b>');
//this._clearCacheService.clearCache("Class id updated");
UIkit.notification('Class <b>' + divId.name + '</b> has been <b>successfully updated</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
},
error => this.handleUpdateError("System error updating class", error)
));
@ -240,28 +257,37 @@ export class DivIdsComponent implements OnInit {
}
public filterDivIds(divId: DivId): boolean {
return this.searchText.toString() == '' || (divId.name + ' ' + divId.portalType).match(this.searchText) != null;
let textFlag = this.searchText.toString() == '' || (divId.name + ' ' + divId.portalType).match(this.searchText) != null;
return textFlag;
}
handleUpdateError(message: string, error = null) {
if (error) {
handleUpdateError(message: string, error) {
if (error == null) {
// this.formComponent.reset();
} else {
UIkit.notification(message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
console.log('Server responded: ' + error);
}
NotificationHandler.rise(message,'danger');
this.showLoading = false;
}
handleError(message: string, error = null) {
if (error) {
console.log('Server responded: ' + error);
}
NotificationHandler.rise(message,'danger');
handleError(message: string, error) {
UIkit.notification(message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
console.log('Server responded: ' + error);
this.showLoading = false;
}
getPages() {
this.showLoading = true;
this.subscriptions.push(this._helpContentService.getAllPages().subscribe(
this.subscriptions.push(this._helpContentService.getAllPages(this.properties.adminToolsAPIURL).subscribe(
pages => {
this.allPages = [];
pages.forEach(page => {
@ -275,4 +301,13 @@ export class DivIdsComponent implements OnInit {
error => this.handleError('System error retrieving pages', error)
));
}
public onSearchClose() {
this.selectedKeyword = this.filterForm.get('keyword').value;
}
public reset() {
this.selectedKeyword = null;
this.searchInputComponent.reset()
}
}

View File

@ -6,21 +6,34 @@ import {AlertModalModule} from '../../utils/modal/alertModal.module';
import {DivIdsComponent} from './divIds.component';
import {AdminToolServiceModule} from "../../services/adminToolService.module";
import {InputModule} from "../../sharedComponents/input/input.module";
import {MatAutocompleteModule} from '@angular/material/autocomplete';
import { MatCheckboxModule } from "@angular/material/checkbox";
import { MatFormFieldModule } from "@angular/material/form-field";
import {MatChipsModule} from '@angular/material/chips';
import {AdminTabsModule} from "../sharedComponents/admin-tabs/admin-tabs.module";
import {PageContentModule} from "../sharedComponents/page-content/page-content.module";
import {ClassesRoutingModule} from "./classes-routing.module";
import {SearchInputModule} from "../../sharedComponents/search-input/search-input.module";
import {IconsModule} from "../../utils/icons/icons.module";
import {IconsService} from "../../utils/icons/icons.service";
import {add, edit, remove} from "../../utils/icons/icons";
import {LoadingModule} from "../../utils/loading/loading.module";
@NgModule({
imports: [
ClassesRoutingModule,
CommonModule, RouterModule, FormsModule,
AlertModalModule, ReactiveFormsModule, AdminToolServiceModule, InputModule,
AdminTabsModule, PageContentModule, SearchInputModule, IconsModule, LoadingModule
AlertModalModule, ReactiveFormsModule, AdminToolServiceModule, InputModule, MatAutocompleteModule, MatFormFieldModule, MatChipsModule,
MatCheckboxModule, AdminTabsModule, PageContentModule, ClassesRoutingModule, SearchInputModule, IconsModule, LoadingModule
],
declarations: [DivIdsComponent],
exports: [DivIdsComponent]
})
export class DivIdsModule {}
export class DivIdsModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([add, edit, remove]);
}
}

View File

@ -1,78 +1,89 @@
<div page-content>
<div header>
<div class="uk-section-xsmall uk-margin-top uk-container">
<div class="uk-flex-middle uk-grid" uk-grid>
<div class="uk-width-expand">
<a routerLink="../" [queryParams]=" { 'pageId': pageId }" class="uk-flex uk-flex-middle uk-h5 uk-link-reset">
<span class="uk-margin-right">
<icon name="west" ratio="1.7" [flex]="true"></icon>
</span>
<h1 *ngIf="page" class="uk-h5 uk-margin-remove">
{{page.name}} - {{pageHelpContent ? 'Update ' : 'Add new '}} class help text
<span *ngIf="myForm.dirty" class="uk-text-large"> (unsaved changes)</span>
</h1>
</a>
</div>
<div class="uk-width-auto">
<button class="uk-button uk-button-default uk-margin-right"
(click)="resetCustom()" [class.uk-disabled]="!myForm.dirty"
[disabled]="!myForm.dirty || showLoading">Reset
</button>
<button class="uk-button uk-button-primary" [class.uk-disabled]="myForm.invalid || !myForm.dirty || myForm.disabled"
(click)="saveCustom()" [disabled]="myForm.invalid ||!myForm.dirty || myForm.disabled || showLoading">Save
</button>
</div>
</div>
<div class="uk-margin-top">
<a routerLink="../" [queryParams]=" { 'pageId': pageId }"
class="uk-text-secondary uk-text-uppercase uk-text-bold uk-text-small">
<span class="uk-icon-button uk-icon small uk-button-secondary">
<icon name="arrow_left"></icon>
</span>
<span class="space">
Go back to class help texts list
</span>
</a>
</div>
</div>
<div inner>
<div class="uk-container">
<div *ngIf="myForm" style="min-height: 60vh"
class="uk-section uk-section-small uk-position-relative">
<div *ngIf="showLoading" class="uk-position-center">
<loading *ngIf="showLoading"></loading>
<div class="uk-card-header">
<div class="uk-flex uk-flex-middle uk-child-width-1-1 uk-child-width-1-2@m uk-grid" uk-grid>
<div>
<div class="uk-text-small uk-text-muted"> {{pageHelpContent ? 'Update ' : 'Add new '}} class help text</div>
<div>
<span *ngIf="page" class="uk-text-bold">{{page.name}}</span>
<span *ngIf="myForm.dirty"> (unsaved changes)</span>
</div>
</div>
<div class=" uk-flex uk-flex-right">
<button (click)="resetCustom()" [disabled]="showLoading || !myForm.dirty"
class="uk-button uk-button-secondary outlined uk-margin-small-right">Reset
</button>
<button (click)="saveCustom()" class="uk-button uk-button-secondary uk-margin-small-right"
[disabled]="showLoading || !myForm.dirty || !myForm.valid ">Save
</button>
</div>
</div>
<form *ngIf="!showLoading" [formGroup]="myForm">
<div class="uk-width-1-2" *ngIf="classOptions.length > 0" input [formInput]="myForm.get('divId')" placeholder="Select Class" [options]="classOptions" type="select"></div>
<div class="form-group uk-margin-medium-top">
<span class="uk-text-bold uk-margin-small-right">Select Status (Enable/ disable)</span>
<mat-slide-toggle [checked]="myForm.get('isActive').value"
(change)="changeStatus()"
uk-tooltip="title:<div><div class='uk-text-bold'> Enable or disable help text to show or hide it from the dashboard</div></div>"
></mat-slide-toggle>
</div>
<div class="form-group uk-margin-large-top"
[ngClass]="{'has-error':!myForm.controls.content.valid &&
myForm.controls.content.dirty}" >
<div class="uk-text-bold uk-margin-bottom uk-flex uk-flex-middle">
<span class="uk-margin-small-right">Content</span>
<button class="uk-button uk-button-link uk-text-normal"><icon name="info" type="outlined" [flex]="true"></icon></button>
<div class="uk-dropdown uk-text-normal uk-width-medium uk-padding-small" uk-dropdown>
OpenAIRE style guide is based on <a href="https://getuikit.com/docs/introduction" target="_blank" class="uk-link custom-external">UIKit</a>.
You can find some usage examples
<a *ngIf="properties.dashboard == 'monitor'" routerLink="/theme" [queryParams]="parentClass?{parentClass: parentClass}:null"
target="_blank" class="uk-link custom-external">here</a>
<a *ngIf="properties.dashboard == 'connect'" [href] ="'https://'+(properties.environment == 'beta' ? 'beta.' : '')+this.portal+'.openaire.eu/theme'"
target="_blank" class="uk-link custom-external">here</a>
in order to style your content.
</div>
</div>
<div [ngClass]="parentClass">
<ckeditor #ckEditor (change)="contentChanged()"
[readonly]="false"
debounce="500"
[formControl]="myForm.get('content')"
[config]="{ extraAllowedContent: '* [uk-*](*) ; span', disallowedContent: 'script; *[on*]',
removeButtons: 'Save,NewPage,DocProps,Preview,Print,' +
'Form,Checkbox,Radio,TextField,Textarea,Select,Button,ImageButton,HiddenField,' +
'CreateDiv,Flash,PageBreak,' +
'Subscript,Superscript,Anchor,Smiley,Iframe,Styles,Font,About,Language',
extraPlugins: 'divarea', height: 500}">
</ckeditor>
</div>
</div>
</form>
</div>
<div class="uk-card uk-card-default uk-position-relative " style="min-height: 60vh">
<div style="max-height: 60vh" class="uk-padding-large uk-overflow-auto">
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger" role="alert">{{errorMessage}}</div>
<div class="uk-animation-fade uk-width-1-1" role="alert">
<div *ngIf="updateErrorMessage" class="uk-alert uk-alert-danger" role="alert">{{updateErrorMessage}}</div>
<div *ngIf="showLoading" class="uk-position-center">
<loading *ngIf="showLoading"></loading>
</div>
<form [formGroup]="myForm" [class.hidden]="showLoading">
<div class="uk-grid uk-child-width-1-2 ">
<div *ngIf="classOptions.length > 0" dashboard-input
[formInput]="myForm.get('divId')"
type="select" placeholder="Select Class"
label="Select Class" [options]="classOptions"
>
</div>
</div>
<div class="form-group uk-margin-top">
<span class="uk-text-bold uk-margin-small-right">Select Status (Enable/ disable)</span>
<mat-slide-toggle [checked]="myForm.get('isActive').value"
(change)="changeStatus()"
uk-tooltip="title:<div class='uk-padding-small uk-width-large'><div class='uk-text-bold '> Enable or disable help text to show or hide it from the dashboard</div></div>"
></mat-slide-toggle>
</div>
<div class="form-group uk-margin-large-top"
[ngClass]="{'has-error':!myForm.controls.content.valid &&
myForm.controls.content.dirty}" >
<label class="uk-text-bold">Content</label>
<div class="uk-margin-top">
<ckeditor (change)="contentChanged()"
[readonly]="false"
debounce="500"
[formControl]="myForm.get('content')"
[config]="{ extraAllowedContent: '* [uk-*](*) ; span', disallowedContent: 'script; *[on*]',
removeButtons: 'Save,NewPage,DocProps,Preview,Print,' +
'Form,Checkbox,Radio,TextField,Textarea,Select,Button,ImageButton,HiddenField,' +
'CreateDiv,Flash,PageBreak,' +
'Subscript,Superscript,Anchor,Smiley,Iframe,Styles,Font,About,Language',
extraPlugins: 'divarea'}">
</ckeditor>
</div>
</div>
<input type="hidden" formControlName="_id">
</form>
</div>
</div>
</div>
</div>
</div>

View File

@ -1,54 +1,56 @@
import {ChangeDetectorRef, Component, OnInit, ViewChild} from '@angular/core';
import {Component, Input, OnInit} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {Page} from '../../utils/entities/adminTool/page';
import {HelpContentService} from '../../services/help-content.service';
import {EnvProperties} from '../../utils/properties/env-properties';
import {Session} from '../../login/utils/helper.class';
import {LoginErrorCodes} from '../../login/utils/guardHelper.class';
import {properties} from '../../../../environments/environment';
import {Subscriber, Subscription, zip} from 'rxjs';
import {HelperFunctions} from '../../utils/HelperFunctions.class';
import {DivHelpContent} from '../../utils/entities/adminTool/div-help-content';
import {NotificationHandler} from "../../utils/notification-handler";
import {ClearCacheService} from "../../services/clear-cache.service";
import {CKEditorComponent} from "ng2-ckeditor";
declare var UIkit;
@Component({
selector: 'class-content-form',
templateUrl: './class-help-content-form.component.html',
})
export class ClassContentFormComponent implements OnInit {
myForm: UntypedFormGroup;
myForm: FormGroup;
portal: string;
parentClass: string;
pageId: string;
pageContentId: string;
page: Page;
classOptions = [];
public properties: EnvProperties = properties;
public showLoading: boolean = true;
public errorMessage: string = '';
@Input() updateErrorMessage: string = '';
private subs: Subscription[] = [];
public pageHelpContent: DivHelpContent;
@ViewChild('ckEditor') ckEditor: CKEditorComponent;
constructor(private route: ActivatedRoute, private _router: Router, private _fb: UntypedFormBuilder,
private cdr: ChangeDetectorRef, private _helpContentService: HelpContentService,
private _clearCacheService: ClearCacheService) {
constructor(private route: ActivatedRoute, private _router: Router, private _fb: FormBuilder, private _helpContentService: HelpContentService) {
}
ngOnInit() {
this.portal = (this.route.snapshot.data.portal) ? this.route.snapshot.data.portal : this.route.snapshot.params[this.route.snapshot.data.param];
this.parentClass = this.route.snapshot.data.parentClass;
this.subs.push(this.route.queryParams.subscribe(params => {
this.pageId = params['pageId'];
this.myForm = this.form;
this.pageContentId = params['pageContentId'];
if (!this.pageId) {
this._router.navigate(['../'], {relativeTo: this.route});
}
this.getInfo(this.pageId);
this.subs.push(this.route.params.subscribe(params => {
this.portal = (this.route.snapshot.data.portal) ? this.route.snapshot.data.portal : this.route.snapshot.params[this.route.snapshot.data.param];
this.subs.push(this.route.queryParams.subscribe(params => {
this.pageId = params['pageId'];
this.myForm = this.form;
this.pageContentId = params['pageContentId'];
if (!this.pageId) {
this._router.navigate(['../'], {relativeTo: this.route});
}
this.getInfo(this.pageId);
}));
}));
}
ngOnDestroy() {
this.subs.forEach(value => {
if (value instanceof Subscriber) {
@ -56,11 +58,11 @@ export class ClassContentFormComponent implements OnInit {
}
});
}
getInfo(pageId: string) {
this.showLoading = true;
let obs = zip(this._helpContentService.getPageByPortal(pageId, this.portal),
this._helpContentService.getDivIdsFullByPortal(pageId, this.portal));
let obs = zip(this._helpContentService.getPageByPortal(pageId, this.properties.adminToolsAPIURL, this.portal),
this._helpContentService.getDivIdsFullByPortal(pageId, this.properties.adminToolsAPIURL, this.portal));
this.subs.push(obs.subscribe(
results => {
this.page = results[0];
@ -69,44 +71,25 @@ export class ClassContentFormComponent implements OnInit {
}
this.setOptions(results[1]);
if (!this.pageContentId) {
this.updateForm(null);
this.updateForm(null);
this.showLoading = false;
this.initCKEditor();
} else {
this.subs.push(this._helpContentService.getDivHelpContent(this.pageContentId, this.portal).subscribe(pageHelpContent => {
this.pageHelpContent = pageHelpContent;
if (this.properties.adminToolsPortalType != this.page.portalType) {
this._router.navigate(['../'], {relativeTo: this.route});
}
this.updateForm(this.pageHelpContent);
this.showLoading = false;
this.initCKEditor();
},
this.subs.push(this._helpContentService.getDivHelpContent( this.pageContentId, this.properties.adminToolsAPIURL, this.portal).subscribe(pageHelpContent=>{
this.pageHelpContent = pageHelpContent;
if (this.properties.adminToolsPortalType != this.page.portalType) {
this._router.navigate(['../'], {relativeTo: this.route});
}
this.updateForm(this.pageHelpContent);
this.showLoading = false;
},
error => {
this.handleError('System error retrieving content by id ' + this.pageContentId, error)
}));
this.handleError('System error retrieving content by id '+ this.pageContentId, error)
}));
}
}));
}
private initCKEditor() {
this.cdr.detectChanges();
if (this.ckEditor) {
this.ckEditor.instance.on('mode', () => {
let editor = this.ckEditor.instance;
if (editor.mode === 'source') {
let editable = editor.editable();
editable.attachListener(editable, 'input', () => {
this.myForm.get('content').setValue(editor.getData());
this.myForm.get('content').markAsDirty();
this.cdr.detectChanges();
});
}
});
}
}
private updateForm(pageHelpContent: DivHelpContent) {
this.pageHelpContent = pageHelpContent;
this.myForm = this.form;
@ -115,64 +98,78 @@ export class ClassContentFormComponent implements OnInit {
this.myForm.get('divId').disable();
}
this.myForm.markAsPristine();
}
public setOptions(divIds) {
this.classOptions = [];
for (let divid of divIds) {
this.classOptions.push({label: divid.name, value: divid._id});
for(let divid of divIds){
this.classOptions.push({label:divid.name, value:divid._id});
}
}
public get form() {
return this._fb.group({
divId: ['', Validators.required],
content: ['', Validators.required],
isActive: true,
portal: this.portal,
_id: '',
_id : '',
});
}
public reset() {
this.myForm.patchValue({
divId: ['', Validators.required],
content: ['', Validators.required],
isActive: true,
portal: '',
_id: '',
_id : '',
});
this.myForm.markAsPristine();
}
handleError(message: string, error = null) {
if (error) {
console.error('Server responded: ' + error);
}
NotificationHandler.rise(message, 'danger');
handleError(message: string, error) {
this.errorMessage = message;
console.error('Server responded: ' + error);
this.showLoading = false;
}
public saveCustom() {
if (this.myForm.valid) {
this.showLoading = true;
let pageHelpContent: DivHelpContent = this.myForm.getRawValue();
this.subs.push(this._helpContentService.insertOrUpdateDivHelpContent(pageHelpContent, this.portal).subscribe(
_ => {
this._router.navigate(['../'], {queryParams: {"pageId": this.pageId}, relativeTo: this.route});
NotificationHandler.rise('Page content has been <b>successfully updated</b>');
this.showLoading = false;
this._clearCacheService.purgeBrowserCache("Class help text saved or updated",this.portal);
},
err => this.handleUpdateError('System error saving page content', err)
));
if (!Session.isLoggedIn()) {
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
"redirectUrl": this._router.url
}
});
} else {
this.showLoading = false;
this.handleError('Please fill all required fields');
if (this.myForm.valid) {
this.showLoading = true;
this.updateErrorMessage = "";
this.myForm.get('divId').enable();
let pageHelpContent: DivHelpContent = this.myForm.value;
this.subs.push(this._helpContentService.insertOrUpdateDivHelpContent(pageHelpContent, this.properties.adminToolsAPIURL, this.portal).subscribe(
_ => {
this._router.navigate(['../'], {queryParams: {"pageId": this.pageId}, relativeTo: this.route});
UIkit.notification('Page content has been <b>successfully updated</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
this.showLoading = false;
},
err => this.handleUpdateError('System error saving page content', err)
));
} else {
this.showLoading = false;
this.errorMessage = "Please fill all required fields";
}
}
}
@ -181,13 +178,15 @@ export class ClassContentFormComponent implements OnInit {
this.updateForm(this.pageHelpContent);
this.showLoading = false;
}
handleUpdateError(message: string, error) {
this.updateErrorMessage = message;
console.error('Server responded: ' + error);
NotificationHandler.rise(message, 'danger');
this.showLoading = false;
}
changeStatus() {
this.myForm.get('isActive').setValue(!this.myForm.get('isActive').value);
if (this.pageHelpContent && this.myForm.get('isActive').value != this.pageHelpContent.isActive || !this.pageHelpContent && !this.myForm.get('isActive').value) {
@ -196,7 +195,7 @@ export class ClassContentFormComponent implements OnInit {
this.myForm.get('isActive').markAsPristine()
}
}
contentChanged() {
if (this.pageHelpContent && this.myForm.get('content').value != this.pageHelpContent.content || !this.pageHelpContent && this.myForm.get('content').value != '') {
this.myForm.get('content').markAsDirty();

View File

@ -10,20 +10,25 @@ import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import {IconsModule} from '../../utils/icons/icons.module';
import {RouterModule} from '@angular/router';
import {LoadingModule} from '../../utils/loading/loading.module';
import {IconsService} from '../../utils/icons/icons.service';
import {arrow_left} from '../../utils/icons/icons';
import {ClassContentFormComponent} from './class-help-content-form.component';
import {ClassHelpContentFormRoutingModule} from './class-help-content-form-routing.module';
import {PageContentModule} from '../sharedComponents/page-content/page-content.module';
@NgModule({
imports: [
ClassHelpContentFormRoutingModule,
CommonModule, FormsModule, RouterModule,
SafeHtmlPipeModule, CKEditorModule,
AlertModalModule, ReactiveFormsModule, AdminToolServiceModule, InputModule, MatSlideToggleModule, IconsModule, LoadingModule, PageContentModule
AlertModalModule, ReactiveFormsModule, ClassHelpContentFormRoutingModule, AdminToolServiceModule, InputModule, MatSlideToggleModule, IconsModule, LoadingModule, PageContentModule
],
declarations: [
ClassContentFormComponent
],
exports: [ClassContentFormComponent]
})
export class ClassHelpContentFormModule {}
export class ClassHelpContentFormModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([arrow_left]);
}
}

View File

@ -1,87 +1,120 @@
<div page-content>
<div header>
<div class="uk-section-xsmall uk-margin-top">
<div class="uk-flex-middle uk-grid" uk-grid>
<div class="uk-width-expand">
<a routerLink="../pages" class="uk-flex uk-flex-middle uk-h5 uk-link-reset">
<span class="uk-margin-right">
<icon name="west" ratio="1.7" [flex]="true"></icon>
</span>
<h1 *ngIf="page" class="uk-h5 uk-margin-remove">{{page.name}}</h1>
</a>
</div>
<div search-input [disabled]="showLoading" [expandable]="true" [searchControl]="filterForm" searchInputClass="outer" placeholder="Search helptext" class="uk-width-1-3@xl uk-width-2-5@l uk-width-1-2@m uk-width-1-1">
</div>
<div>
<button (click)="newPageContent()" [disabled]="showLoading" [class.uk-disabled]="showLoading"
class="uk-flex uk-flex-middle uk-button uk-button-default">
<icon [flex]="true" name="add"></icon>
<span class="uk-margin-small-left">Add class help text</span>
<div class="uk-text-bold">
<span *ngIf="selectedPageId && page">{{page.name}}</span>
</div>
<div class="uk-margin-top">
<a routerLink="../pages/" class="uk-text-secondary uk-text-uppercase uk-text-bold uk-text-small">
<span class="uk-icon-button small uk-icon uk-button-secondary">
<icon name="arrow_left"></icon>
</span>
<span class="space">
Back to pages list
</span>
</a>
</div>
<div 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 #searchInputComponent search-input [control]="filterForm" [showSearch]="false" placeholder="Search helptext"
[selected]="selectedKeyword" (closeEmitter)="onSearchClose()" (resetEmitter)="reset()"
[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>
<a (click)="newPageContent()"
class="uk-flex uk-flex-middle uk-text-uppercase">
<button class="large uk-icon-button uk-button-secondary">
<icon name="add"></icon>
</button>
</div>
<button class="uk-button uk-button-link uk-margin-small-left uk-text-secondary">Add new class help text
</button>
</a>
</div>
</div>
<div *ngIf="showLoading && checkboxes.length > 0"
class="uk-padding uk-padding-remove-bottom uk-padding-remove-top uk-margin-remove-top uk-margin-small-bottom uk-display-inline"
[attr.uk-tooltip]="getSelectedPageHelpContents().length == 0 ? 'pos:left; cls: uk-active' : 'cls: uk-invisible'"
title="Select at least one help text"><input id="checkAll" type="checkbox" (click)="selectAll()"
[ngModel]="getSelectedPageHelpContents().length ==checkboxes.length"/>
<span *ngIf="getSelectedPageHelpContents().length > 0" class="uk-margin-left uk-text-muted">
{{getSelectedPageHelpContents().length}} pages selected </span>
<a class="uk-margin-left ">Actions </a>
<div uk-dropdown="mode: click">
<ul class="uk-nav uk-dropdown-nav"
[attr.uk-tooltip]="getSelectedPageHelpContents().length == 0 ? 'pos:left; cls: uk-active' : 'cls: uk-invisible'"
title="Select at least one help text">
<li><a [class]="getSelectedPageHelpContents().length == 0 ? 'uk-disabled' : ''"
(click)="togglePageHelpContents(true,getSelectedPageHelpContents())"><i></i> Enable
</a></li>
<li><a [class]="getSelectedPageHelpContents().length == 0 ? 'uk-disabled' : ''"
(click)="togglePageHelpContents(false,getSelectedPageHelpContents())"><i></i> Disable
</a>
</li>
<li><a [class]="getSelectedPageHelpContents().length == 0 ? 'uk-disabled' : ''"
(click)="confirmDeleteSelectedPageHelpContents()"><i></i> Delete </a></li>
</ul>
</div>
</div>
</div>
<div inner>
<div class="uk-section uk-section-small uk-position-relative" style="min-height: 60vh">
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
<ng-container *ngIf="!showLoading">
<div *ngIf="checkboxes.length == 0"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-text-bold">
<div>No class help texts found</div>
</div>
<div *ngIf="checkboxes.length > 0">
<div class="uk-grid uk-child-width-1-2@l uk-child-width-1-1" uk-height-match=".uk-card-body" uk-grid>
<div *ngFor="let check of checkboxes; let i=index">
<div class="uk-card uk-card-default uk-margin-bottom">
<div class="uk-card-body">
<div class="uk-margin-medium-bottom">
<div class="multi-line-ellipsis lines-2">
<p>{{check.divHelpContent.content | htmlToString}}</p>
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
<div *ngIf="!showLoading">
<div *ngIf="checkboxes.length > 0" class="uk-margin-medium-bottom">
<ul class="uk-list pages">
<li *ngFor="let check of checkboxes; let i=index" class="uk-card uk-card-default uk-margin-bottom">
<div class="uk-grid uk-grid-divider uk-padding" uk-grid>
<div class="uk-width-4-5 uk-first-column ">
<div class="uk-grid uk-flex uk-flex-middle">
<div><input id="{{check.divHelpContent._id}}" class="checkBox" type="checkbox"
name="entitiescb[]" value="{{check.divHelpContent._id}}"
[(ngModel)]="check.checked">
</div>
<div class="uk-width-expand uk-margin-medium-bottom">
<div class="content multi-line-ellipsis lines-2">
<p>{{check.divHelpContent.content|htmlToString}}</p></div>
</div>
<div class="uk-grid uk-width-1-1 uk-margin-left">
<div class=" ">
<span
class="title">Class: </span>{{check.divHelpContent.divId.name ? check.divHelpContent.divId.name : check.divHelpContent.divId}}
</div>
<div class="uk-text-small">
<span class="uk-text-meta">Class: </span>{{check.divHelpContent.divId.name ? check.divHelpContent.divId.name : check.divHelpContent.divId}}
<div class=" ">
<span class="title uk-margin-small-right">Enable/disable: </span>
<mat-slide-toggle [checked]="check.divHelpContent.isActive"
(change)="($event.source.checked = check.divHelpContent.isActive);togglePageHelpContents(!check.divHelpContent.isActive,[check.divHelpContent._id])"
uk-tooltip="title:<div class='uk-padding-small uk-width-large'><div class='uk-text-bold '> Enable or disable help text to show or hide it from the dashboard</div></div>"
></mat-slide-toggle>
</div>
</div>
</div>
<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">
<mat-slide-toggle [checked]="check.divHelpContent.isActive"
(change)="($event.source.checked = check.divHelpContent.isActive);togglePageHelpContents(!check.divHelpContent.isActive,[check.divHelpContent._id])"
uk-tooltip="title:<div><div class='uk-text-bold '> Enable or disable help text to show or hide it from the dashboard</div></div>">
<span class="uk-text-small">Enable</span>
</mat-slide-toggle>
</div>
</div>
<div><div class="uk-padding-small uk-padding-remove-horizontal">
<button class="uk-button uk-button-link uk-flex uk-flex-middle" (click)="editPageHelpContent(check.divHelpContent._id)">
<icon name="edit" [flex]="true"></icon>
<span class="uk-margin-xsmall-left"> Edit</span>
</button>
</div>
</div>
<div>
<div class="uk-padding-small uk-padding-remove-horizontal">
<button class="uk-button uk-button-link uk-flex uk-flex-middle"
(click)="confirmDeletePageHelpContent(check.divHelpContent._id)">
<icon name="delete" [flex]="true"></icon>
<span class="uk-margin-xsmall-left"> Delete</span>
</button>
</div>
</div>
</div>
<div class="uk-width-1-5 uk-first-column">
<div class=" uk-flex-center uk-flex">
<div class="actions" href="#">
<button (click)="editPageHelpContent(check.divHelpContent._id)" class="uk-button action uk-margin-top uk-flex uk-flex-middle">
<icon name="edit"></icon>
<span class="uk-margin-small-left">Edit</span>
</button>
<button (click)="confirmDeletePageHelpContent(check.divHelpContent._id)"
class="uk-button action uk-margin-top uk-flex uk-flex-middle">
<icon name="remove"></icon>
<span class="uk-margin-small-left">Delete</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-container>
</li>
</ul>
</div>
<div *ngIf="checkboxes.length == 0"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div>No class help texts found</div>
</div>
</div>
</div>
</div>
<modal-alert #AlertModalDeletePageHelpContents [overflowBody]="false" classTitle="uk-background-primary uk-light"
(alertOutput)="confirmedDeletePageHelpContents($event)"></modal-alert>
<modal-alert #AlertModalDeletePageHelpContents (alertOutput)="confirmedDeletePageHelpContents($event)"></modal-alert>

Some files were not shown because too many files have changed in this diff Show More