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
532 changed files with 22809 additions and 40272 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 { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';
import { TransferState } from '@angular/core';
import { properties } from "../../environments/environment"; import { properties } from "../../environments/environment";
@Injectable({ @Injectable({
@ -8,39 +9,29 @@ import { properties } from "../../environments/environment";
export class CacheInterceptorService implements HttpInterceptor { export class CacheInterceptorService implements HttpInterceptor {
cachingRequests = [ cachingRequests = [
// Remove 2 following lines when bug with hidden refine filters is solved. // 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=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=projectoamandatepublications&&type=projects&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=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=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=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=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=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=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=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=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=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=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=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=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=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=projectoamandatepublications&fields=projectstartyear&fields=projectendyear&&type=projects&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=eoscdatasourcetype&fields=datasourceodlanguages&fields=datasourceodcontenttypes&fields=datasourcecompatibilityname&fields=country&fields=collectedfromname&fields=datasourcethematic&fields=datasourcejurisdiction&&type=datasources&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&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&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", "/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",
"/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",
"/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", "/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", "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"
]; ];
@ -58,13 +49,7 @@ export class CacheInterceptorService implements HttpInterceptor {
} }
public checkForCachedRequests(url){ public checkForCachedRequests(url){
// Do not call cache when it is not enabled at all. if(url.indexOf("refine=true") !== -1 || url.indexOf("/count?format=json") !== -1 || url.indexOf("relresulttype%3Dpublication") !== -1) {
// 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)) {
return this.cachingRequests.some(partUrl => (url.indexOf(partUrl) !== -1)); return this.cachingRequests.some(partUrl => (url.indexOf(partUrl) !== -1));
} }
return false; return false;

View File

@ -1,133 +1,313 @@
<div> <div>
<div class="uk-width-xlarge@l uk-width-large" [ngClass]="centerAlign ? 'uk-align-center':''"> <div>
<advanced-search-input> <div class="uk-grid uk-margin-top uk-animation-fade">
<div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..." <div class="uk-width-expand">
[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" <div class="uk-grid uk-flex uk-flex-middle">
[hint]="'Search for ' + openaireEntities.COMMUNITIES + '...'" tooltip="true"></div> <div class="uk-width-1-2">
</advanced-search-input> Select communities to link to
</div> </div>
<div *ngIf="communities"class="uk-padding"> <div class="uk-width-1-2">
<div class="uk-grid uk-child-width-1-3" uk-height-match=".uk-card" uk-grid> <div class="uk-margin">
<div *ngFor="let community of filter()"> <div class="uk-inline">
<a class="uk-link-reset uk-height-1-1" (click)="select(community.id, community.label)"> <span class="uk-form-icon uk-icon" ><svg width="20" height="20" viewBox="0 0 20 20"
<div [title]="(this.results.length>=basketLimit)?'Basket reached the size limit':''" 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>
class="uk-card uk-card-default uk-card-hover uk-padding-small uk-text-center"> <input class=" uk-input uk-width-medium" [(ngModel)]="keyword" name="keyword"
<div class="uk-text-right"> placeholder="Search communities..."/>
<button class="linking-add-button uk-icon-button-small" [class.uk-disabled]="(this.results.length>=basketLimit)" *ngIf="!isSelected(community.id)"> <span *ngIf="keyword.length > 0" class="uk-margin-small-right uk-icon" style="cursor: pointer;"
<icon name="add" [flex]="true"></icon> (click)="keyword='';">
</button> <svg width="20" height="20" viewBox="0 0 20 20"
<button *ngIf="isSelected(community.id)" class="linking-selected-button uk-icon-button-small"> xmlns="http://www.w3.org/2000/svg" data-svg="close"><path fill="none" stroke="#000"
<icon name="check" [flex]="true"></icon> stroke-width="1.06"
</button> d="M16,16 L4,4"></path><path
</div> fill="none"
<img *ngIf="communityLogos && communityLogos[community.id]" stroke="#000"
[src]="communityLogos[community.id] | logoUrl" stroke-width="1.06"
class="uk-blend-multiply" d="M16,4 L4,16"></path></svg>
[alt]="((community.title)?community.title:(community.shortTitle?community.shortTitle:'')) + ' logo'" </span>
loading="lazy" style="max-height:70px"> </div>
<div class="uk-margin-small-top"> </div>
{{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>
<div *ngIf="conceptsCategoryLoading[category.id]" class="uk-alert uk-alert-primary"
role="alert">Loading category information...
</div> </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 <!-- Categories modal-->
*ngIf="conceptsClass[category.id] && conceptsClass[category.id].length == 0 && conceptsClassDisplay[category.id]">No more paths found <div id="modal-categories" uk-modal="bg-close:false;">
</div> <div class="uk-modal-dialog uk-modal-body uk-height-min-medium">
<ul *ngIf="conceptsClass[category.id] && conceptsClassDisplay[category.id]" <a class="uk-modal-close uk-position-right uk-margin-right uk-margin-top" type="button">
class="uk-list uk-animation-fade uk-margin-left uk-margin-top" id="ul_{{category.id}}"> <svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg" data-svg="close-icon">
<li *ngFor="let concept1 of conceptsClass[category.id]"> <line fill="none" stroke="#000" stroke-width="1.1" x1="1" y1="1" x2="13" y2="13"></line>
<div (click)="displaySubcategory(concept1.id)"> <line fill="none" stroke="#000" stroke-width="1.1" x1="13" y1="1" x2="1" y2="13"></line>
<input [ngModel]="isSelected(concept1.id)" type="checkbox" </svg>
(ngModelChange)="isSelected(concept1.id)?removeById(concept1.id):addNewContext(selectedCommunityLabel,category.label,concept1);"> </a>
<span class="uk-margin-small-left">{{concept1.label}}</span>
<span *ngIf="concept1.concepts && concept1.concepts.length==0"> <div class="portal-color uk-margin-top">
<span *ngIf="!conceptsClassDisplay[concept1.id]" uk-icon="icon:chevron-down; ratio:0.7"></span> <span class="uk-icon-button icon-button-small portal-icon-button uk-icon">
<span *ngIf="conceptsClassDisplay[concept1.id]" uk-icon="icon:chevron-up; ratio:0.7"></span> <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> </span>
</div> <span
<div> class="uk-text-bold">{{selectedCommunityLabel}}</span> community is now in your Links Basket
<div </div>
*ngIf="concept1.concepts && concept1.concepts.length==0 && conceptsClassDisplay[concept1.id]">No more paths found <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> </div>
<ul *ngIf="concept1.concepts && conceptsClassDisplay[concept1.id] " <div
class="uk-list uk-animation-fade uk-margin-left uk-margin-top"> [class]="(conceptsClassDisplay[category.id] && conceptsClass[category.id] && conceptsClass[category.id].length>5)?'uk-panel-scrollable':''">
<li *ngFor="let concept2 of concept1.concepts"> <div
<div (click)="displaySubcategory(concept2.id)"> *ngIf="conceptsClass[category.id] && conceptsClass[category.id].length == 0 && conceptsClassDisplay[category.id]">No more paths found
<input [ngModel]="isSelected(concept2.id)" type="checkbox" </div>
(ngModelChange)="isSelected(concept2.id)?removeById(concept2.id):addNewContext(selectedCommunityLabel,category.label,concept2);" > <ul *ngIf="conceptsClass[category.id] && conceptsClassDisplay[category.id]"
<span *ngIf="concept2.concepts && concept2.concepts.length==0"> class="uk-list uk-animation-fade" id="ul_{{category.id}}">
<span class="uk-margin-small-left">{{concept2.label}}</span><span *ngIf="!conceptsClassDisplay[concept1.id]" uk-icon="icon:chevron-down; ratio:0.7"></span> <li *ngFor="let concept1 of conceptsClass[category.id]">
<span *ngIf="conceptsClassDisplay[concept1.id]" uk-icon="icon:chevron-up; ratio:0.7"></span> <span (click)="displaySubcategory(concept1.id)">
</span> <span *ngIf="!conceptsClassDisplay[concept1.id] && concept1.concepts" class="uk-icon"><svg
</div> width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon
<ul *ngIf="concept2.concepts && conceptsClassDisplay[concept2.id] " points="8 5 13 10 8 15"></polygon></svg></span>
class="uk-list uk-animation-fade uk-margin-left uk-margin-top">
<li *ngFor="let concept3 of concept2.concepts"> <span *ngIf="conceptsClassDisplay[concept1.id] && concept1.concepts" class="uk-icon">
<input [ngModel]="isSelected(concept3.id)" type="checkbox" <svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" ratio="1"> <polygon
(ngModelChange)="isSelected(concept3.id)?removeById(concept2.id):addNewContext(selectedCommunityLabel,category.label,concept3);"> points="5 7 15 7 10 12"></polygon></svg></span>
<span class="uk-margin-small-left">{{concept3.label}}</span> {{concept1.label}}
</li> </span>
</ul> <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> </li>
</ul> </ul>
</div> </ul>
</li> </div>
</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>
<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 {Router} from '@angular/router';
import {ContextsService} from './service/contexts.service'; 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 {EnvProperties} from '../../utils/properties/env-properties';
import {Subscriber} from "rxjs"; 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; declare var UIkit: any;
@ -17,16 +15,13 @@ declare var UIkit: any;
}) })
export class ClaimContextSearchFormComponent { export class ClaimContextSearchFormComponent {
@Input() public centerAlign: boolean = false;
@Input() public results:ClaimEntity[]; @Input() public results:ClaimEntity[];
@Input() public sources; @Input() public sources;
@Input() public properties: EnvProperties; @Input() public properties: EnvProperties;
@Input() communityId: string = null; @Input() communityId: string = null;
@Input() public inlineClaim: boolean = false; @Input() public inlineClaim: boolean = false;
@Input() basketLimit; @Input() basketLimit;
@Input() showOptions:ShowOptions;
@ViewChild('modal') modal;
modalClicked = false;
public selectedCommunityId: string = "0"; public selectedCommunityId: string = "0";
public selectedCategoryId: string = "0"; public selectedCategoryId: string = "0";
public query = ''; public query = '';
@ -43,47 +38,11 @@ export class ClaimContextSearchFormComponent {
public loading: boolean = false; public loading: boolean = false;
public error: boolean = false; public error: boolean = false;
@Input() localStoragePrefix: string = ""; @Input() localStoragePrefix: string = "";
openaireEntities = OpenaireEntities;
entitiesSelectOptions;
keyword = ""; keyword = "";
subscriptions = []; subscriptions = [];
communityLogos = {};
communityIds = [];
user = null;
ngOnInit() { ngOnInit() {
this.entitiesSelectOptions = this.showOptions.selectOptions; this.getCommunities();
//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 => {
}));
} }
ngOnDestroy() { ngOnDestroy() {
this.subscriptions.forEach(subscription => { 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() { getCommunityClass(community) {
return this.communities?this.communities.filter(community => this.keyword.length ==0 || community.label.toLowerCase().indexOf(this.keyword.toLowerCase()) != -1):[]; 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.selectedCommunityId = community.id;
this.selectedCommunityLabel = community.label; this.selectedCommunityLabel = community.label;
this.getCategories(); this.getCategories();
this.removeById(community.id); if (this.isSelected(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 (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 { } 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 { isSelected(id): boolean {
for (let _i = 0; _i < this.results.length; _i++) { for (let _i = 0; _i < this.results.length; _i++) {
let item = this.results[_i]; let item = this.results[_i];
@ -159,40 +91,44 @@ export class ClaimContextSearchFormComponent {
} }
return false; 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() ; const entity: ClaimEntity = new ClaimEntity() ;
entity.type = "community"; entity.type = "community";
entity.context = {community: community, category: category, concept: concept}; entity.context = {community: community, category: category, concept: concept};
entity.id = entity.context.concept.id; entity.id = entity.context.concept.id;
return entity;
}
addNewContext(community, category, concept, notify = true) {
const entity: ClaimEntity = this.getClaimEntity(community, category, concept) ;
this.warningMessage = ""; this.warningMessage = "";
if (!this.isSelected(entity.id)) { if (!this.isSelected(entity.id)) {
this.results.push(entity); this.results.push(entity);
localStorage.setItem(this.localStoragePrefix, JSON.stringify(this.results)); localStorage.setItem(this.localStoragePrefix, JSON.stringify(this.results));
UIkit.notification(OpenaireEntities.COMMUNITY + ' added in your basket!', {
status: 'success',
timeout: 4000,
pos: 'bottom-right'
});
} }
} }
getCommunities() { getCommunities() {
if (!Session.isLoggedIn()) {
this.saveStateAndRedirectLogin();
} else {
this.loading = true; this.loading = true;
this.subscriptions.push(this._contextService.getCommunitiesByState().subscribe( this.subscriptions.push(this._contextService.getPublicCommunitiesByState().subscribe(
data => { data => {
this.communities = data.filter(community => { this.communities = data;
return this.communityIds.indexOf(community.id) != -1
});
if (this.communities.length > 0) { 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; this.loading = false;
if (this.communityId != null && this.communityIds.indexOf(this.communityId) != -1) { if (this.communityId != null) {
//preselect community //preselect community
this.selectedCommunityId = this.communityId; this.selectedCommunityId = this.communityId;
for (let i = 0; i < this.communities.length; i++) { for (let i = 0; i < this.communities.length; i++) {
@ -215,26 +151,25 @@ export class ClaimContextSearchFormComponent {
this.error = true; this.error = true;
} }
)); ));
}
} }
getCategories() { getCategories() {
this.loading = true; this.loading = true;
// this.categories=[]; // this.categories=[];
if (this.selectedCommunityId != '0') { if (this.selectedCommunityId != '0') {
if (!Session.isLoggedIn()) {
this.saveStateAndRedirectLogin();
} else {
if (this.categories[this.selectedCommunityId]) { if (this.categories[this.selectedCommunityId]) {
this.loading = false; this.loading = false;
if(this.categories[this.selectedCommunityId].length > 0){
this.openModal()
}
return; return;
} }
this.subscriptions.push(this._contextService.getCategories(this.selectedCommunityId, this.properties.contextsAPI).subscribe( this.subscriptions.push(this._contextService.getCategories(this.selectedCommunityId, this.properties.contextsAPI).subscribe(
data => { data => {
if(data.length > 0){
this.openModal()
}
this.categories[this.selectedCommunityId] = data; this.categories[this.selectedCommunityId] = data;
this.concepts = []; this.concepts = [];
if (this.query !== "") { 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) { displaySubcategory(id) {
if (this.conceptsClassDisplay[id] != null) { if (this.conceptsClassDisplay[id] != null) {
this.conceptsClassDisplay[id] = !this.conceptsClassDisplay[id]; this.conceptsClassDisplay[id] = !this.conceptsClassDisplay[id];
@ -263,6 +268,9 @@ export class ClaimContextSearchFormComponent {
} }
browseConcepts(categoryId) { browseConcepts(categoryId) {
if (!Session.isLoggedIn()) {
this.saveStateAndRedirectLogin();
} else {
if (this.conceptsClass[categoryId] != null) { if (this.conceptsClass[categoryId] != null) {
this.conceptsClassDisplay[categoryId] = !this.conceptsClassDisplay[categoryId]; this.conceptsClassDisplay[categoryId] = !this.conceptsClassDisplay[categoryId];
return; return;
@ -290,6 +298,8 @@ export class ClaimContextSearchFormComponent {
this.conceptsCategoryLoading[categoryId] = false; this.conceptsCategoryLoading[categoryId] = false;
} }
)); ));
}
} }
browseSubConcepts(categoryId, conceptId) { 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) { private static handleError(message: string, error) {
console.error("Claim context search form (component): " + message, error); console.error("Claim context search form (component): " + message, error);
} }

View File

@ -1,26 +1,18 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { SharedModule } from '../../../openaireLibrary/shared/shared.module'; import { SharedModule } from '../../shared/shared.module';
import { ClaimContextSearchFormComponent } from './claimContextSearchForm.component'; import { ClaimContextSearchFormComponent } from './claimContextSearchForm.component';
import {StaticAutocompleteModule} from '../../utils/staticAutoComplete/staticAutoComplete.module'; import {StaticAutocompleteModule} from '../../utils/staticAutoComplete/staticAutoComplete.module';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import {HelperModule} from '../../utils/helper/helper.module'; 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({ @NgModule({
imports: [ imports: [
SharedModule, RouterModule, SharedModule,RouterModule,
StaticAutocompleteModule, StaticAutocompleteModule,
HelperModule, ClaimProjectsSearchFormModule, AdvancedSearchInputModule, InputModule, LogoUrlPipeModule, IconsModule, AlertModalModule HelperModule
], ],
providers: [CommunitiesService],
declarations: [ declarations: [
ClaimContextSearchFormComponent ClaimContextSearchFormComponent
], exports: [ClaimContextSearchFormComponent ] ], exports: [ClaimContextSearchFormComponent ]

View File

@ -1,7 +1,5 @@
//Classes used in linking / inlinelinking when selecting an entity //Classes used in linking / inlinelinking when selecting an entity
import {HelperFunctions} from "../../utils/HelperFunctions.class"; import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {ClaimsProperties} from "./claims.properties";
export class ClaimResult { export class ClaimResult {
public source: string; public source: string;
@ -29,7 +27,6 @@ export class ClaimResult {
export class ClaimProject { export class ClaimProject {
public funderId: string; public funderId: string;
public funderShortname: string;
public funderName: string; public funderName: string;
public acronym: string; public acronym: string;
public startDate: string; public startDate: string;
@ -39,12 +36,6 @@ export class ClaimProject {
public fundingLevel0: string; public fundingLevel0: string;
public url: string; public url: string;
} }
export class ClaimOrganization {
public name: string;
// public shortName: string;
public url: string;
// public country: string;
}
export class ClaimContext { export class ClaimContext {
public community: string; public community: string;
@ -79,7 +70,6 @@ export class ClaimEntity {
result: ClaimResult; result: ClaimResult;
project: ClaimProject; project: ClaimProject;
context: ClaimContext; context: ClaimContext;
organization: ClaimOrganization;
constructor() { constructor() {
this.warningMessages = []; this.warningMessages = [];
@ -101,7 +91,6 @@ export class ClaimRecord2Insert {
targetAccessRights: string; targetAccessRights: string;
targetEmbargoEndDate: string; targetEmbargoEndDate: string;
claimedInDashboard: string; claimedInDashboard: string;
idSuffix:string;
constructor() { constructor() {
@ -116,7 +105,7 @@ export class ClaimDBRecord {
targetType: string; targetType: string;
semantics: string; semantics: string;
approved: string; approved: string;
source: ClaimDBResult | ClaimDBProject | ClaimDBContext; source: ClaimDBResult | ClaimProject | ClaimContext;
target: ClaimDBResult; target: ClaimDBResult;
indexed:boolean; indexed:boolean;
} }
@ -125,12 +114,7 @@ export class ClaimDBContext {
title: string; title: string;
openaireId: string; openaireId: string;
} }
export class ClaimDBOrganization {
openaireId: string;
name: string;
shortName: string;
country: string;
}
export class ClaimDBProject { export class ClaimDBProject {
openaireId: string; openaireId: string;
name: string; name: string;
@ -158,9 +142,9 @@ export class ShowOptions {
show: string; //show values: source, result, project, context, claim show: string; //show values: source, result, project, context, claim
linkTo: string; // linkTo /values: result, project, context linkTo: string; // linkTo /values: result, project, context
linkToEntities: string[]; // show linkToEntities /values: result, project, context linkToEntities: string[]; // show linkToEntities /values: result, project, context
basketShowSources: boolean = true; basketShowSources: boolean;
basketShowLinksTo: boolean = false; basketShowLinksTo: boolean;
selectOptions= [];
constructor() { constructor() {
this.show = "source"; this.show = "source";
this.linkTo = "project"; this.linkTo = "project";
@ -171,37 +155,23 @@ export class ShowOptions {
showSource() { showSource() {
this.show = "source"; this.show = "source";
this.basketswitchToSources();
HelperFunctions.scroll();
}
basketswitchToSources() {
this.basketShowLinksTo = false; this.basketShowLinksTo = false;
this.basketShowSources = true; this.basketShowSources = true;
} HelperFunctions.scroll();
basketswitchToLinkTo() {
this.basketShowLinksTo = true;
this.basketShowSources = false;
} }
showLinkTo() { showLinkTo() {
// console.log(this.linkTo, "showLinkTo")
this.show = this.linkTo; this.show = this.linkTo;
this.basketswitchToLinkTo(); this.basketShowLinksTo = true;
this.basketShowSources = false;
HelperFunctions.scroll(); HelperFunctions.scroll();
} }
initSelectOptions(claimProperties:ClaimsProperties){ showBasketSources() {
let options =[]; if (this.show != 'source') {
if(this.linkToEntities.indexOf('result')!=-1){ this.basketShowSources = !this.basketShowSources;
options.push({value: 'result',label: OpenaireEntities.RESULTS}) 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':''"> <form class=" uk-margin-top uk-animation ">
<advanced-search-input (searchEmitter)="search(page,size)"> <div class="uk-margin-small-bottom">Start searching for projects and add them to the basket to link them to your sources
<div input type="select" [(value)]="showOptions.show" placeholder="Type" hint="Select..." <!-- <helper div="link-project-form" tooltip=true></helper> -->
[options]="showOptions.selectOptions" class="uk-width-medium@xl uk-width-auto"></div> </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> <!-- <input class=" uk-input uk-width-large" [(ngModel)]="keyword" name="keyword" placeholder="Search for projects..."/>-->
<div class="uk-width-expand" input type="text" [(value)]="keyword" [searchable]="true" placeholder="Projects to link" <div class="uk-inline">
[hint]="'Search for ' + openaireEntities.PROJECTS + '...'" tooltip="true" [disabled]="isNoProjectFunder"></div> <a *ngIf="keyword.length > 0" class="uk-form-icon uk-form-icon-flip"
</advanced-search-input> (click)="keyword = ''"
</div> uk-icon="icon: close"></a>
<div *ngIf=" openaireResultsStatus != errorCodes.LOADING && !isNoProjectFunder && this.selectedFunder && openaireResults.length == 0"> <input type="text" class="uk-input uk-width-xlarge@l uk-width-large@m uk-width-medium"
<div class="uk-text-center uk-text-large uk-text-meta uk-margin-large-top">No {{openaireEntities.PROJECT.toLowerCase()}} results yet... <br>Start placeholder="Search for projects..." aria-describedby="sizing-addon2"
searching for {{openaireEntities.PROJECTS.toLowerCase()}} to add them in the Basket [(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> </div>
<div *ngIf=" openaireResultsStatus != errorCodes.LOADING && this.funderOptions.length > 1 && !this.selectedFunder"> <div *ngIf="showResults" class="uk-margin-top">
<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="openaireResultsStatus == errorCodes.NONE" class="uk-alert uk-alert-primary"
role="alert">No Results found
</div> </div>
</div> <div *ngIf="openaireResultsStatus == errorCodes.ERROR" class="uk-alert uk-alert-warning"
<div class="uk-margin-top"> role="alert">An Error Occured
<div class="uk-grid" uk-grid> </div>
<div *ngIf="!isNoProjectFunder && openaireResultsStatus != errorCodes.LOADING && openaireResultsNum > 1 " class="search-filters uk-width-1-1"> <div *ngIf="openaireResultsStatus == errorCodes.NOT_AVAILABLE" class="uk-alert uk-alert-danger"
<div class="uk-grid uk-grid-small" uk-grid> role="alert">Service not available
<ng-container *ngFor="let filter of rangeFilters"> </div>
<div>
<dropdown-filter [name]="filter.selectedFromAndToValues?filter.selectedFromAndToValues:filter.title" <div class="uk-grid">
dropdownMinWidth="450"> <div class="search-filters uk-width-medium">
<div class="uk-padding-small"> <!-- <div class="uk-width-1-1 uk-margin-small-bottom ">
<range-filter [isDisabled]="openaireResultsStatus == errorCodes.LOADING"
[filter]="filter" (onFilterChange)="dateFilterChanged(filter)" <div *ngIf="countFilters()>0" class="uk-margin-small-bottom">
[showQuickButtons]="false"
></range-filter> <span *ngIf = "searchUtils.keyword.length > 0"><span class="uk-text-bold">Keywords:</span>
</div> <a (click) = "clearKeywords() " title="Remove keywords" [class]="((disableForms)?' uk-disabled':' ')+' portal-color '"><span class=" clickable " aria-hidden="true"><span class="uk-icon ">
</dropdown-filter> <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> </div>
</ng-container>
<ng-container *ngFor="let filter of filters ">
<div> </div>
<dropdown-filter [count]="filter.countSelectedValues" [name]="filter.title"
dropdownMinWidth="450"> <div class="uk-margin-small-bottom uk-margin-small-top uk-grid">
<div class="uk-padding-small"> <a *ngIf="countFilters()>1" (click)="clearFilters()" [class]="((disableForms)?'uk-disabled uk-link-muted':'')+' portal-link ' + 'uk-width-1-2'">
<search-filter [isDisabled]="openaireResultsStatus == errorCodes.LOADING" Clear All
[filter]="filter" [filterValuesNum]="0" [showResultCount]=true </a>
(onFilterChange)="filterChanged($event)" [actionRoute]="false"></search-filter>
</div>
</dropdown-filter>
</div>
</ng-container>
</div> </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>
<div class="uk-width-expand@m uk-width-1-1@s uk-first-column"> <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" <!-- <div *ngIf="openaireResultsNum != null && openaireResultsNum > 0" class="uk-clearfix portal-hr ">
role="alert">No Results found <div class="uk-grid">
</div> <div *ngIf="openaireResultsNum>0" class="uk-width-1-2">
<div *ngIf="openaireResultsStatus == errorCodes.ERROR" class="uk-alert uk-alert-warning" <span class="portal-color">{{openaireResultsNum|number}}</span> projects, page <span
role="alert">An Error Occured class="portal-color">{{openaireResultsPage | number}}</span> of <span
</div> class="portal-color">{{totalPages(openaireResultsNum)|number}}</span>
<div *ngIf="openaireResultsStatus == errorCodes.NOT_AVAILABLE" class="uk-alert uk-alert-danger" </div>
role="alert">Service not available <div class="uk-width-1-2 uk-padding-remove">
</div> <paging-no-load class="uk-float-right" [currentPage]="openaireResultsPage"
<div *ngIf="openaireResultsStatus == errorCodes.LOADING" class="uk-animation-fade uk-margin-top uk-width-1-1" [totalResults]="openaireResultsNum" [term]="keyword" [size]="size"
role="alert"> (pageChange)="openaireResultsPageChange($event)"></paging-no-load>
<loading></loading> </div>
</div> </div>
<claim-results [localStoragePrefix]="localStoragePrefix" [results]=openaireResults </div>-->
[selectedResults]=selectedProjects [basketLimit]="basketLimit"></claim-results> <div *ngIf="openaireResultsNum != null && openaireResultsNum > 0" class="uk-clearfix ">
<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 class= "paging-hr searchPaging uk-margin-small-bottom"
<div *ngIf="openaireResultsNum != null && openaireResultsNum > 0 && openaireResultsStatus != errorCodes.LOADING " class="uk-flex uk-flex-center "> *ngIf="(openaireResultsNum > 0) || (openaireResultsStatus == errorCodes.LOADING)">
<paging-no-load [currentPage]="openaireResultsPage" <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" [totalResults]="openaireResultsNum" [term]="keyword"
[size]="size" (pageChange)="openaireResultsPageChange($event)"></paging-no-load> [size]="size" (pageChange)="openaireResultsPageChange($event)"></paging-no-load>
</div>
</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> </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 {SearchProjectsService} from '../../services/searchProjects.service';
import {ProjectService} from '../../landingPages/project/project.service'; import {ProjectService} from '../../landingPages/project/project.service';
import {ClaimEntity, ClaimProject} from './claimHelper.class'; import {ClaimEntity, ClaimProject} from './claimHelper.class';
@ -7,10 +7,9 @@ import {ErrorCodes} from '../../utils/properties/errorCodes';
import {StringUtils} from "../../utils/string-utils.class"; import {StringUtils} from "../../utils/string-utils.class";
import {Filter, Value} from "../../searchPages/searchUtils/searchHelperClasses.class"; import {Filter, Value} from "../../searchPages/searchUtils/searchHelperClasses.class";
import {RangeFilter} from "../../utils/rangeFilter/rangeFilterHelperClasses.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 {NewSearchPageComponent} from "../../searchPages/searchUtils/newSearchPage.component";
import {Subscriber} from "rxjs"; import {Subscriber} from "rxjs";
import { properties } from 'src/environments/environment';
declare var UIkit:any; declare var UIkit:any;
@ -21,17 +20,26 @@ declare var UIkit:any;
}) })
export class ClaimProjectsSearchFormComponent { 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 = ''; public query = '';
@Input() public centerAlign: boolean = false;
@Input() public selectedProjects:ClaimEntity[]=[] ; @Input() public selectedProjects:ClaimEntity[]=[] ;
public elementRef; public elementRef;
// public funders:string[];
// public selectedFunderId:string ="0";
// selectedFunderName:string ="Select funder:";
@Output() projectSelected = new EventEmitter(); @Output() projectSelected = new EventEmitter();
public properties:EnvProperties = properties; @Input() public properties:EnvProperties;
@Input() public inlineClaim:boolean=false; @Input() public inlineClaim:boolean=false;
@Input() localStoragePrefix:string = ""; @Input() localStoragePrefix:string = "";
@Input() basketLimit; @Input() basketLimit;
@Input() showOptions;
public errorCodes:ErrorCodes = new ErrorCodes(); public errorCodes:ErrorCodes = new ErrorCodes();
public projects:string[]; public projects:string[];
public warningMessage = ""; public warningMessage = "";
@ -44,94 +52,58 @@ export class ClaimProjectsSearchFormComponent {
keyword:string = ''; keyword:string = '';
showResults = false; 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 refineFields: string[] = ["funder"];
public refineFieldsQuery: string = "&refine=true&fields=funder"; public refineFieldsQuery: string = "&refine=true&fields=funder";
filters = []; filters = [];
prevFilters = []; prevFilters = [];
// startYear = "";
// endYear = "";
public rangeFilters: RangeFilter[] = []; public rangeFilters: RangeFilter[] = [];
public searchFields: SearchFields = new SearchFields(); public searchFields: SearchFields = new SearchFields();
public rangeFields:string[][] = this.searchFields.PROJECT_RANGE_FIELDS; 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) { constructor(private _service: ProjectService, private _projectService: SearchProjectsService, myElement: ElementRef) {
this.elementRef = myElement; this.elementRef = myElement;
this.rangeFilters = RangeFilter.parse(this.rangeFields,"project"); this.rangeFilters = RangeFilter.parse(this.rangeFields,"project");
this.getFunders();
} }
sub;
ngOnDestroy() { ngOnDestroy() {
if (this.sub instanceof Subscriber) { if (this.sub instanceof Subscriber) {
this.sub.unsubscribe(); 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").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 = [];
if(this.isNoProjectFunder){
this.showResults = true;
this.search(1,1);
}else{
this.openaireResults = [];
}
}
search(page,size) { search(page,size) {
/* if (this.keyword.length == 0) { if(this.keyword.length == 0){
this.showResults = false; this.showResults =false;
return; return;
}*/ }
this.showResults = true; this.showResults =true;
this.openaireResults = []; this.openaireResults = [];
this.openaireResultsStatus = this.errorCodes.LOADING; this.openaireResultsStatus = this.errorCodes.LOADING;
this.prevFilters = this.filters; this.prevFilters = this.filters;
//searchProjects (params: string, refineParams:string, page: number, size: number, refineFields:string[] , properties:EnvProperties ):any { //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).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 => { data => {
if (data != null) { if(data != null) {
this.openaireResultsPage = page; this.openaireResultsPage=page;
this.openaireResultsNum = data[0]; this.openaireResultsNum = data[0];
this.openaireResults = ClaimProjectsSearchFormComponent.openaire2ClaimEntity(data[1], this.properties); this.openaireResults =ClaimProjectsSearchFormComponent.openaire2ClaimEntity(data[1], this.properties);
if (data[2] && data[2].length > 0) { if(data[2] && data[2].length > 0){
this.filters = this.checkSelectedFilters(data[2], this.prevFilters); this.filters = this.checkSelectedFilters( data[2], this.prevFilters);
} }
this.openaireResultsStatus = this.errorCodes.DONE; this.openaireResultsStatus = this.errorCodes.DONE;
if (this.openaireResultsNum == 0) { if(this.openaireResultsNum == 0){
this.openaireResultsStatus = this.errorCodes.NONE; this.openaireResultsStatus = this.errorCodes.NONE;
this.filters = this.checkSelectedFilters([], this.prevFilters); }
}else {
this.openaireResultsStatus = this.errorCodes.ERROR;
} }
/* if(this.isNoProjectFunder && this.claimResultsComponent){ },
this.claimResultsComponent.add(this.openaireResults[0])
}*/
} else {
this.openaireResultsStatus = this.errorCodes.ERROR;
}
},
err => { err => {
this.openaireResultsStatus = this.errorCodes.ERROR; this.openaireResultsStatus = this.errorCodes.ERROR;
//console.log(err.status); //console.log(err.status);
@ -139,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); let index:number =this.selectedProjects.indexOf(item);
if (index > -1) { if (index > -1) {
this.selectedProjects.splice(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[] = []; const projects: ClaimEntity[] = [];
for(const item of items){ for(const item of items){
const entity: ClaimEntity = new ClaimEntity(); const entity: ClaimEntity = new ClaimEntity();
entity.project = new ClaimProject(); entity.project = new ClaimProject();
entity.project.funderId = item.funderId; entity.project.funderId = item.funderId;
entity.project.funderShortname = item.funderShortname?item.funderShortname:(entity.project.funderId?entity.project.funderId.split("::")[1]:""); entity.project.funderName = item.funderShortname;
entity.project.funderName = item.funderName;
entity.id = item.id; 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.title = item.title.name;
entity.project.acronym = item.acronym; entity.project.acronym = item.acronym;
entity.project.startDate = item.startYear; entity.project.startDate = item.startYear;
@ -178,47 +212,43 @@ export class ClaimProjectsSearchFormComponent {
} }
createOpenaireQueryParams(): string { createOpenaireQueryParams():string {
let query = ""; let query = "";
if (this.keyword.length > 0) { if(this.keyword.length > 0){
// query += "q=" + StringUtils.quote(StringUtils.URIEncode(this.keyword)); query += "q=" + StringUtils.quote(StringUtils.URIEncode(this.keyword));
query += 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 = ""; let allFqs = "";
for (let filter of this.filters) { for (let filter of this.filters){
if (filter.countSelectedValues > 0) { if(filter.countSelectedValues > 0){
let count_selected = 0; let count_selected=0;
let fq = ""; let fq = "";
for (let value of filter.values) { for (let value of filter.values){
if (value.selected == true) { if(value.selected == true){
count_selected++; 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) { if(count_selected > 0){
fq = "&fq=" + StringUtils.URIEncode(fq); fq="&fq="+StringUtils.URIEncode(fq);
allFqs += fq; allFqs += fq;
} }
} }
} }
if(this.selectedFunder){ for (let i=0; i<this.rangeFilters.length; i++){
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++) {
let filter = this.rangeFilters[i]; let filter = this.rangeFilters[i];
//selectedFromValue, selectedToValue, equalityOp, equalityOpFrom, equalityOpTo, filterOp ){ //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() { public yearChanged() {
this.search(this.page, this.size); this.search(this.page, this.size);
@ -253,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; 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 { SharedModule } from '../../shared/shared.module';
import {CommonModule} from '@angular/common'; import { CommonModule } from '@angular/common';
import {ClaimProjectsSearchFormComponent} from './claimProjectSearchForm.component'; import {ClaimProjectsSearchFormComponent} from './claimProjectSearchForm.component';
// import {LoadingModalModule} from '../../utils/modal/loadingModal.module';
import {ProjectServiceModule} from '../../landingPages/project/projectService.module'; import {ProjectServiceModule} from '../../landingPages/project/projectService.module';
import {ProjectsServiceModule} from '../../services/projectsService.module'; import {ProjectsServiceModule} from '../../services/projectsService.module';
import {EntitiesAutocompleteModule} from '../../utils/entitiesAutoComplete/entitiesAutoComplete.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 {ClaimResultsModule} from './claimResults.module';
import {PagingModule} from '../../utils/paging.module'; import {PagingModule } from '../../utils/paging.module';
import {SearchFilterModule} from '../../searchPages/searchUtils/searchFilter.module'; import {SearchFilterModule} from '../../searchPages/searchUtils/searchFilter.module';
import {RangeFilterModule} from "../../utils/rangeFilter/rangeFilter.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({ @NgModule({
imports: [ imports: [
SharedModule, CommonModule, SharedModule, CommonModule,
// LoadingModalModule, // LoadingModalModule,
ProjectServiceModule, ProjectsServiceModule, EntitiesAutocompleteModule, HelperModule, ProjectServiceModule, ProjectsServiceModule, EntitiesAutocompleteModule, HelperModule,
PagingModule, SearchFilterModule, ClaimResultsModule, RangeFilterModule, AdvancedSearchInputModule, InputModule, DropdownFilterModule, LoadingModule PagingModule, SearchFilterModule, ClaimResultsModule, RangeFilterModule
], ],
providers:[ providers:[
], ],
declarations: [ declarations: [
ClaimProjectsSearchFormComponent, ClaimProjectsSearchFormComponent
],
exports: [ClaimProjectsSearchFormComponent] ],
}) exports: [ClaimProjectsSearchFormComponent ]
})
export class ClaimProjectsSearchFormModule { } export class ClaimProjectsSearchFormModule { }

View File

@ -1,21 +1,28 @@
<div class="uk-flex uk-flex-center uk-flex-left@m"> <form class=" uk-margin-top">
<div *ngIf="showOptions && showOptions.linkToEntities.length > 0" class="uk-width-xlarge@l uk-width-large" [ngClass]="centerAlign ? 'uk-align-center':''"> <div class="uk-margin-small-bottom">Start searching Research Outcomes and add them to the Basket to Link
<advanced-search-input (searchEmitter)="search(true)"> <!-- <helper div="link-entity-form" styleName="" tooltip=true></helper> -->
<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>
</div> </div>
<div *ngIf="!showOptions" class="uk-width-xlarge@l uk-width-large">
<div search-input [(value)]="keyword" [placeholder]="'Search for ' + openaireEntities.RESULTS.toLowerCase() + '...'" <!-- <input class=" uk-input uk-width-large form-control" [(ngModel)]="keyword" name="keyword"-->
[searchInputClass]="'inner background'" (searchEmitter)="search(true)"></div> <!-- 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>
</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 *ngIf="!showSearchResults">
<div class="uk-text-center uk-text-large uk-text-meta uk-margin-large-top"> <div class="uk-text-center uk-text-large uk-text-muted uk-margin-large-top">
No {{showOptions?openaireEntities.RESULTS.toLowerCase() :'sources'}} yet...<br>Use the searchbar to find and link No research outcomes yet...<br>Start searching for research outcomes to add them in the Basket
{{showOptions?openaireEntities.RESULTS.toLowerCase() :'sources'}}.
</div> </div>
</div> </div>
<div *ngIf="showSearchResults" class="uk-margin-top uk-animation"> <div *ngIf="showSearchResults" class="uk-margin-top uk-animation">
@ -47,63 +54,135 @@
</div> </div>
<div *ngIf="crossrefResultsNum != null && crossrefResultsNum > 0" class="uk-clearfix "> <div *ngIf="crossrefResultsNum != null && crossrefResultsNum > 0" class="uk-clearfix ">
<div class="uk-grid"> <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> </div>
<div *ngIf="crossrefStatus === errorCodes.LOADING" class="uk-animation-fade uk-margin-top uk-width-1-1" <div *ngIf="crossrefStatus === errorCodes.LOADING" class="uk-animation-fade uk-margin-top uk-width-1-1"
role="alert"> role="alert"><span class="loading-gif uk-align-center"></span></div>
<loading></loading>
</div>
<div> <div>
<claim-results [localStoragePrefix]=localStoragePrefix [results]=crossrefResults <claim-results [localStoragePrefix]=localStoragePrefix [results]=crossrefResults
[selectedResults]=selectedResults [basketLimit]="basketLimit"></claim-results> [selectedResults]=selectedResults [basketLimit]="basketLimit"></claim-results>
</div> </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> </div>
<div *ngIf="activeTab == 'openaire'" id="openaire" class="uk-animation-fade"> <div *ngIf="activeTab == 'openaire'" id="openaire" class="uk-animation-fade">
<div class="uk-grid"> <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 openaireResultsfilters " >
<ng-container *ngFor="let filter of rangeFilters"> <ng-container *ngIf = "filter.countSelectedValues > 0">
<div> <span *ngFor="let value of getSelectedValues(filter); let i = index; let end = last; "
<dropdown-filter [name]="filter.selectedFromAndToValues?filter.selectedFromAndToValues:filter.title" [title]="'Remove '+value.name" (click) = "removeFilter(value, filter) " >
dropdownMinWidth="450"> <!-- if no grid on the div above, remove it and move class 'selectedFilterLabel' on top span -->
<div class="uk-padding-small"> <span class="selectedFilterLabel ">
<range-filter [isDisabled]="openaireResultsStatus == errorCodes.LOADING" <a [class]="((openaireResultsStatus ==
[filter]="filter" (onFilterChange)="dateFilterChanged(filter)" errorCodes.LOADING)?' uk-disabled':' ')+' uk-link-text '">
[showQuickButtons]="false" <span class=" clickable" aria-hidden="true">
></range-filter> <span class="uk-icon">
</div> <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>
</dropdown-filter> </span>
</div> </span>
<span class="uk-margin-small-left" [innerHtml]="(value.name.length > 34)?value.name.substring(0,34)+'...':value.name"></span>
</ng-container> </a>
<ng-container *ngFor="let filter of openaireResultsfilters "> </span>
<div *ngIf="(filter.values.length != 0 )"> </span>
<dropdown-filter [count]="filter.countSelectedValues" [name]="filter.title" </ng-container>
dropdownMinWidth="450"> </ng-container>
<div class="uk-padding-small"> </div>
<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>
<!-- 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>
<div class="uk-width-expand@m uk-width-1-1@s uk-first-column"> <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" <div *ngIf="openaireResultsStatus == errorCodes.NONE" class="uk-alert uk-alert-primary"
role="alert">No Results found role="alert">No Results found
</div> </div>
@ -113,17 +192,31 @@
<div *ngIf="openaireResultsStatus == errorCodes.NOT_AVAILABLE" class="uk-alert uk-alert-danger" <div *ngIf="openaireResultsStatus == errorCodes.NOT_AVAILABLE" class="uk-alert uk-alert-danger"
role="alert">Service not available role="alert">Service not available
</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"> 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" <div *ngIf="openaireResultsStatus === errorCodes.LOADING"
class="uk-animation-fade uk-margin-top uk-width-1-1" 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 <claim-results [localStoragePrefix]=localStoragePrefix
[results]=openaireResults [selectedResults]=selectedResults [basketLimit]="basketLimit"></claim-results> [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> </div>
</div> </div>
@ -138,7 +231,30 @@
<div *ngIf="orcidStatus == errorCodes.NONE && orcidResultsNum == -1" <div *ngIf="orcidStatus == errorCodes.NONE && orcidResultsNum == -1"
class="uk-alert uk-alert-primary "> No results found class="uk-alert uk-alert-primary "> No results found
</div> </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"> <div *ngIf="orcidResultsNum >= 0" class="panel-body">
<span><span class="uk-text-bold">Showing results for</span> <span><span class="uk-text-bold">Showing results for</span>
<a target="_blank" href="http://orcid.org/{{authorId}}"> <span <a target="_blank" href="http://orcid.org/{{authorId}}"> <span
@ -168,18 +284,9 @@
[selectedResults]=selectedResults [basketLimit]="basketLimit"></claim-results> [selectedResults]=selectedResults [basketLimit]="basketLimit"></claim-results>
<div *ngIf="orcidResultsNum == 0" class="uk-alert uk-alert-primary uk-margin-top"> No results found</div> <div *ngIf="orcidResultsNum == 0" class="uk-alert uk-alert-primary uk-margin-top"> No results found</div>
</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>
<div *ngIf="orcidStatus == errorCodes.LOADING" class="uk-animation-fade uk-margin-top uk-width-1-1" role="alert"> <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> </div>
<div *ngIf="activeTab == 'datacite'" id="datacite" class="uk-animation-fade"> <div *ngIf="activeTab == 'datacite'" id="datacite" class="uk-animation-fade">
@ -190,18 +297,35 @@
role="alert">Service not available role="alert">Service not available
</div> </div>
<div class="uk-margin-top"> <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" <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> <div>
<claim-results [localStoragePrefix]=localStoragePrefix *ngIf="dataciteResults.length > 0 " <claim-results [localStoragePrefix]=localStoragePrefix *ngIf="dataciteResults.length > 0 "
[results]=dataciteResults [selectedResults]=selectedResults [basketLimit]="basketLimit"></claim-results> [results]=dataciteResults [selectedResults]=selectedResults [basketLimit]="basketLimit"></claim-results>
</div> </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>
</div> </div>

View File

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

View File

@ -1,6 +1,6 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { SharedModule } from '../../../openaireLibrary/shared/shared.module'; import { SharedModule } from '../../shared/shared.module';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { MatSelectModule } from "@angular/material/select"; import { MatSelectModule } from "@angular/material/select";
import {ClaimResultSearchFormComponent} from './claimResultSearchForm.component'; import {ClaimResultSearchFormComponent} from './claimResultSearchForm.component';
@ -17,16 +17,10 @@ import {HelperModule} from '../../utils/helper/helper.module';
import {SearchFilterModule} from '../../searchPages/searchUtils/searchFilter.module'; import {SearchFilterModule} from '../../searchPages/searchUtils/searchFilter.module';
import {QuickSelectionsModule} from "../../searchPages/searchUtils/quick-selections.module"; import {QuickSelectionsModule} from "../../searchPages/searchUtils/quick-selections.module";
import {RangeFilterModule} from "../../utils/rangeFilter/rangeFilter.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({ @NgModule({
imports: [SharedModule, CommonModule, SearchResearchResultsServiceModule, PagingModule, SearchCrossrefServiceModule, 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:[ providers:[
SearchOrcidService SearchOrcidService
], ],

View File

@ -6,69 +6,78 @@ declare var UIkit: any;
@Component({ @Component({
selector: 'claim-results', selector: 'claim-results',
template: ` template: `
<div *ngIf="results.length > 0 " class="uk-margin-top">
<div *ngFor="let entity of results" class="uk-card"> <ul *ngIf="results.length > 0 " class="uk-list uk-list-divider">
<div class="uk-padding-small"> <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-grid">
<div class="uk-width-expand uk-margin-right"> <div class="uk-width-expand">
<claim-title [entity]="entity" [showIcon]="false"></claim-title> <claim-title [entity]="entity"></claim-title>
<claim-result-metadata [entity]="entity"></claim-result-metadata> <claim-result-metadata [entity]="entity"></claim-result-metadata>
<claim-project-metadata [entity]="entity"></claim-project-metadata> <claim-project-metadata [entity]="entity"></claim-project-metadata>
</div> </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':''"> <div class="uk-margin-auto-vertical uk-padding-remove-left uk-margin-small-left" [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)" <a [class]="(this.selectedResults.length>=basketLimit)?'uk-icon-button uk-disabled':'uk-icon-button'" *ngIf="!isSelected(entity)"
(click)="add(entity)"> (click)="add(entity)">
<icon name="add" [flex]="true"></icon> <span class="uk-icon">
</button> <svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="plus"
<button *ngIf="isSelected(entity)" class="linking-selected-button uk-icon-button-small" (click)="remove(entity)"> ratio="1"><rect x="9" y="1" width="1" height="17"></rect><rect x="1" y="9" width="17"
<icon name="check" [flex]="true"></icon> height="1"></rect></svg>
</button> </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> </div>
</div> </li>
</div> </ul>`,
`
}) })
export class ClaimResultsComponent { export class ClaimResultsComponent {
@Input() results: ClaimEntity[]; @Input() results: ClaimEntity[];
@Input() selectedResults: ClaimEntity[]; @Input() selectedResults: ClaimEntity[];
@Input() localStoragePrefix: string = ""; @Input() localStoragePrefix: string = "";
@Input() basketLimit; @Input() basketLimit;
private isSelected(result: ClaimEntity) {
ngOnInit() { let found: boolean = false;
} const id = result.id;
for (let _i = 0; _i < this.selectedResults.length; _i++) {
public isSelected(item: ClaimEntity) { let item = this.selectedResults[_i];
return !!this.selectedResults.find(result => item.id === result.id); 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) { 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); let found: boolean = this.isSelected(item);
if (!found) { if (!found) {
this.selectedResults.push(item); 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) { if (this.selectedResults != null) {
localStorage.setItem(this.localStoragePrefix, JSON.stringify(this.selectedResults)); 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 { NgModule } from '@angular/core';
import { SharedModule } from '../../../openaireLibrary/shared/shared.module'; import { SharedModule } from '../../shared/shared.module';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import {ClaimResultsComponent} from './claimResults.component'; import {ClaimResultsComponent} from './claimResults.component';
import {ClaimEntitiesMetadataModule} from "../linking/selected/ClaimEntitiesMetadata.module"; import {ClaimEntitiesMetadataModule} from "../linking/selected/ClaimEntitiesMetadata.module";
import {IconsModule} from "../../utils/icons/icons.module";
@NgModule({ @NgModule({
imports: [ imports: [
SharedModule, CommonModule, ClaimEntitiesMetadataModule, IconsModule SharedModule, CommonModule, ClaimEntitiesMetadataModule
], ],
providers:[ providers:[
], ],
declarations: [ 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> <schema2jsonld *ngIf="url" [URL]="url" [name]="pageTitle" type="other"></schema2jsonld>
<div class="uk-grid"> <div class="uk-width-1-1">
<div class="uk-width-expand uk-position-relative uk-margin-small-top">
</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" <helper *ngIf="pageContents && pageContents['top'] && pageContents['top'].length > 0"
[texts]="pageContents['top']"></helper> [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"> <form class="">
<div search-input [disabled]="loading" [searchControl]="filterForm.controls.keyword" searchInputClass="outer" <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>
placeholder="Search links" class="uk-width-1-3@xl uk-width-2-5@l uk-width-1-2@m uk-width-1-1" <div #searchInputComponent search-input [control]="filterForm.controls.keyword" [showSearch]="false" placeholder="Search links"
(searchEmitter)="changeKeyword()" [expandable]="true"></div> [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>
</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>
</div> </div>
<helper *ngIf="pageContents && pageContents['right'] && pageContents['right'].length > 0" <helper *ngIf="pageContents && pageContents['right'] && pageContents['right'].length > 0"
[texts]="pageContents['right']" class="uk-width-1-5"></helper> [texts]="pageContents['right']" class="uk-width-1-5"></helper>
</div> </div>
<helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0" <helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0"
[texts]="pageContents['bottom']"></helper> [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-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 {Location} from '@angular/common';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {Subject, Subscriber} from 'rxjs'; import {Subject, Subscriber} from 'rxjs';
import {debounceTime, distinctUntilChanged} from 'rxjs/operators'; import {debounceTime, distinctUntilChanged} from 'rxjs/operators';
import {ClaimsService} from '../service/claims.service'; 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 {EnvProperties} from '../../../utils/properties/env-properties';
import {LoginErrorCodes} from '../../../login/utils/guardHelper.class';
import {SEOService} from '../../../sharedComponents/SEO/SEO.service'; import {SEOService} from '../../../sharedComponents/SEO/SEO.service';
import {IndexInfoService} from '../../../utils/indexInfo.service'; import {IndexInfoService} from '../../../utils/indexInfo.service';
import {ClaimDBRecord} from '../claimHelper.class'; import {ClaimDBRecord} from '../claimHelper.class';
@ -14,19 +17,19 @@ import {HelperService} from '../../../utils/helper/helper.service';
import {Meta, Title} from '@angular/platform-browser'; import {Meta, Title} from '@angular/platform-browser';
import {PiwikService} from '../../../utils/piwik/piwik.service'; import {PiwikService} from '../../../utils/piwik/piwik.service';
import {properties} from '../../../../../environments/environment'; 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 {Option} from '../../../sharedComponents/input/input.component';
import {OpenaireEntities} from "../../../utils/properties/searchFields"; import {SearchInputComponent} from '../../../sharedComponents/search-input/search-input.component';
import {HelperFunctions} from "../../../utils/HelperFunctions.class";
import {NotificationHandler} from "../../../utils/notification-handler";
import {DropdownFilterComponent} from "../../../utils/dropdown-filter/dropdown-filter.component";
declare var UIkit;
@Component({ @Component({
selector: 'displayClaims', selector: 'displayClaims',
templateUrl: 'displayClaims.component.html', 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 = ""; @Input() pageTitle: string = "";
properties: EnvProperties; properties: EnvProperties;
public searchTermStream = new Subject<string>(); public searchTermStream = new Subject<string>();
@ -39,91 +42,93 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
@Input() isAdmin: boolean = false; @Input() isAdmin: boolean = false;
page: number = 1; page: number = 1;
size: number = 50; size: number = 50;
defaultSize:number = 50;
sizes = [10, 20, 30, 50];
keyword: string; // the keyword string to give to the request as parameter keyword: string; // the keyword string to give to the request as parameter
types = ["All", "Project", "Context", "Result", "User", "Organization"]; inputkeyword: string; // the string written in the input field (keyword=inputkeyword when its length is bigger than 3 and the user stops typing)
loading: boolean = false; @ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent;
types = ["All", "Project", "Context", "Result", "User"];
pageLoading:boolean = false;
@Input() fetchBy: string; @Input() fetchBy: string;
@Input() fetchId: string; @Input() fetchId: string;
@Input() user: User; @Input() user: User;
resultsNum: number = 0; resultsNum: number;
claims: ClaimDBRecord[]; claims: ClaimDBRecord[];
@Input() externalPortalUrl: string = null; @Input() externalPortalUrl: string = null;
@Input() claimsInfoURL: string;// ="https://www.openaire.eu/linking"; @Input() claimsInfoURL: string;// ="https://www.openaire.eu/linking";
lastIndexDate = null; lastIndexDate = null;
@ViewChild(ModalLoading) loading: ModalLoading;
public filterForm: FormGroup; public filterForm: FormGroup;
public entities: string[] = []; public entitiesCtrl: FormArray;
selected = [];
mine = false; 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"}}];
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"}];
sortOptions: Option[] = [ sortOptions: Option[] = [
{label: "Date (recent) ", value: {sort: "date", descending: true}}, {label:"Date (recent) ", value:{ sort: "date", descending: true }}, {label:"Date (oldest) ", value:{ sort: "date",descending:false }},
{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: "target", descending: true}}, // {label:"Title (desc) ", value:{ sort: "source",descending: true }}, {label:"Title (asc) ", value:{ sort: "source",descending:false }},
{label: "Title (asc) ", value: {sort: "target", descending: false}}, {label:"Title (desc) ", value:{ sort: "target",descending: true }}, {label:"Title (asc) ", value: { sort: "target",descending:false }},
]; ];
entityTypes: string[] = []; 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; params;
@ViewChild("deleteModal") deleteModal; @ViewChild(AlertModal) alert;
claimsDeleted: number = 0; claimsDeleted: number = 0;
@Input() communityId: string = null; @Input() communityId: string = null;
url = null; url = null;
public pageContents = 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, constructor(private _claimService: ClaimsService, private route: ActivatedRoute, private _router: Router, private location: Location,
private _meta: Meta, private _title: Title, private _piwikService: PiwikService, private _meta: Meta, private _title: Title, private _piwikService: PiwikService,
private seoService: SEOService, private indexInfoService: IndexInfoService, private helper: HelperService, private _fb: FormBuilder) { private seoService: SEOService, private indexInfoService: IndexInfoService, private helper: HelperService, private _fb: FormBuilder) {
} }
ngOnInit() { ngOnInit() {
if (typeof document !== "undefined" && this.actions) { this.entitiesCtrl = this._fb.array([]);
this.offset = Number.parseInt(getComputedStyle(document.documentElement).getPropertyValue('--header-height'));
}
this.entities = [];
this.filterForm = this._fb.group({ this.filterForm = this._fb.group({
keyword: [''], keyword: [''],
entities: this._fb.control(this.entities), entities: this.entitiesCtrl,
sort: this._fb.control(this.sortOptions[0].value) sort: this._fb.control(this.sortOptions[0].value)
}); });
this.properties = properties; this.properties = properties;
this.url = properties.domain + properties.baseLink + this._router.url; this.url = properties.domain + properties.baseLink + this._router.url;
if (!this.myClaims) { if(!this.myClaims){
this.sortOptions.push({label: "User (desc) ", value: {sort: "user", descending: true}}); this.sortOptions.push({label:"User (desc) ", value:{ sort: "user",descending: true }});
this.sortOptions.push({label: "User (asc) ", value: {sort: "user", descending: false}}) 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"; var description = "Openaire, linking, claim, publication, research data, software, other research product, project, community";
this.updateTitle(this.pageTitle); this.updateTitle(this.pageTitle);
this.updateDescription(description); this.updateDescription(description);
this.updateUrl(this.url); this.updateUrl(this.url);
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.subscriptions.push(this.helper.getPageHelpContents(this.properties, this.communityId, this._router.url).subscribe(contents => {
this.pageContents = contents;
}));
} }
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.subscriptions.push(this.indexInfoService.getLastIndexDate(this.properties).subscribe(res => {
this.lastIndexDate = res; this.lastIndexDate = res;
})); }));
this.subscriptions.push(this.route.queryParams.subscribe(params => { this.subscriptions.push(this.route.queryParams.subscribe(params => {
this.seoService.createLinkForCanonicalURL(this.url, false); this.seoService.createLinkForCanonicalURL(this.url, false);
if (this.myClaims) { if (this.myClaims) {
this.fetchBy = "User"; this.fetchBy = "User";
this.fetchId = this.user.email; this.fetchId = this.user.email;
@ -133,14 +138,18 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
this.fetchId = (this.fetchId) ? this.fetchId : params['fetchId']; this.fetchId = (this.fetchId) ? this.fetchId : params['fetchId'];
this.fetchId = this.fetchId ? this.fetchId : ''; this.fetchId = this.fetchId ? this.fetchId : '';
} }
let page = (params['page'] === undefined) ? 1 : +params['page']; 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.keyword = (params['keyword'] ? params['keyword'] : "");
this.filterForm.get('keyword').setValue(this.keyword); this.filterForm.get('keyword').setValue(this.keyword);
this.inputkeyword = this.keyword;
this.page = (page <= 0) ? 1 : page; this.page = (page <= 0) ? 1 : page;
this.size = (size <= 0) ? this.defaultSize : size;
this.entityTypes = [];//(params['types']?params['types']:[]); this.entityTypes = [];//(params['types']?params['types']:[]);
this.setTypes(params['types']); // check the appropriate checkboxes // this.setTypes(params['types']); // check the appropriate checkboxes
this.setSortBy(params['sort']); this.setSortby(params['sort']);
this.getClaims(); this.getClaims();
this.subscriptions.push(this.searchTermStream this.subscriptions.push(this.searchTermStream
.pipe(debounceTime(300), distinctUntilChanged()) .pipe(debounceTime(300), distinctUntilChanged())
@ -152,236 +161,185 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
this.subscriptions.push(this.filterForm.get('entities').valueChanges.subscribe(value => { this.subscriptions.push(this.filterForm.get('entities').valueChanges.subscribe(value => {
this.goTo(); 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.subscriptions.push(this.filterForm.get('sort').valueChanges.subscribe(value => {
this.goTo(); this.goTo();
})); }));
})); }));
} }
ngOnDestroy() { ngOnDestroy() {
this.subscriptions.forEach(subscription => { this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) { if (subscription instanceof Subscriber) {
subscription.unsubscribe(); subscription.unsubscribe();
} }
}); });
if (this.subResults) { if(this.subResults){
this.subResults.unsubscribe(); this.subResults.unsubscribe();
} }
} }
getClaims() { getClaims() {
let types = ''; if (!Session.isLoggedIn()) {
for (let type of this.entities) { this.userValidMessage = "User session has expired. Please login again.";
types += (types.length > 0 ? '&' : '') + "types=" + type; this._router.navigate(['/user-info'], {
} queryParams: {
this.loading = true; "errorCode": LoginErrorCodes.NOT_VALID,
if (this.subResults) { "redirectUrl": this._router.url
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);
} }
); });
} 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 { } 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( this.selected = [];
data => { let types = '';
this.manageAPIData(data); this.showErrorMessage = false;
this.loading = false; this.showForbiddenMessage = false;
}, for (let type of this.entitiesCtrl.getRawValue()) {
err => { types += (this.entitiesCtrl.getRawValue().length > 0 ? '&' : '') + "types=" + type.id;
this.handleErrors(err, "Error getting claims"); }
this.loading = false; 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) { manageAPIData(data) {
this.claims = data.data; this.claims = data.data;
this.resultsNum = +data.total; this.resultsNum = data.total;
} }
handleErrors(err, message) { 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) { goTo(page: number = 1) {
this.page = page; this.page = page;
this.location.go(location.pathname, this.getParametersString()); this.location.go(location.pathname, this.getParametersString());
HelperFunctions.scroll();
this.getClaims(); this.getClaims();
} }
getParametersString() { getParametersString() {
let params = ''; let params = '';
params += (this.page == 1 ? "" : (params.length > 0 ? '&' : '') + "page=" + this.page); params += (this.page == 1 ? "" : (params.length > 0 ? '&' : '') + "page=" + this.page);
params += (this.size == 10 ? "" : (params.length > 0 ? '&' : '') + "size=" + this.size); params += (this.size == 10 ? "" : (params.length > 0 ? '&' : '') + "size=" + this.size);
let types = ""; let types = "";
for (let type of this.entities) { for (let type of this.entitiesCtrl.getRawValue()) {
types += (types.length > 0 ? ',' : '') + type; types += (this.entitiesCtrl.getRawValue().length > 0 ? ',' : '') + type.id;
} }
params += (this.entities.length > 0) ? (params.length > 0 ? '&' : '') + "types=" + types : ""; params += (this.entitiesCtrl.getRawValue().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); 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); params += (this.keyword == '' ? "" : (params.length > 0 ? '&' : '') + "keyword=" + this.keyword);
if (this.communityId != null) {
params += "&communityId=" + this.communityId;
}
return params; return params;
} }
setSortBy(sortby: string) { setSortby(sortby: string) {
let sort = "date"; let sort = "date";
let desc = "desc"; let desc = "desc";
if (sortby && sortby.split("-").length == 2) { if(sortby && sortby.split("-").length == 2){
sort = sortby.split("-")[0]; sort = sortby.split("-")[0];
desc = sortby.split("-")[1]; desc = sortby.split("-")[1];
} }
let option = this.sortOptions.find(option => option.value.sort == sort && ((option.value.descending && desc == "desc") || (!option.value.descending && desc == "asc"))); 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); this.filterForm.get("sort").setValue(option?option.value:this.sortOptions[0].value);
} }
setTypes(typesParam: string) { changekeyword() {
for (let type of typesParam ? typesParam.split(',') : []) {
this.entities.push(type); if (this.filterForm.get("keyword").value.length >= 3 || this.filterForm.get("keyword").value.length == 0) {
}
}
changeKeyword() {
if (this.filterForm.get("keyword") && (this.filterForm.get("keyword").value?.length >= 3 || this.filterForm.get("keyword").value?.length == 0)) {
this.searchTermStream.next(this.filterForm.get("keyword").value); 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);
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; let value = event.currentTarget.checked;
if (value) { if (value) {
this.selected.push(item); this.selected.push(item);
@ -392,6 +350,8 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
this.selected.splice(_i, 1); this.selected.splice(_i, 1);
} }
} }
} }
} }
@ -408,7 +368,7 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
} }
} }
isSelectedClaim(id: string) { isSelected(id: string) {
for (let _i = 0; _i < this.selected.length; _i++) { for (let _i = 0; _i < this.selected.length; _i++) {
let claim = this.selected[_i]; let claim = this.selected[_i];
if (claim['id'] == id) { if (claim['id'] == id) {
@ -418,24 +378,159 @@ export class DisplayClaimsComponent implements OnInit, OnDestroy {
return false; 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) { private updateDescription(description: string) {
this._meta.updateTag({content: description}, "name='description'"); this._meta.updateTag({content: description}, "name='description'");
this._meta.updateTag({content: description}, "property='og:description'"); this._meta.updateTag({content: description}, "property='og:description'");
} }
private updateTitle(title: string) { private updateTitle(title: string) {
var _prefix = ""; var _prefix = "";
if (!this.communityId) { if (!this.communityId) {
_prefix = "OpenAIRE | "; _prefix = "OpenAIRE | ";
} }
var _title = _prefix + ((title.length > 50) ? title.substring(0, 50) : title); var _title = _prefix + ((title.length > 50) ? title.substring(0, 50) : title);
if (this.myClaims) { if(this.myClaims) {
this._title.setTitle(_title); this._title.setTitle(_title);
} }
this._meta.updateTag({content: _title}, "property='og:title'"); this._meta.updateTag({content: _title}, "property='og:title'");
} }
private updateUrl(url: string) { private updateUrl(url: string) {
this._meta.updateTag({content: url}, "property='og:url'"); 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 {Schema2jsonldModule} from '../../../sharedComponents/schema2jsonld/schema2jsonld.module';
import { SEOServiceModule } from '../../../sharedComponents/SEO/SEOService.module'; import { SEOServiceModule } from '../../../sharedComponents/SEO/SEOService.module';
import {IndexInfoServiceModule} from "../../../utils/indexInfoService.module"; import {IndexInfoServiceModule} from "../../../utils/indexInfoService.module";
import {PiwikServiceModule} from "../../../utils/piwik/piwikService.module";
import {SearchInputModule} from '../../../sharedComponents/search-input/search-input.module'; import {SearchInputModule} from '../../../sharedComponents/search-input/search-input.module';
import {InputModule} from '../../../sharedComponents/input/input.module'; import {InputModule} from '../../../sharedComponents/input/input.module';
import {LoadingModule} from '../../../utils/loading/loading.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({ @NgModule({
imports: [ imports: [
CommonModule, FormsModule, RouterModule, ClaimServiceModule, LoadingModalModule, AlertModalModule, CommonModule, FormsModule, RouterModule, ClaimServiceModule, LoadingModalModule, AlertModalModule,
ClaimEntityFormatterModule, PagingModule, HelperModule, Schema2jsonldModule, SEOServiceModule, ClaimEntityFormatterModule, PagingModule, HelperModule, Schema2jsonldModule, SEOServiceModule, PiwikServiceModule,
IndexInfoServiceModule, MatSelectModule, SearchInputModule, MatAutocompleteModule, MatChipsModule, MatFormFieldModule, MatSlideToggleModule, InputModule, LoadingModule, NoLoadPaging, IconsModule, DropdownFilterModule IndexInfoServiceModule, MatSelectModule, SearchInputModule, MatAutocompleteModule, MatChipsModule, MatFormFieldModule, MatSlideToggleModule, InputModule, LoadingModule
], ],
declarations: [ declarations: [
DisplayClaimsComponent DisplayClaimsComponent
@ -41,8 +37,4 @@ import {link} from "../../../utils/icons/icons";
DisplayClaimsComponent DisplayClaimsComponent
] ]
}) })
export class DisplayClaimsModule { export class DisplayClaimsModule { }
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([link])
}
}

View File

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

View File

@ -5,19 +5,18 @@ import { RouterModule } from '@angular/router';
import {ProjectTitleFormatter} from './projectTitleFormatter.component'; import {ProjectTitleFormatter} from './projectTitleFormatter.component';
import {PublicationTitleFormatter} from './publicationTitleFormatter.component'; import {PublicationTitleFormatter} from './publicationTitleFormatter.component';
import {ClaimEntityFormatter} from './claimEntityFormatter.component'; import {ClaimEntityFormatter} from './claimEntityFormatter.component';
import {OrganizationTitleFormatterComponent} from "./organizationTitleFormatter.component";
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, RouterModule CommonModule, RouterModule
], ],
declarations: [ declarations: [
ProjectTitleFormatter, PublicationTitleFormatter, ClaimEntityFormatter, OrganizationTitleFormatterComponent ProjectTitleFormatter, PublicationTitleFormatter, ClaimEntityFormatter
], ],
providers: [ ], providers: [ ],
exports: [ 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,26 +7,24 @@ import {properties} from "../../../../../environments/environment";
@Component({ @Component({
selector: 'project-title', selector: 'project-title',
template: ` template: `
<ng-container> <span *ngIf="externalPortalUrl" class="project-title uk-text-large">
<h6 class="uk-margin-remove multi-line-ellipsis lines-2"> <span><a
<p class="uk-margin-remove"> [href]="externalPortalUrl + projectUrl + '?projectId='+project['openaireId']">{{(project['acronym'] ? ('[' + project['acronym'] + '] ') : '')}}{{project['name']}}</a></span>
<a *ngIf="externalPortalUrl" [href]="externalPortalUrl + projectUrl + '?projectId='+project['openaireId']" class="uk-link uk-link-heading" [class.uk-disabled]="project.name == 'unidentified'"> </span>
{{(project['acronym'] ? ('[' + project['acronym'] + '] ') : '')}}{{project['name']}} <span *ngIf="!externalPortalUrl" class="project-title uk-text-large">
</a> <span><a [queryParams]="routerHelper.createQueryParam('projectId',project['openaireId'])"
<a *ngIf="!externalPortalUrl" [routerLink]="projectUrl" [queryParams]="routerHelper.createQueryParam('projectId',project['openaireId'])" class="uk-link uk-link-heading" [class.uk-disabled]="project.name == 'unidentified'"> routerLinkActive="router-link-active"
{{(project['acronym'] ? ('[' + project['acronym'] + '] ') : '')}}{{project['name']}} [routerLink]="projectUrl">{{(project['acronym'] ? ('[' + project['acronym'] + '] ') : '')}}{{project['name']}} </a></span>
</a> </span>
</p>
</h6> <span *ngIf="project['funderName']">
</ng-container> <span class="uk-text-muted title"> Funder: </span>{{project['funderName']}}
<span *ngIf="project['funderName']" class="uk-margin-small-top">
<span class="uk-text-meta">Funder: </span>{{project['funderName']}}
</span> </span>
` `
}) })
export class ProjectTitleFormatter { export class ProjectTitleFormatter {
@Input() project: any; @Input() project: string[];
@Input() searchLink: string; @Input() searchLink: string;
@Input() externalPortalUrl: string = null; @Input() externalPortalUrl: string = null;
public url: string; public url: string;

View File

@ -6,23 +6,41 @@ import {RouterHelper} from '../../../utils/routerHelper.class';
@Component({ @Component({
selector: 'publication-title', selector: 'publication-title',
template: ` template: `
<ng-container *ngIf="entity.openaireId"> <span *ngIf="!externalPortalUrl" class="publication-title uk-text-large">
<h6 class="uk-margin-remove multi-line-ellipsis lines-2">
<p class="uk-margin-remove"> <span *ngIf="entity.openaireId"><a [queryParams]="routerHelper.createQueryParam(param,entity.openaireId)" routerLinkActive="router-link-active"
<a *ngIf="!externalPortalUrl" [queryParams]="routerHelper.createQueryParam(param,entity.openaireId)" [routerLink]="path"> {{entity.title?entity.title:"[No title available]"}}</a></span>
[routerLink]="path" class="uk-link uk-link-heading" [class.uk-disabled]="!linkAvailable">{{entity.title?entity.title:"[No title available]"}}</a> <!--span *ngIf="url" class="uk-margin-small-left" ><a target="_blank" href="{{url}}" >
<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> (<span class="custom-external custom-icon" ></span>link)</a></span-->
</p> </span>
</h6> <span *ngIf="externalPortalUrl" class="publication-title uk-text-large">
</ng-container>
<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 { export class PublicationTitleFormatter {
// @Input() title: string;
// @Input() url: string;
// @Input() id: string;
@Input() param: string; @Input() param: string;
@Input() path: string; @Input() path: string;
@Input() entity: any; @Input() entity: any;
@Input() externalPortalUrl: string = null; @Input() externalPortalUrl: string = null;
@Input() linkAvailable: boolean = true;
public routerHelper: RouterHelper = new RouterHelper(); 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 { 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 { 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.length>0?"&"+types:types) + (mine?"&mine=true":"") + (mine?"&mine=true":""); let url = apiUrl +"claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+"&"+types;
return this.getClaimRequest(size,page,url,true); 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 { 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); //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); 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); //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); 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 { 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); //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); 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 { 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); //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); 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{ deleteClaimById(claimId:string , apiUrl:string):any{
//console.warn('Trying to delete claim with id : '+claimId); //console.warn('Trying to delete claim with id : '+claimId);
let url = apiUrl +"claims/"+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()) return this.http.delete( url, CustomOptions.getAuthOptionsWithBody())//.map(request => <any> request.json())
// .do(request => console.info("After delete" ))
.pipe(catchError(this.handleError)); .pipe(catchError(this.handleError));
} }
@ -62,7 +61,10 @@ export class ClaimsService {
} }
url= apiUrl +"claims/bulk?"+url; 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)); .pipe(catchError(this.handleError));
} }
@ -70,27 +72,40 @@ export class ClaimsService {
// console.warn('Trying toinsert claims : '+claims); // console.warn('Trying toinsert claims : '+claims);
let url = apiUrl +"claims/bulk"; let url = apiUrl +"claims/bulk";
let body = JSON.stringify( claims ); 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()) return this.http.post(url, body, CustomOptions.getAuthOptionsWithBody())
//.map(res => res.json())
//.do(request => console.info("Insert Response:"+request.status) )
.pipe(catchError(this.handleError)); .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{ insertDirectRecords(records, apiUrl:string):any{
//console.warn('Trying to feedrecords : '+records); //console.warn('Trying to feedrecords : '+records);
let url = apiUrl +"feed/bulk"; let url = apiUrl +"feed/bulk";
let body = JSON.stringify( records ); 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()) return this.http.post(url, body, CustomOptions.getAuthOptionsWithBody())
//.map(res => res.json())
//.do(request => console.info("Insert Response:"+request) )
.pipe(catchError(this.handleError)); .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) { private handleError (error: Response) {
// in a real world app, we may send the error to some remote logging infrastructure // in a real world app, we may send the error to some remote logging infrastructure
// instead of just logging it to the console // instead of just logging it to the console
@ -98,4 +113,22 @@ export class ClaimsService {
return observableThrowError(error || 'Server error'); 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' }) @Injectable({ providedIn: 'root' })
export class ContextsService { export class ContextsService {
private communitiesSubject: BehaviorSubject<any> = new BehaviorSubject(null); private communitiesSubject: BehaviorSubject<any> = new BehaviorSubject(null);
private promise: Promise<void>; private promise: Promise<any>;
private sub: Subscription = null; private sub: Subscription = null;
constructor(private http: HttpClient=null ) { constructor(private http: HttpClient=null ) {
@ -34,7 +34,7 @@ export class ContextsService {
public initCommunities() { public initCommunities() {
let url = properties.contextsAPI + 's/'; 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) this.sub = this.http.get((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => this.parseCommunities(res, true) )) .pipe(map(res => this.parseCommunities(res, true) ))
.subscribe( .subscribe(

View File

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

View File

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

View File

@ -21,38 +21,14 @@ export class SearchOrcidService {
let url = properties.searchOrcidURL + term + '/record'; let url = properties.searchOrcidURL + term + '/record';
return this.http.get(url, { headers: headers }) return this.http.get(url, { headers: headers })
//.map(res => res.json()['person']) //.map(res => res.json()['person'])
.pipe(map(res => res['person'])) .pipe(map(res => res['person']))
.pipe(map(res => [res['name']['given-names'], .pipe(map(res => [res['name']['given-names'],
res['name']['family-name'], res['name']['family-name'],
res['name'], res['name']['institution-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, searchOrcidAuthors(term: string,
properties: EnvProperties): any { 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 { searchOrcidPublications(id: string, properties: EnvProperties, parse: boolean = false): any {
let headers = new HttpHeaders({'Accept': 'application/orcid+json'}); let headers = new HttpHeaders({'Accept': 'application/orcid+json'});
let url = properties.searchOrcidURL + id + '/works'; let url = properties.searchOrcidURL + id + '/works';
return this.http.get(url, { headers: headers }) return this.http.get(url, { headers: headers })
.pipe(map(res => res['group'])) .pipe(map(res => res['group']))
.pipe(map(request => (parse ? SearchOrcidService.parse(id, request) : request))); .pipe(map(request => (parse ? SearchOrcidService.parse(id, request) : request)));
} }
static parseOrcidAuthor(data: any, authorIds: string[], authors, addId): any { static parseOrcidAuthor(data: any, authorIds: string[], authors, addId): any {
@ -124,9 +72,6 @@ export class SearchOrcidService {
} else { } else {
author['authorFamilyName'] = ""; author['authorFamilyName'] = "";
} }
if (data[3] != null) {
author['institution'] = data[3];
}
authors.push(author); authors.push(author);
return true; return true;
} }

View File

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

View File

@ -10,17 +10,18 @@ import {Subscriber} from "rxjs";
@Component({ @Component({
selector: 'claims-admin', selector: 'claims-admin',
template: ` 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 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"> <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 Manage links
</h1> </div>
<div> <div>
<displayClaims *ngIf="user" [user]="user" [enableDelete]=true [myClaims]=false <displayClaims *ngIf="user" [user]="user" [enableDelete]=true [myClaims]=false
[isAdmin]=true [fetchBy]="(fetchId=='openaire')?null:fetchBy" [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" [communityId]="(fetchBy && fetchBy == 'Context' && fetchId && fetchId!='openaire')?fetchId:null"
[externalPortalUrl]=externalPortalUrl [claimsInfoURL]=claimsInfoURL [externalPortalUrl]=externalPortalUrl [claimsInfoURL]=claimsInfoURL
pageTitle="Manage links"></displayClaims> pageTitle="Manage links"></displayClaims>
@ -29,7 +30,9 @@ import {Subscriber} from "rxjs";
</div> </div>
</div> </div>
</div> </div>
`, `,
}) })
export class ClaimsAdminComponent { export class ClaimsAdminComponent {
@Input() fetchBy: string; @Input() fetchBy: string;
@ -37,6 +40,7 @@ export class ClaimsAdminComponent {
@Input() isConnect: boolean = false; @Input() isConnect: boolean = false;
@Input() externalPortalUrl: string; @Input() externalPortalUrl: string;
@Input() claimsInfoURL: string; @Input() claimsInfoURL: string;
@Input() userInfoURL: string;
public user: User = null; public user: User = null;
sub; sub;

View File

@ -1,8 +1,11 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { SharedModule } from '../../../openaireLibrary/shared/shared.module'; import { SharedModule } from '../../shared/shared.module';
import { ClaimsAdminComponent } from './claimsAdmin.component'; import { ClaimsAdminComponent } from './claimsAdmin.component';
import {DisplayClaimsModule} from '../claim-utils/displayClaims/displayClaims.module'; 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({ @NgModule({
imports: [ imports: [
@ -10,7 +13,7 @@ import {DisplayClaimsModule} from '../claim-utils/displayClaims/displayClaims.mo
DisplayClaimsModule DisplayClaimsModule
], ],
providers:[], providers:[AdminLoginGuard, PreviousRouteRecorder,IsRouteEnabled],
declarations: [ declarations: [
ClaimsAdminComponent ClaimsAdminComponent
], ],

View File

@ -18,12 +18,26 @@ export class ClaimsByTokenService {
let key = url; 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) { updateClaimsCuration( selectedRight: Set<string>, selectedWrong: Set<string>, apiURL:string) {
let url = apiURL + "curate/bulk"; 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" <linking-generic *ngIf="validInput" [localStoragePrefix]="localStoragePrefix" [results]="results" [sources]="sources"
[communityId]="communityId" [inlineEntity]="inlineEntity" [showOptions]="showOptions" [communityId]="communityId" [inlineEntity]="inlineEntity" [showOptions]="showOptions"
pageTitle="Direct Linking" [claimsProperties]="claimsProperties"> [piwikSiteId]="piwikSiteId" pageTitle="Direct Linking">
</linking-generic> </linking-generic>
<div *ngIf="validInput== false" id="tm-main" class=" uk-section uk-padding-remove-top tm-middle"> <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 {Component, Input, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {EnvProperties} from '../../utils/properties/env-properties'; 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 {EntitiesSearchService} from '../../utils/entitiesAutoComplete/entitySearch.service';
import {SearchResearchResultsService} from '../../services/searchResearchResults.service'; import {SearchResearchResultsService} from '../../services/searchResearchResults.service';
import {LinkingGenericComponent} from "../linking/linkingGeneric.component"; import {LinkingGenericComponent} from "../linking/linkingGeneric.component";
import {ClaimResultSearchFormComponent} from "../claim-utils/claimResultSearchForm.component"; import {ClaimResultSearchFormComponent} from "../claim-utils/claimResultSearchForm.component";
import {Subscriber} from "rxjs"; import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment"; 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({ @Component({
@ -19,26 +15,26 @@ import {ClaimsProperties} from "../claim-utils/claims.properties";
templateUrl: 'directLinking.component.html' templateUrl: 'directLinking.component.html'
}) })
export class DirectLinkingComponent { export class DirectLinkingComponent {
@Input() piwikSiteId = null;
@ViewChild(LinkingGenericComponent) linking: LinkingGenericComponent; @ViewChild(LinkingGenericComponent) linking: LinkingGenericComponent;
results: ClaimEntity[] = []; results: ClaimEntity[] = [];
// linkType: string = "project"; // link type (selected in home page) : project, context, software, etc // linkType: string = "project"; // link type (selected in home page) : project, context, software, etc
/* url Parameters for inline linking */ /* url Parameters for inline linking */
@Input() id: string = null; //entity id id: string = null; //entity id
type: string = null; // entity type (publication or dataset) type: string = null; // entity type (publication or dataset)
// linkTo: string = null; // entity type (project or context or entity) // linkTo: string = null; // entity type (project or context or entity)
// linkToEntities: string[] = []; // linkToEntities: string[] = [];
showOptions:ShowOptions = new ShowOptions(); showOptions:ShowOptions = new ShowOptions();
validEntityTypes = ["dataset", "publication", "software", "other", "project", "context", "organization"]; validEntityTypes = ["dataset", "publication", "software", "orp", "project", "context"];
sources: ClaimEntity[] = []; sources: ClaimEntity[] = [];
inlineEntity: ClaimEntity = null; inlineEntity: ClaimEntity = null;
validInput: boolean = null;//'true; validInput: boolean = null;//'true;
properties: EnvProperties; properties: EnvProperties;
@Input() communityId: string = null; @Input() communityId: string = null;
localStoragePrefix: string = ""; localStoragePrefix: string = "";
@Input() organizationClaim: boolean = false;
@Input() claimsProperties:ClaimsProperties = new ClaimsProperties();
constructor(private _router: Router, private route: ActivatedRoute,private entitySearch:EntitiesSearchService, constructor(private _router: Router, private route: ActivatedRoute,private entitySearch:EntitiesSearchService,
private _searchResearchResultsService: SearchResearchResultsService) {} private _searchResearchResultsService: SearchResearchResultsService) {}
subscriptions = []; subscriptions = [];
@ -51,21 +47,20 @@ export class DirectLinkingComponent {
} }
ngOnInit() { ngOnInit() {
this.properties = properties; this.properties = properties;
/* if(!this.claimsProperties){
this.claimsProperties = new ClaimsProperties();
}*/
this.subscriptions.push(this.route.queryParams.subscribe(params => { this.subscriptions.push(this.route.queryParams.subscribe(params => {
if(this.organizationClaim){ this.id = params['id'];
this.type = "organization"; this.type = params['type'];
this.showOptions.linkTo = "result"; this.showOptions.linkTo = params['linkTo'];
}else {
this.id = params['id'];
this.type = params['type'];
this.showOptions.linkTo = params['linkTo'];
}
if (this.type != null && this.showOptions.linkTo != null) { if (this.type != null && this.showOptions.linkTo != null) {
this.type = (this.validEntityTypes.indexOf(this.type) != -1) ? this.type : 'publication'; 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.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) + "_"; this.localStoragePrefix = (this.communityId ? (this.communityId + "_") : '') + this.type.substr(0, 3) + "_" + this.showOptions.linkTo.substr(0, 3) + "_";
if (localStorage.getItem(this.localStoragePrefix + "results")) { if (localStorage.getItem(this.localStoragePrefix + "results")) {
@ -78,22 +73,20 @@ export class DirectLinkingComponent {
if (this.type == "project") { if (this.type == "project") {
// this.linkType = "project"; // this.linkType = "project";
this.getProjectById(this.id); this.getProjectById(this.id);
} else if (this.type == "organization") {
this.getOrganizationById(this.id);
} else if (this.type == "publication") { } else if (this.type == "publication") {
this.getResearchResultById("publication", this.id); this.getResearchResultById("publication", this.id);
} else if (this.type == "dataset") { } else if (this.type == "dataset") {
this.getResearchResultById("dataset", this.id); this.getResearchResultById("dataset", this.id);
} else if (this.type == "software") { } else if (this.type == "software") {
this.getResearchResultById("software", this.id); this.getResearchResultById("software", this.id);
} else if (this.type == "other") { } else if (this.type == "orp") {
this.getResearchResultById("other", this.id); this.getResearchResultById("other", this.id);
} else { } else {
this.validInput = this.isValidInput(null); this.validInput = this.isValidInput(null);
} }
//set which entities it is allowed to link to. //set which entities it is allowed to link to.
// add first the // add first the
if(this.type == "project" || this.type == "organization"){ if(this.type == "project"){
this.showOptions.linkToEntities = ["result"]; this.showOptions.linkToEntities = ["result"];
this.showOptions.linkTo = "result"; this.showOptions.linkTo = "result";
}else{ }else{
@ -107,27 +100,24 @@ export class DirectLinkingComponent {
this.showOptions.linkToEntities = ["result","project","context" ]; this.showOptions.linkToEntities = ["result","project","context" ];
} }
}
} else {
this.validInput = this.isValidInput(null);
} }
})); } else {
this.validInput = this.isValidInput(null);
}
}));
} }
isValidInput(result: ClaimEntity) { isValidInput(result: ClaimEntity) {
if (result == null) { if (result == null) {
return false; return false;
} else if (this.type == "organization" && !this.claimsProperties.ALLOW_ORGANIZATION_LINKING) { } else if (this.type == "project" && this.showOptions.linkTo != "result") {
return false; 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; return false;
} else if (["dataset", "publication", "software", "other"].indexOf(this.type) != -1 && (["project", "context", "result"].indexOf(this.showOptions.linkTo) == -1)) { } else if (["project", "dataset", "publication", "software", "orp"].indexOf(this.type) == -1) {
return false;
} else if (["project", "dataset", "publication", "software", "other", "organization"].indexOf(this.type) == -1) {
return false; return false;
} else { } else {
return true; return true;
@ -145,17 +135,6 @@ export class DirectLinkingComponent {
this.handleError("Error getting project by id: " + id, err); 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) { getResearchResultById(resultType: string, id: string) {
this.subscriptions.push(this._searchResearchResultsService.searchById(resultType, id, this.properties).subscribe(data => { this.subscriptions.push(this._searchResearchResultsService.searchById(resultType, id, this.properties).subscribe(data => {
@ -164,7 +143,7 @@ export class DirectLinkingComponent {
err => { err => {
this.validInput = this.isValidInput(null); this.validInput = this.isValidInput(null);
//console.log("An error occured") //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);
})); }));
} }
@ -177,28 +156,16 @@ export class DirectLinkingComponent {
entity.type = "project"; entity.type = "project";
entity.title = project.projectName; entity.title = project.projectName;
entity.project = new ClaimProject(); entity.project = new ClaimProject();
entity.project.url = properties.searchLinkToProject + entity.id;
entity.project.acronym = project.projectAcronym; entity.project.acronym = project.projectAcronym;
entity.project.code = project.code; entity.project.code = project.code;
entity.project.endDate = project.endDate; entity.project.endDate = project.endDate;
entity.project.funderId = project.funderId; entity.project.funderId = project.funderId;
entity.project.funderShortname = project.funderShortName?project.funderShortName:(entity.project.funderId.split("::")[1]);
entity.project.funderName = project.funderName; entity.project.funderName = project.funderName;
entity.project.fundingLevel0 = project.fundingLevel0; entity.project.fundingLevel0 = project.fundingLevel0;
entity.project.jurisdiction = project.jurisdiction; entity.project.jurisdiction = project.jurisdiction;
entity.project.startDate = project.startDate; entity.project.startDate = project.startDate;
this.inlineEntity = entity; this.inlineEntity = entity;
}else if(type =="organization"){ }else{
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{
results = ClaimResultSearchFormComponent.openaire2ClaimResults(data, this.properties); results = ClaimResultSearchFormComponent.openaire2ClaimResults(data, this.properties);
} }
@ -212,7 +179,15 @@ export class DirectLinkingComponent {
console.error("Direct Linking Page: " + message, error); console.error("Direct Linking Page: " + message, error);
} }
private getEntityName (entityType:string, plural:boolean) { private getEntityName (entityType:string, plural:boolean, full:boolean): string {
return StringUtils.getEntityName(entityType, plural); 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 { NgModule } from '@angular/core';
import { SharedModule } from '../../../openaireLibrary/shared/shared.module'; import { SharedModule } from '../../shared/shared.module';
import { DirectLinkingComponent } from './directLinking.component'; import { DirectLinkingComponent } from './directLinking.component';
import {EntitySearchServiceModule} from '../../utils/entitiesAutoComplete/entitySearchService.module'; import {EntitySearchServiceModule} from '../../utils/entitiesAutoComplete/entitySearchService.module';
import {SearchResearchResultsServiceModule} from '../../services/searchResearchResultsService.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 {Schema2jsonldModule} from '../../sharedComponents/schema2jsonld/schema2jsonld.module';
import { SEOServiceModule } from '../../sharedComponents/SEO/SEOService.module'; import { SEOServiceModule } from '../../sharedComponents/SEO/SEOService.module';
import {LinkingGenericModule} from '../linking/linkingGeneric.module'; import {LinkingGenericModule} from '../linking/linkingGeneric.module';
import {LoadingModule} from "../../utils/loading/loading.module";
@NgModule({ @NgModule({
imports: [ imports: [
SharedModule, SharedModule,
EntitySearchServiceModule, SearchResearchResultsServiceModule, EntitySearchServiceModule, SearchResearchResultsServiceModule,
Schema2jsonldModule, SEOServiceModule, LinkingGenericModule, LoadingModule Schema2jsonldModule, SEOServiceModule, LinkingGenericModule
], ],
providers:[], providers:[LoginGuard, PreviousRouteRecorder, IsRouteEnabled],
declarations: [ declarations: [
DirectLinkingComponent DirectLinkingComponent
], exports:[DirectLinkingComponent] ], exports:[DirectLinkingComponent]

View File

@ -21,17 +21,15 @@ declare var UIkit: any;
<div> <div>
<!--div class="uk-text-lead">Upload a DOI csv file <helper div="link-result-bulk" tooltip=true ></helper></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--> <label for="exampleInputFile">Select a file: </label-->
<div class="uk-float-left"> <div class="js-upload" uk-form-custom>
<span class="js-upload" uk-form-custom> <input id="exampleInputFile" class="uk-width-medium" type="file" (change)="fileChangeEvent($event)"/>
<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 class="uk-link " style="text-decoration: underline;">Upload a DOI's CSV file </span>
</span>
<!--button class="uk-button portal-button" type="button" tabindex="-1" [class.disabled]="!enableUpload" ><span class="uk-margin-small-right uk-icon" > <!--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> <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--> <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--> <!--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> </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"> <div *ngIf="showReport" uk-alert class="uk-alert-primary">
<a class="uk-alert-close" uk-close></a> <a class="uk-alert-close" uk-close></a>
<div>Uploaded file contains <span <div>Uploaded file contains <span
@ -109,16 +107,17 @@ export class BulkClaimComponent {
exceedsLimit = false; exceedsLimit = false;
@Input() basketLimit ; @Input() basketLimit ;
tooltip = ` tooltip = `
<div> <div class="uk-padding-small uk-padding-remove-right uk-padding-remove-left">
<div class="uk-margin-bottom">Up to 100 DOIs</div> <div >
<div><span class="uk-text-bold">CSV format:</span> <br>&quot;DOI&quot;,&quot;ACCESS_MODE&quot;,&quot;DATE&quot;</div> <div><span class="uk-text-bold">CSV format:</span> <br>&quot;DOI&quot;,&quot;ACCESS_MODE&quot;,&quot;DATE&quot;</div>
<br> <br>
<div class="uk-text-small"> <div class=" uk-text-small">
<div>- DOI is required</div> <div>- DOI is required</div>
<div>- Access mode: <br> OPEN, CLOSED, EMBARGO</div> <div>- Access mode: <br> OPEN, CLOSED, EMBARGO</div>
<div>- Embargo end date:<br> YYYY-MM-DD </div> <div>- Embargo end date:<br> YYYY-MM-DD </div>
</div> </div>
</div>`; </div>
</div>`;
constructor(private _searchCrossrefService: SearchCrossrefService, private _searchDataciteService: SearchDataciteService) { constructor(private _searchCrossrefService: SearchCrossrefService, private _searchDataciteService: SearchDataciteService) {
this.filesToUpload = []; this.filesToUpload = [];
} }
@ -133,11 +132,11 @@ export class BulkClaimComponent {
} }
}); });
} }
upload() { upload() {
this.enableUpload = false; this.enableUpload = false;
this.showReport = false; this.showReport = false;
this.errorMessage = ""; this.errorMessage = "";
console.log(this.filesToUpload);
if (this.filesToUpload.length == 0) { if (this.filesToUpload.length == 0) {
this.errorMessage = "There is no selected file to upload."; this.errorMessage = "There is no selected file to upload.";
return; return;
@ -227,7 +226,7 @@ export class BulkClaimComponent {
} }
makeFileRequest(url: string, params: Array<string>, files: Array<File>) { 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 formData: any = new FormData();
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
for (let i = 0; i < files.length; i++) { for (let i = 0; i < files.length; i++) {
@ -248,12 +247,11 @@ export class BulkClaimComponent {
} }
fetchResult(id: string, accessMode: string, date: string, row: number) { 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.searchCrossrefByDOIs([id], this.properties, true).subscribe(
this.subscriptions.push(this._searchCrossrefService.searchCrossrefByDOI(id).subscribe(
data => { data => {
if (data.length > 0) { const result:ClaimEntity = data[1][0];
const result:ClaimEntity = data[0]; if (data[1].length > 0) {
this.foundIds.push(id); this.foundIds.push(id);
result.result.accessRights = accessMode; result.result.accessRights = accessMode;
result.result.embargoEndDate = date; result.result.embargoEndDate = date;
@ -269,16 +267,11 @@ export class BulkClaimComponent {
} }
}, },
err => { err => {
// console.log(err); //console.log(err);
BulkClaimComponent.handleError("Error getting crossref by DOIs: " + id, err); BulkClaimComponent.handleError("Error getting crossref by DOIs: " + id, err);
this.notFoundIds.push(id);
if(err.status == 404) { this.notFoundIdsRow.push(row);
this.searchInDatacite(id, accessMode, date, row); this.endOfFetching();
} else {
this.notFoundIds.push(id);
this.notFoundIdsRow.push(row);
this.endOfFetching();
}
} }
)); ));
} }

View File

@ -1,6 +1,6 @@
import { NgModule } from '@angular/core'; 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 {LoadingModalModule} from '../../../utils/modal/loadingModal.module';
import {BulkClaimComponent} from './bulkClaim.component'; import {BulkClaimComponent} from './bulkClaim.component';
import {SearchCrossrefServiceModule} from '../../claim-utils/service/searchCrossrefService.module'; import {SearchCrossrefServiceModule} from '../../claim-utils/service/searchCrossrefService.module';

View File

@ -14,53 +14,46 @@ import {
Message Message
} from "../../claim-utils/claimHelper.class"; } from "../../claim-utils/claimHelper.class";
import {UserManagementService} from "../../../services/user-management.service"; import {UserManagementService} from "../../../services/user-management.service";
import {Subscriber, timer} from "rxjs"; import {Subscriber} from "rxjs";
import {map} from "rxjs/operators";
import {LogService} from "../../../utils/log/log.service";
@Component({ @Component({
selector: 'claim-insert', selector: 'claim-insert',
template: ` 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))" <div class="uk-width-1-1">
[class.uk-disabled]="!(results.length > 0 && (sources.length > 0 || inlineEntity))"> <modal-loading [message]="'Please wait...'"></modal-loading>
<button class="uk-flex uk-flex-middle uk-button uk-button-text" <modal-alert (alertOutput)="confirmClose()">
[class.uk-disabled]="!(results.length > 0 && (sources.length > 0 || inlineEntity))" <h4 class="modal-title uk-text-bold " id="myModalLabel">Confirmation notice</h4>
[disabled]="!(results.length > 0 && (sources.length > 0 || inlineEntity))"> <p>All the links you provided will be published in the OpenAIRE platform. <br>
<icon name="link" visuallyHidden="link" [flex]="true"></icon> Please make sure that the information is valid.<br>
<div class="uk-width-expand uk-margin-small-left">CONFIRM LINKING</div> <span class="uk-text-bold">In some cases, links take some time to be published.</span><br>
</button> For more information please check the linking status in My-Links page.
</div> </p>
<modal-loading [message]="'Please wait...'"> <p>
Do you confirm the information you provide is valid?
<div *ngIf="claimsJob"> </p>
<div *ngIf="claimsJob && claimsJob.insertedIds.length <1" class="uk-text-meta uk-text-small"> </modal-alert>
Initiating process....</div> <div class="uk-clearfix">
<div *ngIf="claimsJob && claimsJob.insertedIds.length >0" class="uk-text-meta uk-text-small">
{{claimsJob.insertedIds.length}} out of {{claims2Insert}} links created.</div> <div>
<div *ngIf="feedRecordsJob && feedRecordsJob.insertedIds.length >0" class="uk-text-meta uk-text-small"> <div *ngIf="!claiming " (click)="insert()" style="width: 350px;"
{{feedRecordsJob.insertedIds.length}} out of {{records2Insert}} records added in the index...</div> [class]="getButtonClass()">CONFIRM LINKING
<div *ngIf="claimsJob.status != 'COMPLETE'" class="uk-text-meta uk-text-small"> <span [class]="(defaultColors?'':' uk-margin-small-top ')+'uk-icon uk-float-right uk-text-bold uk-margin-small-right'">
Please don't close the window, process is ongoing...</div> <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>
</modal-loading> </div>
<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>
` `
}) })
export class ClaimInsertComponent { export class ClaimInsertComponent {
constructor(private claimService: ClaimsService, private _router: Router, private route: ActivatedRoute, constructor(private claimService: ClaimsService, private _router: Router, private route: ActivatedRoute,
private userManagementService: UserManagementService, private _logService: LogService) { private userManagementService: UserManagementService) {
} }
subscriptions = []; subscriptions = [];
ngOnDestroy() { ngOnDestroy() {
@ -74,32 +67,6 @@ export class ClaimInsertComponent {
this.subscriptions.push(this.route.queryParams.subscribe(params => { this.subscriptions.push(this.route.queryParams.subscribe(params => {
this.params = 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);
let timerSubscription = timer(0, 10000).pipe(
map(() => {
this.getStatus(); // load data contains the http request
})
).subscribe();
this.subscriptions.push(timerSubscription);
}else{
this.claimsJob = null;
}
}
} }
params = {}; params = {};
@ -124,16 +91,15 @@ export class ClaimInsertComponent {
private errorInClaims: ClaimRecord2Insert[] = []; private errorInClaims: ClaimRecord2Insert[] = [];
private insertedRecords = []; private insertedRecords = [];
private errorInRecords = []; private errorInRecords = [];
public claimsJob;
public feedRecordsJob;
public claims2Insert;
public records2Insert
infoToLog = [];
public insert() { public insert() {
this.confirmOpen(); this.confirmOpen();
} }
saveAndNavigate(){ 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'], { this._router.navigate(['/user-info'], {
queryParams: { queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID, "errorCode": LoginErrorCodes.NOT_VALID,
@ -147,7 +113,6 @@ export class ClaimInsertComponent {
this.errorInClaims = []; this.errorInClaims = [];
this.insertedRecords = []; this.insertedRecords = [];
this.errorInRecords = []; this.errorInRecords = [];
this.infoToLog = [];
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => { this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
if (!user) { if (!user) {
this.saveAndNavigate(); this.saveAndNavigate();
@ -156,14 +121,13 @@ export class ClaimInsertComponent {
this.loading.open(); this.loading.open();
let claims: ClaimRecord2Insert[] = []; let claims: ClaimRecord2Insert[] = [];
let directclaims: DirectIndexRecord[] = []; let directclaims: DirectIndexRecord[] = [];
let idSuffix = (new Date()).getTime() + "";
let dashboard = this.properties.environment+"_"+this.properties.dashboard + (this.communityId?("_"+this.communityId):''); 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 for (let j = 0; j < this.sources.length; j++) { // if an external result -> direct insert in the index
const result: ClaimEntity = this.sources[j]; const result: ClaimEntity = this.sources[j];
if (result.result && ["crossref", "datacite", "orcid"].indexOf(result.result.source) != -1) { if (result.result && ["crossref", "datacite", "orcid"].indexOf(result.result.source) != -1) {
directclaims.push({ directclaims.push({
"id": result.id, "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) { if (this.sources.length > 0) {
directclaims.push({ directclaims.push({
"id": entity.id, "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({ directclaims.push({
"id": entity.id, "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++) { for (let j = 0; j < this.sources.length; j++) {
const result: ClaimEntity = this.sources[j]; // this is a research result const result: ClaimEntity = this.sources[j]; // this is a research result
if (entity.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) { } 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) { } else if (entity.project) {
claims.push(ClaimInsertComponent.createProjectClaim(result, entity, user.email, dashboard, idSuffix)); claims.push(ClaimInsertComponent.createProjectClaim(result, entity, user.email, dashboard));
/* } else if (entity.organization) {
claims.push(ClaimInsertComponent.createOrganizationClaim(result, entity, user.email, dashboard, idSuffix));*/
} }
this.infoToLog.push([ result.title?result.title: result.id, entity.title?entity.title:entity.id]);
} }
if (this.inlineEntity) { 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 (this.inlineEntity.result) {
if (entity.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) { } 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) { } 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) { } else if (this.inlineEntity.project) {
if (entity.result) { if (entity.result) {
claims.push(ClaimInsertComponent.createProjectClaim(entity, this.inlineEntity, user.email, dashboard, idSuffix)); claims.push(ClaimInsertComponent.createProjectClaim(entity, this.inlineEntity, user.email, dashboard));
}
} else if (this.inlineEntity.organization) {
if (entity.result) {
claims.push(ClaimInsertComponent.createOrganizationClaim(entity, this.inlineEntity, user.email, dashboard, idSuffix));
} }
} }
} }
@ -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 //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");
// 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( this.subscriptions.push(this.claimService.insertDirectRecords(directclaims, this.properties.claimsAPIURL).subscribe(
data => { data => {
this.feedRecordsJob = data.data; this.insertedRecords = data.insertedIds;
this.records2Insert = directclaims.length;
// console.log(data); this.errorInRecords = data.errorInClaims;
// this.insertedRecords = data.insertedIds;
//
// this.errorInRecords = data.errorInClaims;
this.isertBulkClaims(claims); this.isertBulkClaims(claims);
}, },
err => { err => {
@ -243,12 +197,12 @@ export class ClaimInsertComponent {
if (err.code && err.code == 403) { if (err.code && err.code == 403) {
this.saveAndNavigate(); this.saveAndNavigate();
} }
/* if (err.insertedIds && err.insertedIds.length > 0) { if (err.insertedIds && err.insertedIds.length > 0) {
this.insertedRecords = err.insertedIds; this.insertedRecords = err.insertedIds;
} }
if (err.errorInClaims && err.errorInClaims.length > 0) { if (err.errorInClaims && err.errorInClaims.length > 0) {
this.errorInRecords = err.errorInClaims; this.errorInRecords = err.errorInClaims;
}*/ }
this.isertBulkClaims(claims); this.isertBulkClaims(claims);
ClaimInsertComponent.handleError("Error inserting direct records: " + JSON.stringify(directclaims), err); ClaimInsertComponent.handleError("Error inserting direct records: " + JSON.stringify(directclaims), err);
@ -262,24 +216,30 @@ export class ClaimInsertComponent {
} }
private isertBulkClaims(claims: ClaimRecord2Insert[]) { private isertBulkClaims(claims: ClaimRecord2Insert[]) {
console.log("claims");
console.log(claims);
this.errors.splice(0, this.errors.length); this.errors.splice(0, this.errors.length);
this.subscriptions.push(this.claimService.insertBulkClaims(claims, this.properties.claimsAPIURL).subscribe( this.subscriptions.push(this.claimService.insertBulkClaims(claims, this.properties.claimsAPIURL).subscribe(
data => { data => {
this.claims2Insert = claims.length; this.insertedClaims = data.insertedIds;
this.claimsJob = data.data; this.errorInClaims = data.errorInClaims;
if(this.properties.logServiceUrl) { //TODO remove - testing having errors in claims
for(let info of this.infoToLog) { // this.insertedClaims.pop();
this.subscriptions.push(this._logService.logLink(this.properties, info[0],info[1]).subscribe(res => { // 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.afterclaimsInsertion();
let timerSubscription = timer(0, 10000).pipe(
map(() => {
this.getStatus(); // load data contains the http request
})
).subscribe();
this.subscriptions.push(timerSubscription);
}, },
err => { err => {
err = err && err.error?err.error:err; err = err && err.error?err.error:err;
@ -382,27 +342,19 @@ export class ClaimInsertComponent {
} }
private afterclaimsInsertion() { private afterclaimsInsertion() {
this.claiming = false;
this.loading.close();
this.loading.close();
this.claiming = false;
if (this.errorInClaims.length == 0 && this.insertedClaims.length > 0) { if (this.errorInClaims.length == 0 && this.insertedClaims.length > 0) {
localStorage.removeItem(this.localStoragePrefix + "sources"); localStorage.removeItem(this.localStoragePrefix + "sources");
localStorage.removeItem(this.localStoragePrefix + "results"); localStorage.removeItem(this.localStoragePrefix + "results");
localStorage.removeItem(this.localStoragePrefix + "claimsJob"); this._router.navigate(['/myclaims'], {queryParams: this.params});
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(["/"]);
}
} }
} }
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 { return {
claimedBy: user, claimedBy: user,
sourceId: contextEntity.context.concept.id, sourceId: contextEntity.context.concept.id,
@ -415,12 +367,11 @@ export class ClaimInsertComponent {
targetCollectedFrom: resultEntity.result.source, targetCollectedFrom: resultEntity.result.source,
targetAccessRights: resultEntity.result.accessRights, targetAccessRights: resultEntity.result.accessRights,
targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(resultEntity), targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(resultEntity),
claimedInDashboard : dashboard, claimedInDashboard : dashboard
idSuffix : idSuffix
}; };
} }
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 { return {
claimedBy: user, claimedBy: user,
sourceId: projectEntity.id, sourceId: projectEntity.id,
@ -433,29 +384,11 @@ export class ClaimInsertComponent {
targetCollectedFrom: resultEntity.result.source, targetCollectedFrom: resultEntity.result.source,
targetAccessRights: resultEntity.result.accessRights, targetAccessRights: resultEntity.result.accessRights,
targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(resultEntity), targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(resultEntity),
claimedInDashboard : dashboard, 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
}; };
} }
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 { return {
claimedBy: user, claimedBy: user,
@ -469,9 +402,7 @@ export class ClaimInsertComponent {
targetCollectedFrom: inlineResult.result.source, targetCollectedFrom: inlineResult.result.source,
targetAccessRights: inlineResult.result.accessRights, targetAccessRights: inlineResult.result.accessRights,
targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(inlineResult), targetEmbargoEndDate: ClaimInsertComponent.getEmbargoEndDate(inlineResult),
claimedInDashboard : dashboard, claimedInDashboard : dashboard
idSuffix : idSuffix
}; };
} }
@ -481,13 +412,12 @@ export class ClaimInsertComponent {
} }
return "" return ""
} }
static createOpenAIREId(id, idSuffix:string):string {
return id.indexOf( "::" ) == -1 ? ("userclaim___::" + Md5.hashStr(id + idSuffix)):id; static createDirectClaim(resultEntity: ClaimEntity, results: ClaimEntity[]) {
}
static createDirectClaim(resultEntity: ClaimEntity, results: ClaimEntity[], idSuffix:string) {
let entity = {}; let entity = {};
entity["originalId"] = this.createOpenAIREId(resultEntity.id, idSuffix); const md5_id = Md5.hashStr(resultEntity.id);
entity["openaireId"] = this.createOpenAIREId(resultEntity.id, idSuffix); entity["originalId"] = "userclaim___::" + md5_id;
entity["openaireId"] = "userclaim___::" + md5_id;
entity["title"] = resultEntity.title; entity["title"] = resultEntity.title;
entity["title"] = (Array.isArray(resultEntity.title) && resultEntity.title.length > 0) ? resultEntity.title[0] : 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"] = []; entity["linksToProjects"] = [];
} }
let project: ClaimEntity = results[i]; 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) { } else if (results[i].context) {
@ -594,77 +524,10 @@ export class ClaimInsertComponent {
} }
if(this.defaultColors){ if(this.defaultColors){
buttonClass+=" linksbaskettitles uk-padding-small "; buttonClass+=" linksbaskettitles uk-padding-small ";
}else{
buttonClass+=" uk-button uk-button-large ";
} }
return buttonClass + "uk-text-center "; return buttonClass + "uk-text-center ";
} }
getStatus(){
if(this.feedRecordsJob && ! (this.feedRecordsJob.status == "COMPLETE" || this.feedRecordsJob.status == "ERROR") ) {
this.subscriptions.push(this.claimService.getStatus(this.feedRecordsJob.id, this.properties.claimsAPIURL).subscribe(data => {
this.feedRecordsJob = data.data;
// console.log("feed", this.feedRecordsJob.status);
if (this.feedRecordsJob.status == "COMPLETE" || data.data.status == "ERROR") {
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;
// console.log("claim: ", this.claimsJob.status, this.feedRecordsJob.status?this.feedRecordsJob.status:" no feed job");
if ((this.claimsJob.status == "COMPLETE" || data.data.status == "ERROR") && ( !this.feedRecordsJob || (this.feedRecordsJob.status == "COMPLETE" || data.data.status == "ERROR")) ) {
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();
}
}, 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 { 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 {AlertModalModule} from '../../../utils/modal/alertModal.module';
import {LoadingModalModule} from '../../../utils/modal/loadingModal.module'; import {LoadingModalModule} from '../../../utils/modal/loadingModal.module';
import {ClaimInsertComponent} from './insertClaim.component'; import {ClaimInsertComponent} from './insertClaim.component';
import {ClaimServiceModule} from '../../claim-utils/service/claimsService.module'; import {ClaimServiceModule} from '../../claim-utils/service/claimsService.module';
import {IconsModule} from "../../../utils/icons/icons.module";
import {LogServiceModule} from "../../../utils/log/LogService.module";
@NgModule({ @NgModule({
imports: [ imports: [
SharedModule, AlertModalModule, LoadingModalModule, ClaimServiceModule, IconsModule, LogServiceModule SharedModule, AlertModalModule, LoadingModalModule, ClaimServiceModule
], ],
declarations: [ClaimInsertComponent], declarations: [ClaimInsertComponent],
exports:[ ClaimInsertComponent] exports:[ ClaimInsertComponent]

View File

@ -1,263 +1,353 @@
<ng-template #destinations_basket> <metadata-preview *ngIf="showOptions.show=='claim' && properties" class="uk-margin-top"
<div *ngIf="(results.length)> 0 || showOptions.show=='result'" class="uk-padding-small uk-padding-remove-horizontal" style="min-height: 17px;"> [results]="results" [sources]="sources"
<start-over *ngIf=" (results.length)> 0" [localStoragePrefix]="localStoragePrefix" [inlineEntity]="inlineEntity"
[results]="results" [localStoragePrefix]="localStoragePrefix+'results'" [showOptions]="showOptions" [properties]=properties [pageContents]="pageContents"
message="all results (projects, communities, research results)" [defaultColors]="(communityId?false:true)" [communityId]="communityId"
class="uk-float-right"></start-over> >
<bulk-claim *ngIf="showOptions.show=='result'" [results]="results" [properties]=properties </metadata-preview>
[localStoragePrefix]="localStoragePrefix+'results'" <div id="tm-main" class="uk-section uk-padding-remove-top tm-middle" *ngIf="showOptions.show != 'claim'">
[basketLimit]="basketLimit"></bulk-claim> <div class="uk-grid">
</div> <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-padding-small uk-padding-remove-horizontal"> <schema2jsonld *ngIf="url" [URL]="url" name="Link your research outcomes" type="other"></schema2jsonld>
<div *ngIf="results.length >= basketLimit " <div [class]="((showOptions.show == 'claim')?'':' uk-margin-top ')+' uk-container uk-container-large '">
class="uk-alert uk-alert-warning uk-text-center"> <div>
Basket reached the size limit. No more entities can be added. <!-- <div class="uk-width-1-1">
</div> <helper position="top"></helper>
<claim-selected-results sectionTitle="Selected Results" [results]="results" </div> -->
[localStoragePrefix]="localStoragePrefix+'results'" type="target"> <div class="uk-grid helper-grid">
</claim-selected-results> <!-- <helper position="left" styleName=" uk-width-1-5 uk-padding-left"></helper>-->
<div *ngIf="(results.length) == 0 " class=" uk-text-center"> <div class="uk-width-expand">
No entities to link with the sources. Start adding entities from the left panel.
</div>
</div> <div *ngIf="properties" class="uk-section uk-section-default white-box-with-border uk-padding-small uk-padding-remove-top">
</ng-template>
<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 *ngIf="showOptions.show!='source' && showOptions.show != 'claim' && showOptions.linkToEntities.length > 1">-->
<div class="uk-container uk-container-large uk-section uk-section-small uk-padding-remove-bottom"> <!-- <mat-form-field class="matSelectionFormField">-->
<div class="uk-padding-small uk-padding-remove-horizontal"> <!-- <mat-label>Sort by:</mat-label>-->
<breadcrumbs *ngIf="!inlineEntity" [breadcrumbs]="breadcrumbs"></breadcrumbs> <!-- <mat-select [(ngModel)]="showOptions.show" class="uk-width-auto uk-text-bold matSelection"-->
<!-- [routerLink]="inlineEntity.result?.url.split('?')[0]"--> <!-- *ngIf="showOptions.linkToEntities.length > 1"-->
<!-- [queryParams]="routerHelper.createQueryParam(inlineEntity.result?.url.split('?')[1].split('=')[0], inlineEntity.id)"--> <!-- [disableOptionCentering]="true"-->
<a *ngIf="inlineEntity && inlineEntity.result" <!-- panelClass="matSelectionPanel">-->
(click)="back()" <!-- <mat-option *ngIf="showOptions.linkToEntities.indexOf('project')!=-1 "-->
class="uk-button uk-button-link uk-text-transform-none uk-flex uk-flex-middle"> <!-- value="project">PROJECTS</mat-option>-->
<icon name="west" [flex]="true"></icon> <!-- <mat-option *ngIf="showOptions.linkToEntities.indexOf('result')!=-1 " value="result">RESEARCH-->
<span class="uk-margin-small-left">Back to {{getEntityName(inlineEntity.type, false)}}</span> <!-- RESULTS</mat-option>-->
</a> <!-- <mat-option *ngIf="showOptions.linkToEntities.indexOf('context')!=-1 " value="context">COMMUNITIES-->
<a *ngIf="inlineEntity && inlineEntity.project" <!-- </mat-option>-->
[routerLink]="inlineEntity.project?.url?.split('?')[0]" <!-- </mat-select>-->
[queryParams]="routerHelper.createQueryParam(inlineEntity.project?.url.split('?')[1].split('=')[0], inlineEntity.id)" <!-- </mat-form-field>-->
class="uk-button uk-button-link uk-text-transform-none uk-flex uk-flex-middle"> <!-- </div>-->
<icon name="west" [flex]="true"></icon>
<span class="uk-margin-small-left">Back to {{getEntityName(inlineEntity.type, false)}}</span> <span *ngIf="showOptions.show!='source' && showOptions.show != 'claim' && showOptions.linkToEntities.length > 1"
</a> class="uk-flex-inline uk-flex-middle uk-width-3-5@m uk-width-1-1@s">
</div> <span class="uk-width-1-4 uk-text-muted uk-text-large">LINK TO </span>
</div> <mat-select [(ngModel)]="showOptions.show" class="uk-width-3-4@m matSelection"
<div *ngIf="!inlineEntity" uk-sticky="offset: 65; end: #pageBottom; media: @m" class="uk-blur-background"> *ngIf="showOptions.linkToEntities.length > 1"
<div class="uk-section-xsmall"> [disableOptionCentering]="true"
<stepper> panelClass="matSelectionPanel">
<step [status]="stepStatus('source')" stepId="source" stepNumber="1" <mat-option *ngIf="showOptions.linkToEntities.indexOf('project')!=-1 "
[stepText]="'Find Sources'" (stepChanged)="stepHasChanged($event)" value="project">PROJECTS</mat-option>
[active]="this.showOptions.show" [showStepLine]="false"></step> <mat-option *ngIf="showOptions.linkToEntities.indexOf('result')!=-1 " value="result">RESEARCH
<step [status]="stepStatus('target')" stepId="target" [stepNumber]="2" RESULTS</mat-option>
[stepText]="'Link Sources to Entities'" <mat-option *ngIf="showOptions.linkToEntities.indexOf('context')!=-1 " value="context">COMMUNITIES
(stepChanged)="stepHasChanged($event)" [active]="this.showOptions.show" </mat-option>
[showStepLine]="true"></step> </mat-select>
<step [status]="stepStatus('claim')" stepId="claim" [stepNumber]="3" </span>
[stepText]="'Summarize and finish'"
(stepChanged)="stepHasChanged($event)" [active]="this.showOptions.show" <span *ngIf="showOptions.show!='source' && showOptions.show != 'claim' && showOptions.linkToEntities.length ==1">
[showStepLine]="true"></step> <span>LINK TO </span>
</stepper> <span class=" uk-width-auto uk-text-bold">
</div> <span *ngIf="showOptions.linkToEntities.indexOf('project')!=-1 "
</div> value="project">PROJECTS</span>
<div id="pageTop"></div> <span *ngIf="showOptions.linkToEntities.indexOf('result')!=-1 " value="result">RESEARCH
<metadata-preview *ngIf="showOptions.show=='claim' && properties" class="uk-margin-top" RESULTS</span>
[results]="results" [sources]="sources" <span *ngIf="showOptions.linkToEntities.indexOf('context')!=-1 " value="context">COMMUNITIES
[localStoragePrefix]="localStoragePrefix" [inlineEntity]="inlineEntity" </span>
[showOptions]="showOptions" [properties]=properties [pageContents]="pageContents" </span>
[defaultColors]="!communityId" [communityId]="communityId" [claimsProperties]="claimsProperties" </span>
> <span *ngIf="showOptions.show=='source'" class="uk-text-bold">
</metadata-preview> ADD LINKING SOURCES
<div id="tm-main" class="uk-section uk-padding-remove-top" *ngIf="showOptions.show != 'claim'"> </span>
<div>
<schema2jsonld *ngIf="url" [URL]="url" name="Link your {{openaireEntities.RESULTS}}" type="other"></schema2jsonld> </div>
<div class="uk-container uk-container-large"> <div *ngIf="showOptions.show=='source'">
<div *ngIf="properties && claimsProperties" class="uk-section uk-padding-remove-top"> <claim-result-search-form [selectedResults]="sources" [properties]=properties
<div class="uk-container uk-container-large"> [localStoragePrefix]="localStoragePrefix+'sources'" [basketLimit]="basketLimit"
<div class="uk-grid basketContainer" *ngIf="showOptions.show!='claim'" uk-grid> ></claim-result-search-form>
<div class="uk-width-2-3@m uk-position-z-index uk-flex-first@m uk-flex-last uk-margin-medium-top"> </div>
<h2 *ngIf="inlineEntity && claimsProperties.INLINE_ENTITY.show" class="uk-text-center">Link source to</h2> <div *ngIf="showOptions.show=='project'">
<div *ngIf="inlineEntity && claimsProperties.INLINE_ENTITY.guideText" class="uk-text-center">{{claimsProperties.INLINE_ENTITY.guideText}}</div> <claim-projects-search-form [selectedProjects]="results" [properties]=properties
<div *ngIf="showOptions.show=='source'"> [localStoragePrefix]="localStoragePrefix+'results'" [basketLimit]="basketLimit"
<claim-result-search-form [selectedResults]="sources" [properties]=properties ></claim-projects-search-form>
[localStoragePrefix]="localStoragePrefix+'sources'" </div>
[basketLimit]="basketLimit" [centerAlign]="!!inlineEntity" <div *ngIf="showOptions.show=='context'">
></claim-result-search-form> <claim-contexts-search-form [communityId]=communityId [results]="results" [sources]="sources"
</div> [properties]=properties
<div *ngIf="showOptions.show=='project'"> [localStoragePrefix]="localStoragePrefix+'results'" [basketLimit]="basketLimit"
<claim-projects-search-form [selectedProjects]="results" [properties]=properties ></claim-contexts-search-form>
[localStoragePrefix]="localStoragePrefix+'results'" </div>
[basketLimit]="basketLimit" [showOptions]="showOptions" <div *ngIf="showOptions.show=='result'">
[centerAlign]="!!inlineEntity" <claim-result-search-form [selectedResults]="results" [properties]=properties
></claim-projects-search-form> [localStoragePrefix]="localStoragePrefix+'results'" [basketLimit]="basketLimit"
</div> ></claim-result-search-form>
<div *ngIf="showOptions.show=='context'"> </div>
<claim-contexts-search-form [communityId]=communityId [results]="results" [sources]="sources"
[properties]=properties </div>
[localStoragePrefix]="localStoragePrefix+'results'" <!-- Basket-->
[basketLimit]="basketLimit" [showOptions]="showOptions" <div *ngIf="showOptions.show != 'claim'" class="uk-width-1-3" style="" >
[centerAlign]="!!inlineEntity" <div id="basket" uk-sticky=" offset: 130; top:#basketStickTop; bottom: #basketStickBottom;"
></claim-contexts-search-form> style="z-index: 0">
</div> <h6 class="linksbasketheader uk-margin-bottom uk-text-bold">
<div *ngIf="showOptions.show=='result'"> LINKS BASKET
<claim-result-search-form [selectedResults]="results" [properties]=properties </h6>
[localStoragePrefix]="localStoragePrefix+'results'" <div class="linksbasket uk-inline uk-width-1-1" style="">
[basketLimit]="basketLimit" [showOptions]="showOptions" <div *ngIf="inlineEntity == null">
[centerAlign]="!!inlineEntity" <div class="linksbaskettitles uk-padding-small uk-animation-toggle"
></claim-result-search-form> (click)="showOptions.showBasketSources()"
</div> [style.cursor]="(showOptions.show!='source'?'pointer':'default')">
</div> <div class="uk-h6 uk-margin-remove portal-color" >
<!-- Basket--> SOURCES ({{(sources.length) | number}})
<div *ngIf="showOptions.show != 'claim'" class="uk-width-1-3@m uk-flex-last@m uk-flex-first uk-margin-medium-top"> <span *ngIf="showOptions.show!='source' && !showOptions.basketShowSources"
<div id="basket" uk-sticky="offset: 220; end: !*; media: @m" style="z-index: 0!important;"> class="uk-icon"><svg width="20"
<div class="uk-card uk-card-default linkingBasket"> height="20"
<div class="uk-card-body uk-padding-small"> viewBox="0 0 20 20"
<div> xmlns="http://www.w3.org/2000/svg"
<ng-container *ngIf="inlineEntity"> icon="chevron-left"
<div *ngIf="claimsProperties.INLINE_ENTITY.show" class="uk-margin-small-bottom"> ratio="1"><polyline
<div class="uk-text-emphasis uk-text-bolder">{{claimsProperties.BASKET.source_title}}</div> fill="none" stroke="#000" stroke-width="1.03" points="13 16 7 10 13 4"></polyline></svg></span>
<claim-selected-results [results]="[inlineEntity]" <span *ngIf="showOptions.show!='source' && showOptions.basketShowSources"
[localStoragePrefix]="localStoragePrefix+'sources'" class="" class="uk-icon"><svg width="20"
[enableRemove]="false" type="source"> height="20"
</claim-selected-results> 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>
<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-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> <span class="uk-label custom-label linkInlineEntityLabel"
<ng-container *ngTemplateOutlet="destinations_basket"></ng-container> 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> </div>
</ng-container>
<ng-container *ngIf="!inlineEntity"> </div>
<ul class="uk-tab" uk-tab> <div *ngIf="showOptions.show !='source'">
<li [class.uk-active]="showOptions.basketShowSources" <div class=" linksbaskettitles uk-padding-small uk-animation-toggle" (click)="showOptions.basketShowLinksTo=!showOptions.basketShowLinksTo;
(click)="showOptions.basketswitchToSources()"> showOptions.basketShowSources=!showOptions.basketShowLinksTo ">
<a> <div *ngIf="!inlineEntity"> <!--Enable toggle -->
Sources to link ({{(sources.length) |number}}) <span class="uk-h6 uk-margin-remove portal-color" >
</a> LINK TO ({{(results.length) | number}})
</li> <span *ngIf="!showOptions.basketShowLinksTo" class="uk-icon"><svg width="20"
<li [class.uk-disabled]="sources.length == 0" height="20"
[class.uk-active]="showOptions.basketShowLinksTo"> viewBox="0 0 20 20"
<a (click)="showOptions.basketswitchToLinkTo()">Link to <span xmlns="http://www.w3.org/2000/svg"
*ngIf="results.length> 0">({{(results.length) | number}})</span> icon="chevron-left"
</a> ratio="1"><polyline
</li> fill="none" stroke="#000" stroke-width="1.03"
</ul> points="13 16 7 10 13 4"></polyline></svg></span>
<div *ngIf="showOptions.basketShowSources"> <span *ngIf="showOptions.basketShowLinksTo" class="uk-icon"><svg width="20"
<div class="uk-height-max-medium uk-overflow-auto uk-padding uk-padding-remove-left uk-padding-remove-vertical"> height="20"
<div *ngIf="showOptions.show == 'source'" class="uk-padding-small uk-padding-remove-horizontal" style="min-height:17px;"> viewBox="0 0 20 20"
<start-over *ngIf="showOptions.show == 'source' && sources.length> 0" xmlns="http://www.w3.org/2000/svg"
[results]="sources" icon="chevron-down"
[localStoragePrefix]="localStoragePrefix+'sources'" ratio="1"><polyline
message="all sources" class="uk-float-right"></start-over> fill="none" stroke="#000" stroke-width="1.03"
<bulk-claim *ngIf="showOptions.show == 'source'" [results]="sources" points="16 7 10 13 4 7"></polyline></svg></span>
[properties]=properties </span>
[localStoragePrefix]="localStoragePrefix+'sources'" [basketLimit]="basketLimit" </div>
> <div *ngIf="inlineEntity"> <!--Inline Entity - no toggle -->
</bulk-claim> <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 class="linksBasketSubtitles">
<div *ngIf="sources.length == 0" class="uk-text-center uk-text-meta"> Entities to link with the sources
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> </div>
</div> </div>
<div *ngIf="showOptions.basketShowLinksTo"> <div *ngIf="showOptions.basketShowLinksTo"
<div class="uk-height-max-medium uk-overflow-auto uk-padding uk-padding-remove-left uk-padding-remove-vertical"> class="uk-height-medium uk-overflow-auto">
<ng-container *ngTemplateOutlet="destinations_basket"></ng-container> <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>
</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> </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> </div>
<div id="basketStickBottom"></div>
<helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0" [texts]="pageContents['bottom']"></helper>
</div> </div>
<!-- <helper position="right" styleName=" uk-width-1-5"></helper>-->
</div> </div>
<!-- <helper position="right" styleName=" uk-width-1-5"></helper>--> <!-- <helper position="bottom"></helper>-->
</div> </div>
<helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0"
[texts]="pageContents['bottom']"></helper>
</div> </div>
</div> </div>
</div> </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> </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 {ActivatedRoute, Router} from '@angular/router';
import {Meta, Title} from '@angular/platform-browser'; import {Meta, Title} from '@angular/platform-browser';
import {EnvProperties} from '../../utils/properties/env-properties'; 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 {PiwikService} from "../../utils/piwik/piwik.service";
import {Subscriber} from "rxjs"; import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component";
import {OpenaireEntities} from "../../utils/properties/searchFields"; declare var UIkit:any;
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";
@Component({ @Component({
selector: 'linking-generic', selector: 'linking-generic',
templateUrl: 'linkingGeneric.component.html' templateUrl: 'linkingGeneric.component.html'
}) })
export class LinkingGenericComponent { export class LinkingGenericComponent {
@Input() pageTitle: string = "Create links between research objects"; @Input() piwikSiteId = null;
@Input() pageTitle: string = " Create links between research objects";
piwiksub:any; piwiksub:any;
@Input() communityId:string= null; @Input() communityId:string= null;
@ -42,43 +38,28 @@ export class LinkingGenericComponent {
// show linkToEntities /values: result, project, context // show linkToEntities /values: result, project, context
@Input() sources:ClaimEntity[] =[]; @Input() sources:ClaimEntity[] =[];
properties:EnvProperties = properties; properties:EnvProperties;
public openaireEntities = OpenaireEntities;
@Input() localStoragePrefix:string = "linking_"; @Input() localStoragePrefix:string = "linking_";
url=null; url=null;
@ViewChild(AlertModal) alert; @ViewChild(AlertModal) alert;
public pageContents = null; 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, constructor (private _router: Router, private route: ActivatedRoute, private entitySearch:EntitiesSearchService,
private _meta: Meta, private _title: Title, private _piwikService:PiwikService, private _meta: Meta, private _title: Title, private _piwikService:PiwikService,
private seoService: SEOService, private helper: HelperService, private cdr: ChangeDetectorRef, private seoService: SEOService, private helper: HelperService ) {
private location: Location, private userManagementService: UserManagementService) {
} }
subscriptions = []; subscriptions = [];
ngOnInit() { 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.show = 'source';
this.showOptions.initSelectOptions(this.claimsProperties);
if(this.inlineEntity){ if(this.inlineEntity){
this.showOptions.showLinkTo(); this.showOptions.basketShowSources = false;
// this.showOptions.basketShowLinksTo = true; this.showOptions.basketShowLinksTo = true;
this.showOptions.show = this.showOptions.linkTo; this.showOptions.show = this.showOptions.linkTo;
} }
this.properties = properties;
this.url = this.properties.domain + this.properties.baseLink+this._router.url; 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."; 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.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.helper.getPageHelpContents(this.properties, this.communityId, this._router.url).subscribe(contents => {
this.pageContents = contents; this.pageContents = contents;
}) })
}
if( typeof localStorage !== 'undefined') { if( typeof localStorage !== 'undefined') {
@ -106,11 +87,6 @@ export class LinkingGenericComponent {
if(localStorage.getItem(this.localStoragePrefix + "sources")){ if(localStorage.getItem(this.localStoragePrefix + "sources")){
this.sources = JSON.parse(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) { private updateUrl(url:string) {
this._meta.updateTag({content:url},"property='og:url'"); 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 { NgModule } from '@angular/core';
import {MatSelectModule} from "@angular/material/select"; 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 {SelectedProjectsModule} from './selected/selectedProjects.module';
import {SelectedContextsModule} from './selected/selectedContexts.module'; import {SelectedContextsModule} from './selected/selectedContexts.module';
import {SelectedPublicationsModule} from './selected/selectedResults.module'; import {SelectedPublicationsModule} from './selected/selectedResults.module';
import {LinkingGenericComponent} from './linkingGeneric.component'; import {LinkingGenericComponent} from './linkingGeneric.component';
import {StartOverModule} from '../claim-utils/startOver.module'; 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 {ClaimContextSearchFormModule} from '../claim-utils/claimContextSearchForm.module';
import {ClaimProjectsSearchFormModule} from '../claim-utils/claimProjectSearchForm.module'; import {ClaimProjectsSearchFormModule} from '../claim-utils/claimProjectSearchForm.module';
import {BulkClaimModule} from './bulkClaim/bulkClaim.module'; import {BulkClaimModule} from './bulkClaim/bulkClaim.module';
import {ClaimResultSearchFormModule} from '../claim-utils/claimResultSearchForm.module'; import {ClaimResultSearchFormModule} from '../claim-utils/claimResultSearchForm.module';
import {HelperModule} from '../../utils/helper/helper.module'; import {HelperModule} from '../../utils/helper/helper.module';
import {IsRouteEnabled} from '../../error/isRouteEnabled.guard';
import {Schema2jsonldModule} from '../../sharedComponents/schema2jsonld/schema2jsonld.module'; 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 {MetadataPreviewModule} from './selected/metadataPreview.module';
import {ClaimEntitiesMetadataModule} from "./selected/ClaimEntitiesMetadata.module"; import {ClaimEntitiesMetadataModule} from "./selected/ClaimEntitiesMetadata.module";
import {AlertModalModule} from '../../utils/modal/alertModal.module'; import {AlertModalModule} from '../../utils/modal/alertModal.module';
import {BreadcrumbsModule} from "../../utils/breadcrumbs/breadcrumbs.module"; import {PiwikServiceModule} from "../../utils/piwik/piwikService.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";
@NgModule({ @NgModule({
imports: [ imports: [
SharedModule, SelectedProjectsModule, SelectedContextsModule, SharedModule, SelectedProjectsModule, SelectedContextsModule,
SelectedPublicationsModule, SelectedPublicationsModule,
StartOverModule, StartOverModule,
ClaimContextSearchFormModule, ClaimProjectsSearchFormModule, BulkClaimModule, ClaimResultSearchFormModule, ClaimContextSearchFormModule, ClaimProjectsSearchFormModule, BulkClaimModule, ClaimResultSearchFormModule,
HelperModule, Schema2jsonldModule, SEOServiceModule, MetadataPreviewModule, ClaimEntitiesMetadataModule, AlertModalModule, HelperModule, Schema2jsonldModule, SEOServiceModule, MetadataPreviewModule, ClaimEntitiesMetadataModule, AlertModalModule,
MatSelectModule, BreadcrumbsModule, StepperModule, IconsModule PiwikServiceModule,
MatSelectModule
], ],
providers: [], providers:[LoginGuard, PreviousRouteRecorder, IsRouteEnabled],
declarations: [ declarations: [
LinkingGenericComponent LinkingGenericComponent
], exports: [ ], exports:[
LinkingGenericComponent] LinkingGenericComponent ]
}) })
export class LinkingGenericModule { export class LinkingGenericModule { }
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([link]);
}
}

View File

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

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({ @Component({
selector: 'claim-project-metadata', selector: 'claim-project-metadata',
template: ` 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" <div *ngIf="entity.type == 'project' && entity.project" class="uk-grid uk-margin-remove-top uk-text-small">
[class.uk-margin-xsmall-top]="!shortVersion"> <div class="uk-width-1-2">
<span class="uk-text-capitalize"> <div *ngIf="entity.project.funderName">
{{entity.type == 'project' && entity.project.code == 'unidentified'?'funder':entity.type}} <span class="uk-text-muted">Funder </span>{{entity.project.funderName}}
</span> </div>
<span *ngIf="entity.project.startDate || entity.project.endDate">
{{(entity.project.startDate) ? entity.project.startDate : 'Unknown'}}{{'-' + ((entity.project.endDate) ? entity.project.endDate : 'Unknown')}}
</span>
</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" <div class="uk-width-1-2">
[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 *ngIf="entity.project.code"> <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>
<div *ngIf="entity.project.funderName || entity.project.funderShortname"> <div *ngIf=" !shortVersion && (entity.project.startDate || entity.project.endDate)">
<span class="uk-text-meta">Funding: </span>{{entity.project.funderName?entity.project.funderName:entity.project.funderShortname}} <span
class="uk-text-muted">Duration </span>{{(entity.project.startDate) ? entity.project.startDate : 'Unknown'}}{{'-' + ((entity.project.endDate) ? entity.project.endDate : 'Unknown')}}
</div> </div>
</div> </div>
</ng-container> </div>
`, `
styleUrls: ['ClaimEntityMetadata.component.less']
}) })

View File

@ -3,38 +3,33 @@ import {ClaimEntity} from '../../claim-utils/claimHelper.class';
@Component({ @Component({
selector: 'claim-result-metadata', selector: 'claim-result-metadata',
template: ` template:
`
<div *ngIf="entity.result"> <div *ngIf="entity.result">
<!-- display all existing data similar to entity-metadata --> <div *ngIf="entity.result.authors && entity.result.authors.length >0 " class="uk-text-small">
<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-muted">Authors </span>
<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">
{{sliceArray(entity.result.authors)}} {{sliceArray(entity.result.authors)}}
</div> </div>
<div class="uk-text-small uk-margin-top"> <div *ngIf="!shortVersion && entity.result.editors&& entity.result.editors.length > 0" class="uk-text-small">
<span *ngIf="getProjectDurationMessage(entity)" [class]="(getProjectDurationMessage(entity)?'uk-text-warning':'')"> <span class="uk-text-muted">Editors </span>
{{getProjectDurationMessage(entity)}} {{sliceArray(entity.result.editors)}}
</span> </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>
</div> </div>
`, `
styleUrls: ['ClaimEntityMetadata.component.less']
}) })

View File

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

View File

@ -1,314 +1,452 @@
<div class="uk-section uk-margin-small-top uk-padding-remove-top"> <div class="uk-section uk-padding-remove-top uk-padding-remove-bottom ">
<div class="uk-container uk-container-large"> <div
<div *ngIf="properties" class="uk-section uk-padding-remove-top"> [class]="((defaultColors)?'linkingToolbar':'communityPanelBackground')+' uk-padding-small'">
<div class="uk-margin-top"> <div class="uk-container uk-container-large uk-margin-small-top uk-padding-small">
<div class="uk-grid" uk-grid> <div class="uk-grid">
<div class="uk-width-expand"> <div class="uk-padding-remove-left uk-margin-auto-vertical back uk-link">
<div class="uk-card uk-card-default"> <span
<div class="uk-card-body"> (click)="showOptions.showLinkTo()"
<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" > style="cursor:pointer">
<!-- Sources--> <span class="uk-icon">
<div *ngIf="claimsProperties.INLINE_ENTITY.show"> <svg width="30" height="30" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="chevron-left"
<div class=" uk-margin uk-animation-toggle"> ratio="1.5"><polyline fill="none" stroke="#000" stroke-width="1.03"
<span class="uk-h6 "> {{claimsProperties.METADATA_PREVIEW.source_title}} ({{sources.length + (inlineEntity ? 1 : 0) | number}}) points="13 16 7 10 13 4"></polyline></svg></span>
</span> BACK
<a *ngIf="!inlineEntity" class="uk-float-right uk-text-small" (click)="showOptions.showSource() "> <span </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> </div>
<modal-alert (alertOutput)="confirmClose()"> <div class="uk-width-expand">
</modal-alert> <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> </div>
</div> </div>
<helper *ngIf="pageContents && pageContents['bottom'] && pageContents['bottom'].length > 0" </div>
[texts]="pageContents['bottom']"></helper>
<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> </div>

View File

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

View File

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

View File

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

View File

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

View File

@ -1,27 +1,19 @@
<ul *ngIf="results.length > 0 " class="uk-list uk-list-divider"> <ul *ngIf="results.length > 0 " class="uk-list uk-list-divider">
<li *ngFor=" let entity of results " class=""> <li *ngFor=" let entity of results " >
<!--<div class="uk-text-muted"> <div class="uk-text-muted">
{{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}} {{(!entity.result) ? entity.type : ((entity.result && entity.result.source == 'openaire') ? entity.type : (entity.result && entity.result.source + ' result'))}}
</div>--> </div>
<div class="uk-grid uk-flex uk-flex-middle uk-margin-small-top uk-margin-small-bottom uk-margin-remove-left"> <div class="uk-grid">
<!--<div > <div class="uk-width-expand">
<span *ngIf="type == 'source' || entity.result" class="material-icons uk-text-small uk-text-meta">insert_drive_file <claim-title [entity]="entity" [slice]="true" [sliceSize]="45" [shortVersion]="true"></claim-title>
</span> <claim-result-metadata [entity]="entity" [slice]="true" [sliceSize]="5" [shortVersion]="true"></claim-result-metadata>
<span *ngIf="type == 'target' && entity.project" <claim-project-metadata [entity]="entity" [slice]="true" [sliceSize]="5" [shortVersion]="true"></claim-project-metadata>
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>
<div class="uk-margin-auto-vertical uk-padding-remove-left uk-margin-small-left" *ngIf="enableRemove"> <div class="uk-margin-auto-vertical uk-padding-remove-left uk-margin-small-left" *ngIf="enableRemove">
<a class=" uk-link " (click)="remove(entity)" > <a class=" uk-icon-button " (click)="remove(entity)" >
<span uk-icon="close"> </span> <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> </a>
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
import {Component, Input} from '@angular/core'; import {Component, Input} from '@angular/core';
import {ClaimEntity} from '../../claim-utils/claimHelper.class'; import {ClaimEntity} from '../../claim-utils/claimHelper.class';
declare var UIkit: any;
@Component({ @Component({
selector: 'claim-selected-results', selector: 'claim-selected-results',
templateUrl: 'selectedResults.component.html' templateUrl: 'selectedResults.component.html'
@ -11,8 +11,7 @@ export class ClaimSelectedResultsComponent {
@Input() sectionTitle: string = "Research Results"; @Input() sectionTitle: string = "Research Results";
@Input() localStoragePrefix: string = ""; @Input() localStoragePrefix: string = "";
@Input() enableRemove:boolean = true; @Input() enableRemove:boolean = true;
@Input() type: "source" | "target";
@Input() shortVersion:boolean = true;
ngOnInit() { ngOnInit() {
} }
@ -24,11 +23,6 @@ export class ClaimSelectedResultsComponent {
if (this.results != null) { if (this.results != null) {
localStorage.setItem(this.localStoragePrefix, JSON.stringify(this.results)); 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 { NgModule } from '@angular/core';
import { SharedModule } from '../../../../openaireLibrary/shared/shared.module'; import { SharedModule } from '../../../shared/shared.module';
import {ClaimSelectedResultsComponent} from './selectedResults.component'; import {ClaimSelectedResultsComponent} from './selectedResults.component';
import {AlertModalModule} from '../../../utils/modal/alertModal.module'; import {AlertModalModule} from '../../../utils/modal/alertModal.module';
import { MyDatePickerModule } from '../../../utils/my-date-picker/my-date-picker.module'; import { MyDatePickerModule } from '../../../utils/my-date-picker/my-date-picker.module';

View File

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

View File

@ -1,8 +1,11 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { SharedModule } from '../../../openaireLibrary/shared/shared.module'; import { SharedModule } from '../../shared/shared.module';
import { MyClaimsComponent } from './myClaims.component'; import { MyClaimsComponent } from './myClaims.component';
import {DisplayClaimsModule} from '../claim-utils/displayClaims/displayClaims.module'; 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({ @NgModule({
imports: [ imports: [
@ -10,7 +13,7 @@ import {DisplayClaimsModule} from '../claim-utils/displayClaims/displayClaims.mo
DisplayClaimsModule DisplayClaimsModule
], ],
providers:[], providers:[LoginGuard, PreviousRouteRecorder, IsRouteEnabled],
declarations: [ declarations: [
MyClaimsComponent MyClaimsComponent
], exports: [MyClaimsComponent] ], exports: [MyClaimsComponent]

View File

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

View File

@ -5,12 +5,11 @@ import { EnvProperties} from '../../utils/properties/env-properties';
import {ConnectHelper} from '../connectHelper'; import {ConnectHelper} from '../connectHelper';
import {SearchCommunityDataprovidersService} from '../contentProviders/searchDataproviders.service'; import {SearchCommunityDataprovidersService} from '../contentProviders/searchDataproviders.service';
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
import {OpenaireEntities} from "../../utils/properties/searchFields";
@Component({ @Component({
selector: 'approved-by-community', selector: 'approved-by-community',
template: ` 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>
` `
}) })
@ -22,7 +21,6 @@ export class ApprovedByCommunityComponent {
private communityContentProviders = []; private communityContentProviders = [];
properties:EnvProperties; properties:EnvProperties;
public openaireEntities = OpenaireEntities;
constructor (private route: ActivatedRoute, private _searchDataprovidersService: SearchCommunityDataprovidersService) {} constructor (private route: ActivatedRoute, private _searchDataprovidersService: SearchCommunityDataprovidersService) {}
@ -42,7 +40,7 @@ export class ApprovedByCommunityComponent {
this.approved = this.checkApproval(); this.approved = this.checkApproval();
}, },
error => { 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);
} }
); );
} }
@ -60,6 +58,6 @@ export class ApprovedByCommunityComponent {
} }
private handleError(message: string, error) { 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['description'] = resData.description;
result['date'] = resData.creationDate; result['date'] = resData.creationDate;
result['status'] = 'all'; result['status'] = 'all';
result['claim'] = resData.claim;
result['membership'] = resData.membership;
if (resData.hasOwnProperty('status')) { if (resData.hasOwnProperty('status')) {
result['status'] = resData.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) { if (resData.type != null) {
result['type'] = resData.type; result['type'] = resData.type;

View File

@ -1,103 +1,22 @@
import {properties} from "../../../../environments/environment";
export class Layout { export class Layout {
_id: string; _id:string;
portalPid: string; portalPid:string;
layoutOptions: CustomizationOptions; layoutOptions:CustomizationOptions;
date; constructor(community, options:CustomizationOptions){
constructor(community, options: CustomizationOptions) {
this.portalPid = community; this.portalPid = community;
this.layoutOptions = options; 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 { export class CustomizationOptions {
identity: { identity: {
mainColor: string; mainColor: string;
secondaryColor: string; secondaryColor: string;
}; };
identityIsCustom: boolean; identityIsCustom:boolean;
backgroundsIsCustom: boolean; backgroundsAndButtonsIsCustom:boolean;
buttonsIsCustom: boolean;
backgrounds: { backgrounds: {
dark: { dark: {
color: string; //background color: string; //background
} }
light: { light: {
color: string; //background color: string; //background
@ -106,43 +25,40 @@ export class CustomizationOptions {
color: string; //background color: string; //background
imageUrl: string; imageUrl: string;
imageFile: string; imageFile: string;
position: string; position:string;
fontsDarkMode:boolean;
} }
}; };
buttons: { buttons: {
darkBackground: ButtonsCustomization; darkBackground: ButtonsCustomization;
lightBackground: ButtonsCustomization; lightBackground: ButtonsCustomization;
}; };
constructor(mainColor: string = null, secondaryColor: string = null) { constructor(mainColor: string = null, secondaryColor: string = null) {
this.identity = { this.identity= {
mainColor: mainColor ? mainColor : CustomizationOptions.getIdentity().mainColor, mainColor: mainColor ? mainColor : CustomizationOptions.getIdentity().mainColor,
secondaryColor: secondaryColor ? secondaryColor : CustomizationOptions.getIdentity().secondaryColor, secondaryColor : secondaryColor ? secondaryColor : CustomizationOptions.getIdentity().secondaryColor,
}; };
this.identityIsCustom = false; this.identityIsCustom = false;
this.backgroundsIsCustom = false; this.backgroundsAndButtonsIsCustom = false;
this.buttonsIsCustom = false; this.backgrounds={
this.backgrounds = { dark : {
dark: {
color: this.identity.mainColor, color: this.identity.mainColor,
}, },
light: { light : {
color: "#f9f9f9" //CustomizationOptions.getRGBA(this.identity.mainColor,0.05), color: CustomizationOptions.getRGBA(this.identity.mainColor,0.05),
}, },
form: { form : {
color: CustomizationOptions.getRGBA(this.identity.mainColor, 0.15), color: CustomizationOptions.getRGBA(this.identity.mainColor,0.15),
imageUrl: null, imageUrl : null,
imageFile: null, imageFile : null,
position: null, position: null
fontsDarkMode: true
} }
}; };
this.buttons = { this.buttons = {
darkBackground: { darkBackground: {
isDefault: true, isDefault:true,
backgroundColor: "#ffffff", backgroundColor: "#ffffff",
color: "#000000", color: "#000000",
borderStyle: "solid", borderStyle: "solid",
@ -156,7 +72,7 @@ export class CustomizationOptions {
} }
}, },
lightBackground: { lightBackground: {
isDefault: true, isDefault:true,
backgroundColor: this.identity.mainColor, backgroundColor: this.identity.mainColor,
color: '#ffffff', color: '#ffffff',
borderStyle: "solid", borderStyle: "solid",
@ -169,107 +85,93 @@ export class CustomizationOptions {
borderColor: this.identity.secondaryColor, borderColor: this.identity.secondaryColor,
} }
} }
}; };
} }
public static checkForObsoleteVersion(current:CustomizationOptions, communityId:string){
public static checkForObsoleteVersion(current: CustomizationOptions, communityId: string) { let defaultCO = new CustomizationOptions(CustomizationOptions.getIdentity(communityId).mainColor,CustomizationOptions.getIdentity(communityId).secondaryColor);
if(communityId === 'connect') {
return null;
}
let defaultCO = new CustomizationOptions(CustomizationOptions.getIdentity(communityId).mainColor, CustomizationOptions.getIdentity(communityId).secondaryColor);
let updated = Object.assign({}, defaultCO); let updated = Object.assign({}, defaultCO);
if (!current) { if(current.identity && current.identity.mainColor && current.identity.secondaryColor ) {
current = Object.assign({}, defaultCO); updated = new CustomizationOptions(current.identity.mainColor, current.identity.secondaryColor);
} else { }
if (current.identity && current.identity.mainColor && current.identity.secondaryColor) { if(!current.backgrounds){
updated = new CustomizationOptions(current.identity.mainColor, current.identity.secondaryColor); current.backgrounds = Object.assign({}, updated.backgrounds);
} }
if (!current.backgrounds) { if(!current.backgrounds.dark){
current.backgrounds = Object.assign({}, updated.backgrounds); current.backgrounds.dark = Object.assign({}, updated.backgrounds.dark);
} }
if (!current.backgrounds.dark) { if(!current.backgrounds.light){
current.backgrounds.dark = Object.assign({}, updated.backgrounds.dark); current.backgrounds.light = Object.assign({}, updated.backgrounds.light);
} }
if (!current.backgrounds.light) { if(!current.backgrounds.form){
current.backgrounds.light = Object.assign({}, updated.backgrounds.light); current.backgrounds.form = Object.assign({}, updated.backgrounds.form);
} }
if (!current.backgrounds.form) { if(!current.backgrounds.form.position){
current.backgrounds.form = Object.assign({}, updated.backgrounds.form); current.backgrounds.form.position = "center bottom"
} }
if (!current.backgrounds.form.position) { if(!current.buttons){
current.backgrounds.form.position = "center bottom" current.buttons = Object.assign({}, updated.buttons);
} }
if (current.backgrounds.form.fontsDarkMode == undefined) { if(!current.buttons.darkBackground){
current.backgrounds.form.fontsDarkMode = true; current.buttons.darkBackground = Object.assign({}, updated.buttons.darkBackground);
} }
if (!current.buttons) { if(!current.buttons.lightBackground){
current.buttons = Object.assign({}, updated.buttons); current.buttons.lightBackground = Object.assign({}, updated.buttons.lightBackground);
} }
if (!current.buttons.darkBackground) { if(!current.hasOwnProperty('identityIsCustom')){
current.buttons.darkBackground = Object.assign({}, updated.buttons.darkBackground); current.identityIsCustom = (JSON.stringify(current.identity) != JSON.stringify(defaultCO.identity));
} }
if (!current.buttons.lightBackground) { if(!current.hasOwnProperty('backgroundsAndButtonsIsCustom')){
current.buttons.lightBackground = Object.assign({}, updated.buttons.lightBackground); current.identityIsCustom = (JSON.stringify(current.backgrounds) != JSON.stringify(updated.backgrounds) || JSON.stringify(current.buttons) != JSON.stringify(updated.buttons)) ;
}
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));
}
} }
return current; return current;
} }
public static getIdentity(community:string=null){
public static getIdentity(community: string = null) { let COLORS= {
let COLORS = { default:{
default: { mainColor:'#4687E6',
mainColor: '#4687E6',
secondaryColor: '#2D72D6' secondaryColor: '#2D72D6'
}, },
"covid-19": { "covid-19":{
mainColor: "#03ADEE", mainColor:"#03ADEE",
secondaryColor: "#F15157" secondaryColor: "#F15157"
} }
}; };
if (community && COLORS[community]) { if(community && COLORS[community]){
return COLORS[community]; return COLORS[community];
} }
return COLORS.default; return COLORS.default;
} }
public static getRGBA(color, A){
public static getRGBA(color, A) { if(color.indexOf("#")!=-1){
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 'rgba(' + parseInt(color.substring(1, 3), 16) + ',' + parseInt(color.substring(3, 5), 16) + ',' + parseInt(color.substring(5, 7), 16) + ',' + A + ')';
} }
return color; return color;
} }
public static isForLightBackground(color: string) { public static isForLightBackground(color:string){
let L, r, g, b, a = 1; 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); r = parseInt(color.substring(1, 3), 16);
g = parseInt(color.substring(3, 5), 16); g = parseInt(color.substring(3, 5), 16);
b = parseInt(color.substring(5, 7), 16); b = parseInt(color.substring(5, 7), 16);
if (color.length == 9) { if(color.length == 9) {
a = parseInt(color.substring(7, 9), 16); 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(","); let array = color.split("rgba(")[1].split(")")[0].split(",");
r = parseInt(array[0]); r = parseInt(array[0]);
g = parseInt(array[1]); g = parseInt(array[1]);
b = parseInt(array[2]); b = parseInt(array[2]);
a = +array[3]; 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 (brightness < 186)
// return !(r*0.299 + g*0.587 + b*0.114 > 186); // return !(r*0.299 + g*0.587 + b*0.114 > 186);
/*for(let c of [r,g,b]){ /*for(let c of [r,g,b]){
c = c / 255.0; c = c / 255.0;
@ -283,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 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; backgroundColor: string;
color: string; color: string;
borderStyle: string; borderStyle: string;

View File

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

View File

@ -1,5 +1,5 @@
import {StringUtils} from "../../utils/string-utils.class"; import {StringUtils} from "../../utils/string-utils.class";
import {SelectionCriteria} from "../../utils/entities/contentProvider"; import {properties} from "../../../../environments/environment";
export class CommunityInfo { export class CommunityInfo {
title: string; title: string;
@ -13,17 +13,11 @@ export class CommunityInfo {
managers: string[]; managers: string[];
date:Date; date:Date;
subjects: string[]; subjects: string[];
status:"all" | "manager" | "hidden" | "PUBLIC" | "RESTRICTED" | "PRIVATE"; status:string;
claim: "all" | "managersOnly" | "membersOnly";
membership: "open" | "byInvitation";
zenodoCommunity:string; zenodoCommunity:string;
otherZenodoCommunities: string[];
isUpload: boolean; isUpload: boolean;
isSubscribed: boolean; isSubscribed: boolean;
isManager: boolean; isManager: boolean;
fos: string[] = [];
sdg: string[] = []
selectionCriteria: SelectionCriteria;
public static checkIsUpload(response: CommunityInfo | CommunityInfo[]): any | any[] { public static checkIsUpload(response: CommunityInfo | CommunityInfo[]): any | any[] {
if (Array.isArray(response)) { if (Array.isArray(response)) {
@ -35,24 +29,5 @@ export class CommunityInfo {
} }
return response; 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"]; // 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 {filter, map, mergeMap, take} from 'rxjs/operators';
import {Injectable} from '@angular/core'; 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 {Observable, of} from 'rxjs';
import {Session} from '../../login/utils/helper.class'; import {Session} from '../../login/utils/helper.class';
import {LoginErrorCodes} from '../../login/utils/guardHelper.class'; import {LoginErrorCodes} from '../../login/utils/guardHelper.class';
import {UserManagementService} from "../../services/user-management.service"; import {UserManagementService} from "../../services/user-management.service";
@Injectable() @Injectable()
export class ConnectAdminLoginGuard { export class ConnectAdminLoginGuard implements CanActivate, CanActivateChild {
constructor(private router: Router, constructor(private router: Router,
private userManagementService: UserManagementService) { private userManagementService: UserManagementService) {
@ -15,9 +22,8 @@ export class ConnectAdminLoginGuard {
check(community: string, path: string): Observable<boolean> | boolean { check(community: string, path: string): Observable<boolean> | boolean {
let errorCode = LoginErrorCodes.NOT_LOGIN; 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) { if (user) {
errorCode = LoginErrorCodes.NOT_ADMIN;
if (Session.isPortalAdministrator(user) || Session.isCommunityCurator(user) || Session.isManager('community', community, user)) { if (Session.isPortalAdministrator(user) || Session.isCommunityCurator(user) || Session.isManager('community', community, user)) {
return of(true); return of(true);
} }

View File

@ -22,7 +22,7 @@ export class ConnectCommunityGuard implements CanActivate, CanActivateChild {
check(community: string, url: string): Observable<boolean> | boolean { check(community: string, url: string): Observable<boolean> | boolean {
return this.communityService.isCommunityType(community).pipe(take(1), tap(isCommunity => { return this.communityService.isCommunityType(community).pipe(take(1), tap(isCommunity => {
if (!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'; } from '@angular/router';
import {Observable, Subscription} from 'rxjs'; import {Observable, Subscription} from 'rxjs';
import {CommunityService} from '../community/community.service'; import {CommunityService} from '../community/community.service';
import {properties} from "../../../../environments/environment";
@Injectable() @Injectable()
export class ConnectRIGuard implements CanActivate, CanActivateChild { export class ConnectRIGuard implements CanActivate, CanActivateChild {
@ -23,7 +22,7 @@ export class ConnectRIGuard implements CanActivate, CanActivateChild {
check(community: string, url: string): Observable<boolean> | boolean { check(community: string, url: string): Observable<boolean> | boolean {
return this.communityService.isRIType(community).pipe(tap(authorized => { return this.communityService.isRIType(community).pipe(tap(authorized => {
if (!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 { } else {
community = ConnectHelper.getCommunityFromDomain(properties.domain); 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 (user) {
if (Session.isSubscribedTo('community', community, user)) { if (Session.isSubscribedTo('community', community, user)) {
return of(true); return of(true);

View File

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

View File

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

View File

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

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 ) {} constructor(private http: HttpClient ) {}
getUserEmailPreferencesForCommunity (communityId:string, apiUrl:string):any { 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 { 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) { saveUserEmailPreferences (notification: any, apiUrl: string) {
let body = JSON.stringify(notification); let url = apiUrl +"users/notification/save";
return this.http.post(apiUrl +"users/notification/save", body, CustomOptions.getAuthOptionsWithBody());
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 { NgModule} from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import {SearchOrcidService} from "./searchOrcid.service";
import {SearchZenodoCommunitiesService} from './searchZenodoCommunities.service';
@NgModule({ @NgModule({
@ -11,9 +13,9 @@ import {SearchOrcidService} from "./searchOrcid.service";
declarations: [ declarations: [
], ],
providers:[ providers:[
SearchOrcidService SearchZenodoCommunitiesService
], ],
exports: [ exports: [
] ]
}) })
export class SearchOrcidServiceModule { } export class SearchZenodoCommunitiesServiceModule { }

View File

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

View File

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

View File

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

View File

@ -1,105 +1,108 @@
<div page-content> <div page-content class="admin-pages">
<div header> <div header>
<admin-tabs tab="class"></admin-tabs> <admin-tabs tab="class" header></admin-tabs>
<ul class="uk-subnav uk-subnav-pill uk-margin-medium-top"> <div *ngIf="!showLoading" class="uk-grid" uk-grid>
<li [class.uk-active]="filterForm.get('type').value === 'all'" class="uk-margin-small-bottom"><a <div class="uk-width-1-1">
(click)="filterForm.get('type').setValue('all')"><span <ul class="uk-subnav uk-subnav-pill">
class="title">All portals</span></a></li> <li [class.uk-active]="filterForm.get('type').value === 'all'" class="uk-margin-small-bottom"><a
<li *ngFor="let type of portalUtils.portalTypes; let i=index" (click)="filterForm.get('type').setValue('all')"><span
[class.uk-active]="filterForm.get('type').value === type.value" class="uk-margin-small-bottom"><a class="title">All portals</span></a></li>
(click)="filterForm.get('type').setValue(type.value)"><span <li *ngFor="let type of portalUtils.portalTypes; let i=index"
class="title">{{type.label}}</span></a></li> [class.uk-active]="filterForm.get('type').value === type.value" class="uk-margin-small-bottom"><a
</ul> (click)="filterForm.get('type').setValue(type.value)"><span
</div> class="title">{{type.label}}</span></a></li>
<div actions> </ul>
<div class="uk-section-xsmall"> </div>
<div class="uk-flex uk-flex-right@m uk-flex-center uk-flex-wrap uk-flex-middle uk-grid" uk-grid> <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 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> <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> <div>
<button class="uk-button uk-button-default uk-flex uk-flex-middle" (click)="newDivId()" <a (click)="newDivId()"
[disabled]="showLoading" [class.uk-disabled]="showLoading"> class="uk-flex uk-flex-middle uk-text-uppercase">
<icon name="add" [flex]="true"></icon> <button class="large uk-icon-button uk-button-secondary">
<span class="uk-margin-small-left uk-text-bold uk-text-uppercase">Add class</span> <icon name="add"></icon>
</button> </button>
<button class="uk-button uk-button-link uk-margin-small-left uk-text-secondary">Add class</button>
</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div inner> <div inner>
<div class="uk-section uk-section-small uk-position-relative" style="min-height: 60vh"> <div *ngIf="showLoading" class="uk-position-center">
<div *ngIf="showLoading" class="uk-position-center"> <loading></loading>
<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> </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> </div>
</div> </div>
<modal-alert #editModal (alertOutput)="divIdSaveConfirmed($event)" <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> <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 dashboard-input [formInput]="classForm.get('name')"
<div input [formInput]="classForm.get('pages')" placeholder="Pages" [options]="allPages" type="chips"></div> type="text" label="Class Name" placeholder="Write a name">
<div input [formInput]="classForm.get('portalType')" placeholder="Portal Type" [options]="portalUtils.portalTypes" type="select"></div> </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> </form>
</modal-alert> </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 {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from "@angular/router"; import {ActivatedRoute, Router} from "@angular/router";
import {HelpContentService} from "../../services/help-content.service"; 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 {CheckDivId, DivId} from "../../utils/entities/adminTool/divId";
import {Page} from "../../utils/entities/adminTool/page"; import {Page} from "../../utils/entities/adminTool/page";
import {EnvProperties} from '../../utils/properties/env-properties'; import {EnvProperties} from '../../utils/properties/env-properties';
@ -11,39 +11,42 @@ import {properties} from "../../../../environments/environment";
import {PortalUtils} from "../portal/portalHelper"; import {PortalUtils} from "../portal/portalHelper";
import {AlertModal} from "../../utils/modal/alert"; import {AlertModal} from "../../utils/modal/alert";
import {Option} from "../../sharedComponents/input/input.component"; import {Option} from "../../sharedComponents/input/input.component";
import {SearchInputComponent} from "../../sharedComponents/search-input/search-input.component";
import {Title} from "@angular/platform-browser"; import {Title} from "@angular/platform-browser";
import {ClearCacheService} from "../../services/clear-cache.service";
import {NotificationHandler} from "../../utils/notification-handler"; declare var UIkit;
@Component({ @Component({
selector: 'divIds', selector: 'divIds',
templateUrl: './divIds.component.html', templateUrl: './divIds.component.html',
}) })
export class DivIdsComponent implements OnInit { export class DivIdsComponent implements OnInit {
@ViewChild('editModal') editModal: AlertModal; @ViewChild('editModal') editModal: AlertModal;
@ViewChild('deleteModal') deleteModal: AlertModal; @ViewChild('deleteModal') deleteModal: AlertModal;
private selectedDivIds: string[] = []; private selectedDivIds: string[] = [];
public checkboxes: CheckDivId[] = []; public checkboxes: CheckDivId[] = [];
public divIds: DivId[] = []; public divIds: DivId[] = [];
public classForm: UntypedFormGroup; public classForm: FormGroup;
public pagesCtrl: UntypedFormArray; public pagesCtrl: FormArray;
private searchText: RegExp = new RegExp(''); private searchText: RegExp = new RegExp('');
public keyword: string = ""; public keyword: string = "";
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public formPages: Page[] = []; public formPages: Page[] = [];
public showLoading: boolean = true; public showLoading: boolean = true;
public filterForm: UntypedFormGroup; public filterForm: FormGroup;
private subscriptions: any[] = []; private subscriptions: any[] = [];
public allPages: Option[] = []; public allPages: Option[] = [];
selectedCommunityPid = null; selectedCommunityPid = null;
public portalUtils: PortalUtils = new PortalUtils(); public portalUtils: PortalUtils = new PortalUtils();
private index: number; private index: number;
public selectedKeyword: string;
@ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent;
constructor(private element: ElementRef, private route: ActivatedRoute, private _router: Router, constructor(private element: ElementRef, private route: ActivatedRoute, private _router: Router,
private title: Title, private title: Title,
private _helpContentService: HelpContentService, private _fb: UntypedFormBuilder, private _helpContentService: HelpContentService, private _fb: FormBuilder) {
private _clearCacheService: ClearCacheService) {
} }
ngOnInit() { ngOnInit() {
@ -130,6 +133,8 @@ export class DivIdsComponent implements OnInit {
} }
private confirmModalOpen() { private confirmModalOpen() {
this.deleteModal.cancelButton = true;
this.deleteModal.okButton = true;
this.deleteModal.alertTitle = "Delete Confirmation"; this.deleteModal.alertTitle = "Delete Confirmation";
this.deleteModal.message = "Are you sure you want to delete the selected class(es)?"; this.deleteModal.message = "Are you sure you want to delete the selected class(es)?";
this.deleteModal.okButtonText = "Yes"; this.deleteModal.okButtonText = "Yes";
@ -141,9 +146,12 @@ export class DivIdsComponent implements OnInit {
this.subscriptions.push(this._helpContentService.deleteDivIds(this.selectedDivIds, this.properties.adminToolsAPIURL).subscribe( this.subscriptions.push(this._helpContentService.deleteDivIds(this.selectedDivIds, this.properties.adminToolsAPIURL).subscribe(
_ => { _ => {
this.deleteDivIdsFromArray(this.selectedDivIds); 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.showLoading = false;
this._clearCacheService.clearCache("Class ids deleted");
}, },
error => this.handleUpdateError('System error deleting the selected classes', error) 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) { private divIdsModalOpen(title: string, yesBtn: string) {
this.editModal.cancelButton = true;
this.editModal.okButton = true;
this.editModal.okButtonLeft = false; this.editModal.okButtonLeft = false;
this.editModal.alertTitle = title; this.editModal.alertTitle = title;
this.editModal.okButtonText = yesBtn; this.editModal.okButtonText = yesBtn;
@ -190,21 +200,28 @@ export class DivIdsComponent implements OnInit {
public divIdSaveConfirmed(data: any) { public divIdSaveConfirmed(data: any) {
this.showLoading = true; this.showLoading = true;
if (!this.classForm.getRawValue()._id) { if (!this.classForm.value._id) {
this.subscriptions.push(this._helpContentService.saveDivId(<DivId>this.classForm.getRawValue(), this.properties.adminToolsAPIURL).subscribe( this.subscriptions.push(this._helpContentService.saveDivId(<DivId>this.classForm.value, this.properties.adminToolsAPIURL).subscribe(
divId => { divId => {
this.divIdSavedSuccessfully(divId); this.divIdSavedSuccessfully(divId);
NotificationHandler.rise('Class <b>' + divId.name + '</b> has been <b>successfully created</b>'); UIkit.notification('Class <b>' + divId.name + '</b> has been <b>successfully created</b>', {
this._clearCacheService.clearCache("Class id saved"); status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
}, },
error => this.handleUpdateError("System error creating class", error) error => this.handleUpdateError("System error creating class", error)
)); ));
} else { } else {
this.subscriptions.push(this._helpContentService.updateDivId(<DivId>this.classForm.getRawValue(), this.properties.adminToolsAPIURL).subscribe( this.classForm.get('portalType').enable();
this.subscriptions.push(this._helpContentService.updateDivId(<DivId>this.classForm.value, this.properties.adminToolsAPIURL).subscribe(
divId => { divId => {
this.divIdUpdatedSuccessfully(divId); this.divIdUpdatedSuccessfully(divId);
NotificationHandler.rise('Class <b>' + divId.name + '</b> has been <b>successfully updated</b>'); UIkit.notification('Class <b>' + divId.name + '</b> has been <b>successfully updated</b>', {
this._clearCacheService.clearCache("Class id updated"); status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
}, },
error => this.handleUpdateError("System error updating class", error) error => this.handleUpdateError("System error updating class", error)
)); ));
@ -240,22 +257,31 @@ export class DivIdsComponent implements OnInit {
} }
public filterDivIds(divId: DivId): boolean { 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) { handleUpdateError(message: string, error) {
if (error) { if (error == null) {
// this.formComponent.reset();
} else {
UIkit.notification(message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
console.log('Server responded: ' + error); console.log('Server responded: ' + error);
} }
NotificationHandler.rise(message,'danger');
this.showLoading = false; this.showLoading = false;
} }
handleError(message: string, error = null) { handleError(message: string, error) {
if (error) { UIkit.notification(message, {
console.log('Server responded: ' + error); status: 'danger',
} timeout: 6000,
NotificationHandler.rise(message,'danger'); pos: 'bottom-right'
});
console.log('Server responded: ' + error);
this.showLoading = false; this.showLoading = false;
} }
@ -275,4 +301,13 @@ export class DivIdsComponent implements OnInit {
error => this.handleError('System error retrieving pages', error) 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 {DivIdsComponent} from './divIds.component';
import {AdminToolServiceModule} from "../../services/adminToolService.module"; import {AdminToolServiceModule} from "../../services/adminToolService.module";
import {InputModule} from "../../sharedComponents/input/input.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 {AdminTabsModule} from "../sharedComponents/admin-tabs/admin-tabs.module";
import {PageContentModule} from "../sharedComponents/page-content/page-content.module"; import {PageContentModule} from "../sharedComponents/page-content/page-content.module";
import {ClassesRoutingModule} from "./classes-routing.module"; import {ClassesRoutingModule} from "./classes-routing.module";
import {SearchInputModule} from "../../sharedComponents/search-input/search-input.module"; import {SearchInputModule} from "../../sharedComponents/search-input/search-input.module";
import {IconsModule} from "../../utils/icons/icons.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"; import {LoadingModule} from "../../utils/loading/loading.module";
@NgModule({ @NgModule({
imports: [ imports: [
ClassesRoutingModule,
CommonModule, RouterModule, FormsModule, CommonModule, RouterModule, FormsModule,
AlertModalModule, ReactiveFormsModule, AdminToolServiceModule, InputModule, AlertModalModule, ReactiveFormsModule, AdminToolServiceModule, InputModule, MatAutocompleteModule, MatFormFieldModule, MatChipsModule,
AdminTabsModule, PageContentModule, SearchInputModule, IconsModule, LoadingModule MatCheckboxModule, AdminTabsModule, PageContentModule, ClassesRoutingModule, SearchInputModule, IconsModule, LoadingModule
], ],
declarations: [DivIdsComponent], declarations: [DivIdsComponent],
exports: [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 page-content>
<div header> <div header>
<div class="uk-section-xsmall uk-margin-top uk-container"> <div class="uk-margin-top">
<div class="uk-flex-middle uk-grid" uk-grid> <a routerLink="../" [queryParams]=" { 'pageId': pageId }"
<div class="uk-width-expand"> class="uk-text-secondary uk-text-uppercase uk-text-bold uk-text-small">
<a routerLink="../" [queryParams]=" { 'pageId': pageId }" class="uk-flex uk-flex-middle uk-h5 uk-link-reset"> <span class="uk-icon-button uk-icon small uk-button-secondary">
<span class="uk-margin-right"> <icon name="arrow_left"></icon>
<icon name="west" ratio="1.7" [flex]="true"></icon> </span>
</span> <span class="space">
<h1 *ngIf="page" class="uk-h5 uk-margin-remove"> Go back to class help texts list
{{page.name}} - {{pageHelpContent ? 'Update ' : 'Add new '}} class help text </span>
<span *ngIf="myForm.dirty" class="uk-text-large"> (unsaved changes)</span> </a>
</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> </div>
</div> </div>
<div inner> <div inner>
<div class="uk-container"> <div class="uk-card-header">
<div *ngIf="myForm" style="min-height: 60vh" <div class="uk-flex uk-flex-middle uk-child-width-1-1 uk-child-width-1-2@m uk-grid" uk-grid>
class="uk-section uk-section-small uk-position-relative"> <div>
<div *ngIf="showLoading" class="uk-position-center"> <div class="uk-text-small uk-text-muted"> {{pageHelpContent ? 'Update ' : 'Add new '}} class help text</div>
<loading *ngIf="showLoading"></loading> <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> </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>
<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> </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 {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 {Page} from '../../utils/entities/adminTool/page';
import {HelpContentService} from '../../services/help-content.service'; import {HelpContentService} from '../../services/help-content.service';
import {EnvProperties} from '../../utils/properties/env-properties'; 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 {properties} from '../../../../environments/environment';
import {Subscriber, Subscription, zip} from 'rxjs'; import {Subscriber, Subscription, zip} from 'rxjs';
import {HelperFunctions} from '../../utils/HelperFunctions.class';
import {DivHelpContent} from '../../utils/entities/adminTool/div-help-content'; import {DivHelpContent} from '../../utils/entities/adminTool/div-help-content';
import {NotificationHandler} from "../../utils/notification-handler";
import {ClearCacheService} from "../../services/clear-cache.service"; declare var UIkit;
import {CKEditorComponent} from "ng2-ckeditor";
@Component({ @Component({
selector: 'class-content-form', selector: 'class-content-form',
templateUrl: './class-help-content-form.component.html', templateUrl: './class-help-content-form.component.html',
}) })
export class ClassContentFormComponent implements OnInit { export class ClassContentFormComponent implements OnInit {
myForm: UntypedFormGroup; myForm: FormGroup;
portal: string; portal: string;
parentClass: string;
pageId: string; pageId: string;
pageContentId: string; pageContentId: string;
page: Page; page: Page;
classOptions = []; classOptions = [];
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public showLoading: boolean = true; public showLoading: boolean = true;
public errorMessage: string = '';
@Input() updateErrorMessage: string = '';
private subs: Subscription[] = []; private subs: Subscription[] = [];
public pageHelpContent: DivHelpContent; public pageHelpContent: DivHelpContent;
@ViewChild('ckEditor') ckEditor: CKEditorComponent;
constructor(private route: ActivatedRoute, private _router: Router, private _fb: FormBuilder, private _helpContentService: HelpContentService) {
constructor(private route: ActivatedRoute, private _router: Router, private _fb: UntypedFormBuilder,
private cdr: ChangeDetectorRef, private _helpContentService: HelpContentService,
private _clearCacheService: ClearCacheService) {
} }
ngOnInit() { ngOnInit() {
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.params.subscribe(params => {
this.parentClass = this.route.snapshot.data.parentClass; 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.subs.push(this.route.queryParams.subscribe(params => {
this.pageId = params['pageId']; this.pageId = params['pageId'];
this.myForm = this.form; this.myForm = this.form;
this.pageContentId = params['pageContentId']; this.pageContentId = params['pageContentId'];
if (!this.pageId) { if (!this.pageId) {
this._router.navigate(['../'], {relativeTo: this.route}); this._router.navigate(['../'], {relativeTo: this.route});
} }
this.getInfo(this.pageId); this.getInfo(this.pageId);
}));
})); }));
} }
ngOnDestroy() { ngOnDestroy() {
this.subs.forEach(value => { this.subs.forEach(value => {
if (value instanceof Subscriber) { if (value instanceof Subscriber) {
@ -56,7 +58,7 @@ export class ClassContentFormComponent implements OnInit {
} }
}); });
} }
getInfo(pageId: string) { getInfo(pageId: string) {
this.showLoading = true; this.showLoading = true;
let obs = zip(this._helpContentService.getPageByPortal(pageId, this.properties.adminToolsAPIURL, this.portal), let obs = zip(this._helpContentService.getPageByPortal(pageId, this.properties.adminToolsAPIURL, this.portal),
@ -69,44 +71,25 @@ export class ClassContentFormComponent implements OnInit {
} }
this.setOptions(results[1]); this.setOptions(results[1]);
if (!this.pageContentId) { if (!this.pageContentId) {
this.updateForm(null); this.updateForm(null);
this.showLoading = false; this.showLoading = false;
this.initCKEditor();
} else { } else {
this.subs.push(this._helpContentService.getDivHelpContent(this.pageContentId, this.properties.adminToolsAPIURL, this.portal).subscribe(pageHelpContent => { this.subs.push(this._helpContentService.getDivHelpContent( this.pageContentId, this.properties.adminToolsAPIURL, this.portal).subscribe(pageHelpContent=>{
this.pageHelpContent = pageHelpContent; this.pageHelpContent = pageHelpContent;
if (this.properties.adminToolsPortalType != this.page.portalType) { if (this.properties.adminToolsPortalType != this.page.portalType) {
this._router.navigate(['../'], {relativeTo: this.route}); this._router.navigate(['../'], {relativeTo: this.route});
} }
this.updateForm(this.pageHelpContent); this.updateForm(this.pageHelpContent);
this.showLoading = false; this.showLoading = false;
this.initCKEditor(); },
},
error => { 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) { private updateForm(pageHelpContent: DivHelpContent) {
this.pageHelpContent = pageHelpContent; this.pageHelpContent = pageHelpContent;
this.myForm = this.form; this.myForm = this.form;
@ -115,64 +98,78 @@ export class ClassContentFormComponent implements OnInit {
this.myForm.get('divId').disable(); this.myForm.get('divId').disable();
} }
this.myForm.markAsPristine(); this.myForm.markAsPristine();
} }
public setOptions(divIds) { public setOptions(divIds) {
this.classOptions = []; this.classOptions = [];
for (let divid of divIds) { for(let divid of divIds){
this.classOptions.push({label: divid.name, value: divid._id}); this.classOptions.push({label:divid.name, value:divid._id});
} }
} }
public get form() { public get form() {
return this._fb.group({ return this._fb.group({
divId: ['', Validators.required], divId: ['', Validators.required],
content: ['', Validators.required], content: ['', Validators.required],
isActive: true, isActive: true,
portal: this.portal, portal: this.portal,
_id: '', _id : '',
}); });
} }
public reset() { public reset() {
this.myForm.patchValue({ this.myForm.patchValue({
divId: ['', Validators.required], divId: ['', Validators.required],
content: ['', Validators.required], content: ['', Validators.required],
isActive: true, isActive: true,
portal: '', portal: '',
_id: '', _id : '',
}); });
this.myForm.markAsPristine(); this.myForm.markAsPristine();
} }
handleError(message: string, error = null) { handleError(message: string, error) {
if (error) { this.errorMessage = message;
console.error('Server responded: ' + error); console.error('Server responded: ' + error);
}
NotificationHandler.rise(message, 'danger');
this.showLoading = false; this.showLoading = false;
} }
public saveCustom() { public saveCustom() {
if (this.myForm.valid) { if (!Session.isLoggedIn()) {
this.showLoading = true; this._router.navigate(['/user-info'], {
let pageHelpContent: DivHelpContent = this.myForm.getRawValue(); queryParams: {
this.subs.push(this._helpContentService.insertOrUpdateDivHelpContent(pageHelpContent, this.properties.adminToolsAPIURL, this.portal).subscribe( "errorCode": LoginErrorCodes.NOT_VALID,
_ => { "redirectUrl": this._router.url
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.clearCache("Class help text saved or updated");
},
err => this.handleUpdateError('System error saving page content', err)
));
} else { } 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.updateForm(this.pageHelpContent);
this.showLoading = false; this.showLoading = false;
} }
handleUpdateError(message: string, error) { handleUpdateError(message: string, error) {
this.updateErrorMessage = message;
console.error('Server responded: ' + error); console.error('Server responded: ' + error);
NotificationHandler.rise(message, 'danger');
this.showLoading = false; this.showLoading = false;
} }
changeStatus() { changeStatus() {
this.myForm.get('isActive').setValue(!this.myForm.get('isActive').value); 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) { 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() this.myForm.get('isActive').markAsPristine()
} }
} }
contentChanged() { contentChanged() {
if (this.pageHelpContent && this.myForm.get('content').value != this.pageHelpContent.content || !this.pageHelpContent && this.myForm.get('content').value != '') { if (this.pageHelpContent && this.myForm.get('content').value != this.pageHelpContent.content || !this.pageHelpContent && this.myForm.get('content').value != '') {
this.myForm.get('content').markAsDirty(); 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 {IconsModule} from '../../utils/icons/icons.module';
import {RouterModule} from '@angular/router'; import {RouterModule} from '@angular/router';
import {LoadingModule} from '../../utils/loading/loading.module'; 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 {ClassContentFormComponent} from './class-help-content-form.component';
import {ClassHelpContentFormRoutingModule} from './class-help-content-form-routing.module'; import {ClassHelpContentFormRoutingModule} from './class-help-content-form-routing.module';
import {PageContentModule} from '../sharedComponents/page-content/page-content.module'; import {PageContentModule} from '../sharedComponents/page-content/page-content.module';
@NgModule({ @NgModule({
imports: [ imports: [
ClassHelpContentFormRoutingModule,
CommonModule, FormsModule, RouterModule, CommonModule, FormsModule, RouterModule,
SafeHtmlPipeModule, CKEditorModule, SafeHtmlPipeModule, CKEditorModule,
AlertModalModule, ReactiveFormsModule, AdminToolServiceModule, InputModule, MatSlideToggleModule, IconsModule, LoadingModule, PageContentModule AlertModalModule, ReactiveFormsModule, ClassHelpContentFormRoutingModule, AdminToolServiceModule, InputModule, MatSlideToggleModule, IconsModule, LoadingModule, PageContentModule
], ],
declarations: [ declarations: [
ClassContentFormComponent ClassContentFormComponent
], ],
exports: [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 page-content>
<div header> <div header>
<div class="uk-section-xsmall uk-margin-top"> <div class="uk-text-bold">
<div class="uk-flex-middle uk-grid" uk-grid> <span *ngIf="selectedPageId && page">{{page.name}}</span>
<div class="uk-width-expand"> </div>
<a routerLink="../pages" class="uk-flex uk-flex-middle uk-h5 uk-link-reset"> <div class="uk-margin-top">
<span class="uk-margin-right"> <a routerLink="../pages/" class="uk-text-secondary uk-text-uppercase uk-text-bold uk-text-small">
<icon name="west" ratio="1.7" [flex]="true"></icon> <span class="uk-icon-button small uk-icon uk-button-secondary">
</span> <icon name="arrow_left"></icon>
<h1 *ngIf="page" class="uk-h5 uk-margin-remove">{{page.name}}</h1> </span>
</a> <span class="space">
</div> Back to pages list
<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"> </span>
</div> </a>
<div> </div>
<button (click)="newPageContent()" [disabled]="showLoading" [class.uk-disabled]="showLoading" <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>
class="uk-flex uk-flex-middle uk-button uk-button-default"> <div #searchInputComponent search-input [control]="filterForm" [showSearch]="false" placeholder="Search helptext"
<icon [flex]="true" name="add"></icon> [selected]="selectedKeyword" (closeEmitter)="onSearchClose()" (resetEmitter)="reset()"
<span class="uk-margin-small-left">Add class help text</span> [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> </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>
</div> </div>
<div inner> <div inner>
<div class="uk-section uk-section-small uk-position-relative" style="min-height: 60vh"> <div *ngIf="showLoading" class="uk-position-center">
<div *ngIf="showLoading" class="uk-position-center"> <loading></loading>
<loading></loading> </div>
</div> <div *ngIf="!showLoading">
<ng-container *ngIf="!showLoading"> <div *ngIf="checkboxes.length > 0" class="uk-margin-medium-bottom">
<div *ngIf="checkboxes.length == 0" <ul class="uk-list pages">
class="uk-card uk-card-default uk-padding-large uk-text-center uk-text-bold"> <li *ngFor="let check of checkboxes; let i=index" class="uk-card uk-card-default uk-margin-bottom">
<div>No class help texts found</div> <div class="uk-grid uk-grid-divider uk-padding" uk-grid>
</div> <div class="uk-width-4-5 uk-first-column ">
<div *ngIf="checkboxes.length > 0"> <div class="uk-grid uk-flex uk-flex-middle">
<div class="uk-grid uk-child-width-1-2@l uk-child-width-1-1" uk-height-match=".uk-card-body" uk-grid> <div><input id="{{check.divHelpContent._id}}" class="checkBox" type="checkbox"
<div *ngFor="let check of checkboxes; let i=index"> name="entitiescb[]" value="{{check.divHelpContent._id}}"
<div class="uk-card uk-card-default uk-margin-bottom"> [(ngModel)]="check.checked">
<div class="uk-card-body"> </div>
<div class="uk-margin-medium-bottom"> <div class="uk-width-expand uk-margin-medium-bottom">
<div class="multi-line-ellipsis lines-2">
<p>{{check.divHelpContent.content | htmlToString}}</p> <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>
<div class="uk-text-small"> <div class=" ">
<span class="uk-text-meta">Class: </span>{{check.divHelpContent.divId.name ? check.divHelpContent.divId.name : check.divHelpContent.divId}} <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>
</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> <div class="uk-width-1-5 uk-first-column">
<div class="uk-padding-small uk-padding-remove-horizontal">
<mat-slide-toggle [checked]="check.divHelpContent.isActive" <div class=" uk-flex-center uk-flex">
(change)="($event.source.checked = check.divHelpContent.isActive);togglePageHelpContents(!check.divHelpContent.isActive,[check.divHelpContent._id])" <div class="actions" href="#">
uk-tooltip="title:<div><div class='uk-text-bold '> Enable or disable help text to show or hide it from the dashboard</div></div>"> <button (click)="editPageHelpContent(check.divHelpContent._id)" class="uk-button action uk-margin-top uk-flex uk-flex-middle">
<span class="uk-text-small">Enable</span> <icon name="edit"></icon>
</mat-slide-toggle> <span class="uk-margin-small-left">Edit</span>
</div> </button>
</div> <button (click)="confirmDeletePageHelpContent(check.divHelpContent._id)"
<div><div class="uk-padding-small uk-padding-remove-horizontal"> class="uk-button action uk-margin-top uk-flex uk-flex-middle">
<button class="uk-button uk-button-link uk-flex uk-flex-middle" (click)="editPageHelpContent(check.divHelpContent._id)"> <icon name="remove"></icon>
<icon name="edit" [flex]="true"></icon> <span class="uk-margin-small-left">Delete</span>
<span class="uk-margin-xsmall-left"> Edit</span> </button>
</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>
</div> </div>
</div> </div>
</div> </div>
</div> </li>
</div> </ul>
</ng-container> </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> </div>
</div> </div>
<modal-alert #AlertModalDeletePageHelpContents [overflowBody]="false" classTitle="uk-background-primary uk-light" <modal-alert #AlertModalDeletePageHelpContents (alertOutput)="confirmedDeletePageHelpContents($event)"></modal-alert>
(alertOutput)="confirmedDeletePageHelpContents($event)"></modal-alert>

View File

@ -1,5 +1,5 @@
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {UntypedFormBuilder, UntypedFormControl, UntypedFormGroup} from '@angular/forms'; import {FormBuilder, FormControl, FormGroup} from '@angular/forms';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {HelpContentService} from '../../services/help-content.service'; import {HelpContentService} from '../../services/help-content.service';
import {PageHelpContentFilterOptions} from '../../utils/entities/adminTool/page-help-content'; import {PageHelpContentFilterOptions} from '../../utils/entities/adminTool/page-help-content';
@ -14,8 +14,9 @@ import {properties} from '../../../../environments/environment';
import {DomSanitizer} from '@angular/platform-browser'; import {DomSanitizer} from '@angular/platform-browser';
import {SearchInputComponent} from '../../sharedComponents/search-input/search-input.component'; import {SearchInputComponent} from '../../sharedComponents/search-input/search-input.component';
import {CheckDivHelpContent, DivHelpContent} from '../../utils/entities/adminTool/div-help-content'; import {CheckDivHelpContent, DivHelpContent} from '../../utils/entities/adminTool/div-help-content';
import {ClearCacheService} from "../../services/clear-cache.service";
import {NotificationHandler} from "../../utils/notification-handler"; declare var UIkit;
@Component({ @Component({
selector: 'class-help-contents', selector: 'class-help-contents',
@ -26,7 +27,7 @@ export class ClassHelpContentsComponent implements OnInit {
private selectedPageContents: string[] = []; private selectedPageContents: string[] = [];
public checkboxes: CheckDivHelpContent[] = []; public checkboxes: CheckDivHelpContent[] = [];
public divHelpContents: DivHelpContent[] = []; public divHelpContents: DivHelpContent[] = [];
public formGroup: UntypedFormGroup; public formGroup: FormGroup;
public pages: Page[]; public pages: Page[];
public checkboxAll: boolean = false; public checkboxAll: boolean = false;
public filters: PageHelpContentFilterOptions = {id: '', active: null, text: new RegExp('')}; public filters: PageHelpContentFilterOptions = {id: '', active: null, text: new RegExp('')};
@ -39,12 +40,12 @@ export class ClassHelpContentsComponent implements OnInit {
public page: Page; public page: Page;
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public showLoading: boolean = true; public showLoading: boolean = true;
public filterForm: UntypedFormControl; public filterForm: FormControl;
private subscriptions: any[] = []; private subscriptions: any[] = [];
public selectedKeyword: string;
@ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent;
constructor(private element: ElementRef, private route: ActivatedRoute, private router: Router, constructor(private element: ElementRef, private route: ActivatedRoute, private router: Router, private _helpService: HelpContentService, private _fb: FormBuilder, private sanitizer: DomSanitizer) {
private _helpService: HelpContentService, private _fb: UntypedFormBuilder, private sanitizer: DomSanitizer,
private _clearCacheService: ClearCacheService) {
} }
ngOnInit() { ngOnInit() {
@ -141,9 +142,17 @@ export class ClassHelpContentsComponent implements OnInit {
this.confirmModalOpen(); this.confirmModalOpen();
} }
public confirmDeleteSelectedPageHelpContents() {
this.selectedPageContents = this.getSelectedPageHelpContents();
this.confirmModalOpen();
}
private confirmModalOpen() { private confirmModalOpen() {
this.alertModalDeletePageHelpContents.cancelButton = true;
this.alertModalDeletePageHelpContents.okButton = true;
this.alertModalDeletePageHelpContents.alertTitle = 'Delete Confirmation'; this.alertModalDeletePageHelpContents.alertTitle = 'Delete Confirmation';
this.alertModalDeletePageHelpContents.message = 'Are you sure you want to delete the selected class help text?'; this.alertModalDeletePageHelpContents.message = 'Are you sure you want to delete the selected page content(s)?';
this.alertModalDeletePageHelpContents.okButtonText = 'Yes'; this.alertModalDeletePageHelpContents.okButtonText = 'Yes';
this.alertModalDeletePageHelpContents.open(); this.alertModalDeletePageHelpContents.open();
} }
@ -153,9 +162,12 @@ export class ClassHelpContentsComponent implements OnInit {
this.subscriptions.push(this._helpService.deleteDivHelpContents(this.selectedPageContents, this.properties.adminToolsAPIURL, this.portal).subscribe( this.subscriptions.push(this._helpService.deleteDivHelpContents(this.selectedPageContents, this.properties.adminToolsAPIURL, this.portal).subscribe(
_ => { _ => {
this.deletePageHelpContentsFromArray(this.selectedPageContents); this.deletePageHelpContentsFromArray(this.selectedPageContents);
NotificationHandler.rise('Page content(s) has been <b>successfully deleted</b>'); UIkit.notification('Page content(s) has been <b>successfully deleted</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
this.showLoading = false; this.showLoading = false;
this._clearCacheService.clearCache("Class text texts deleted");
}, },
error => this.handleUpdateError('System error deleting the selected page content(s)', error) error => this.handleUpdateError('System error deleting the selected page content(s)', error)
)); ));
@ -189,19 +201,31 @@ export class ClassHelpContentsComponent implements OnInit {
} }
public togglePageHelpContents(status: boolean, ids: string[]) { public togglePageHelpContents(status: boolean, ids: string[]) {
this.subscriptions.push(this._helpService.toggleDivHelpContents(ids, status, this.properties.adminToolsAPIURL, this.portal).subscribe( if (!Session.isLoggedIn()) {
() => { this.router.navigate(['/user-info'], {
for (let id of ids) { queryParams: {
let i = this.checkboxes.findIndex(_ => _.divHelpContent._id == id); 'errorCode': LoginErrorCodes.NOT_VALID,
this.checkboxes[i].divHelpContent.isActive = status; 'redirectUrl': this.router.url
} }
this.countClassHelpContents(); });
this.applyCheck(false); } else {
NotificationHandler.rise('Page content(s) has been <b>successfully updated</b>'); this.subscriptions.push(this._helpService.toggleDivHelpContents(ids, status, this.properties.adminToolsAPIURL, this.portal).subscribe(
this._clearCacheService.clearCache("class help text's status changed"); () => {
}, for (let id of ids) {
error => this.handleUpdateError('System error changing the status of the selected page content(s)', error) let i = this.checkboxes.findIndex(_ => _.divHelpContent._id == id);
)); this.checkboxes[i].divHelpContent.isActive = status;
}
this.countClassHelpContents();
this.applyCheck(false);
UIkit.notification('Page content(s) has been <b>successfully updated</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
},
error => this.handleUpdateError('System error changing the status of the selected page content(s)', error)
));
}
} }
@ -226,19 +250,23 @@ export class ClassHelpContentsComponent implements OnInit {
this.applyFilter(); this.applyFilter();
} }
handleError(message: string, error = null) { handleError(message: string, error) {
if(error) { UIkit.notification(message, {
console.log('Server responded: ' + error); status: 'danger',
} timeout: 6000,
NotificationHandler.rise(message, 'danger'); pos: 'bottom-right'
});
console.log('Server responded: ' + error);
this.showLoading = false; this.showLoading = false;
} }
handleUpdateError(message: string, error = null) { handleUpdateError(message: string, error) {
if(error) { UIkit.notification(message, {
console.log('Server responded: ' + error); status: 'danger',
} timeout: 6000,
NotificationHandler.rise(message, 'danger'); pos: 'bottom-right'
});
console.log('Server responded: ' + error);
this.showLoading = false; this.showLoading = false;
} }
@ -250,6 +278,15 @@ export class ClassHelpContentsComponent implements OnInit {
}); });
} }
public onSearchClose() {
this.selectedKeyword = this.filterForm.value;
}
public reset() {
this.selectedKeyword = null;
this.searchInputComponent.reset();
}
selectAll() { selectAll() {
let checked = (this.getSelectedPageHelpContents().length != this.checkboxes.length); let checked = (this.getSelectedPageHelpContents().length != this.checkboxes.length);
for (let check of this.checkboxes) { for (let check of this.checkboxes) {

View File

@ -6,11 +6,13 @@ import {ConnectAdminLoginGuard} from '../../connect/communityGuard/connectAdminL
import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {AlertModalModule} from '../../utils/modal/alertModal.module'; import {AlertModalModule} from '../../utils/modal/alertModal.module';
import {SafeHtmlPipeModule} from '../../utils/pipes/safeHTMLPipe.module'; import {SafeHtmlPipeModule} from '../../utils/pipes/safeHTMLPipe.module';
import {MatSlideToggleModule} from '@angular/material/slide-toggle'; import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import {AdminToolServiceModule} from '../../services/adminToolService.module'; import {AdminToolServiceModule} from '../../services/adminToolService.module';
import {InputModule} from '../../sharedComponents/input/input.module'; import {InputModule} from '../../sharedComponents/input/input.module';
import {SearchInputModule} from '../../sharedComponents/search-input/search-input.module'; import {SearchInputModule} from '../../sharedComponents/search-input/search-input.module';
import {IconsModule} from '../../utils/icons/icons.module'; import {IconsModule} from '../../utils/icons/icons.module';
import {IconsService} from '../../utils/icons/icons.service';
import {add, arrow_left, edit, remove} from '../../utils/icons/icons';
import {LoadingModule} from '../../utils/loading/loading.module'; import {LoadingModule} from '../../utils/loading/loading.module';
import {HTMLToStringPipeModule} from '../../utils/pipes/HTMLToStringPipe.module'; import {HTMLToStringPipeModule} from '../../utils/pipes/HTMLToStringPipe.module';
import {ClassHelpContentsRoutingModule} from './class-help-contents-routing.module'; import {ClassHelpContentsRoutingModule} from './class-help-contents-routing.module';
@ -19,9 +21,8 @@ import {PageContentModule} from '../sharedComponents/page-content/page-content.m
@NgModule({ @NgModule({
imports: [ imports: [
ClassHelpContentsRoutingModule,
CommonModule, RouterModule, FormsModule, SafeHtmlPipeModule, CommonModule, RouterModule, FormsModule, SafeHtmlPipeModule,
AlertModalModule, ReactiveFormsModule, MatSlideToggleModule, AdminToolServiceModule, InputModule, AlertModalModule, ReactiveFormsModule, MatSlideToggleModule, AdminToolServiceModule, InputModule, ClassHelpContentsRoutingModule,
SearchInputModule, IconsModule, LoadingModule, HTMLToStringPipeModule, PageContentModule SearchInputModule, IconsModule, LoadingModule, HTMLToStringPipeModule, PageContentModule
], ],
declarations: [ declarations: [
@ -30,4 +31,8 @@ import {PageContentModule} from '../sharedComponents/page-content/page-content.m
providers: [IsCommunity, ConnectAdminLoginGuard], providers: [IsCommunity, ConnectAdminLoginGuard],
exports: [ClassHelpContentsComponent] exports: [ClassHelpContentsComponent]
}) })
export class ClassHelpContentsModule {} export class ClassHelpContentsModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([add, arrow_left, edit, remove])
}
}

View File

@ -1,103 +1,123 @@
<div page-content> <div page-content class="admin-pages">
<div header> <div header>
<admin-tabs tab="entity" [portal]="portal" [type]="type"></admin-tabs> <admin-tabs tab="entity" [portal]="portal"></admin-tabs>
<ul *ngIf="!isPortalAdministrator" class="uk-subnav uk-subnav-pill uk-margin-medium-top"> <div *ngIf="!showLoading" class="uk-grid" uk-grid>
<li [class.uk-active]="filterForm.get('status').value === 'all'"><a <div class="uk-width-1-1">
(click)="filterForm.get('status').setValue('all')"><span <ul *ngIf="!isPortalAdministrator" class="uk-subnav uk-subnav-pill">
class="title">All entities</span></a></li> <li [class.uk-active]="filterForm.get('status').value === 'all'"><a
<li [class.uk-active]="filterForm.get('status').value === 'enabled'"><a (click)="filterForm.get('status').setValue('all')"><span
(click)="filterForm.get('status').setValue('enabled')"><span class="title">Enabled</span></a></li> class="title">All entities</span></a></li>
<li [class.uk-active]="filterForm.get('status').value === 'disabled'"><a <li [class.uk-active]="filterForm.get('status').value === 'enabled'"><a
(click)="filterForm.get('status').setValue('disabled')"><span class="title">Disabled</span></a></li> (click)="filterForm.get('status').setValue('enabled')"><span class="title">Enabled</span></a></li>
</ul> <li [class.uk-active]="filterForm.get('status').value === 'disabled'"><a
</div> (click)="filterForm.get('status').setValue('disabled')"><span class="title">Disabled</span></a></li>
<div actions> </ul>
<div class="uk-section-xsmall"> </div>
<div class="uk-flex uk-flex-right@m uk-flex-center uk-flex-wrap uk-flex-middle uk-grid" uk-grid> <div class="uk-width-1-1 uk-flex uk-flex-right@m uk-flex-center uk-flex-wrap uk-flex-middle uk-grid uk-margin-remove-top"
<div search-input [expandable]="true" [searchControl]="filterForm.get('keyword')" searchInputClass="outer" placeholder="Search entity" uk-grid>
[disabled]="showLoading" class="uk-width-1-3@xl uk-width-2-5@l uk-width-1-2@m uk-width-1-1"></div> <div #searchInputComponent search-input [control]="filterForm.controls.keyword" [showSearch]="false"
<div *ngIf="isPortalAdministrator"> placeholder="Search entity"
<button class="uk-button uk-button-default uk-flex uk-flex-middle" (click)="newEntity()" [selected]="selectedKeyword" (closeEmitter)="onSearchClose()" (resetEmitter)="reset()"
[disabled]="showLoading" [class.uk-disabled]="showLoading"> [bordered]="true" colorClass="uk-text-secondary"
<icon name="add" [flex]="true"></icon> class="uk-width-1-3@xl uk-width-2-5@l uk-width-1-2@m uk-width-1-1"></div>
<span class="uk-margin-small-left uk-text-bold uk-text-uppercase">Add entity</span> <div *ngIf="isPortalAdministrator">
</button> <a (click)="newEntity()"
</div> class="uk-flex uk-flex-middle uk-text-uppercase">
</div> <button class="large uk-icon-button uk-button-secondary">
</div> <icon name="add"></icon>
</div> </button>
<button class="uk-button uk-button-link uk-margin-small-left uk-text-secondary">Add entity</button>
</a>
</div>
</div>
</div>
<div *ngIf="!showLoading && checkboxes.length > 0"
class="uk-margin-remove-top uk-margin-small-left uk-margin-small-bottom uk-display-inline"
[attr.uk-tooltip]="getSelectedEntities().length == 0 ? 'pos:left; cls: uk-active' : null"
title="Select at least one entity"><input id="checkAll" type="checkbox" (click)="selectAll()"
[ngModel]="getSelectedEntities().length ==checkboxes.length"/>
<span *ngIf="getSelectedEntities().length > 0" class="uk-margin-left uk-text-muted">
{{getSelectedEntities().length}} entities selected </span>
<a class="uk-margin-left ">Actions </a>
<div uk-dropdown="mode: click">
<ul class="uk-nav uk-dropdown-nav"
[attr.uk-tooltip]="getSelectedEntities().length == 0 ? 'pos:left; cls: uk-active' : 'cls: uk-invisible'"
title="Select at least one entity">
<li *ngIf="!isPortalAdministrator"><a [class]="getSelectedEntities().length == 0 ? 'uk-disabled' : ''"
(click)="toggleEntities(true,getSelectedEntities())"><i></i> Enable
</a></li>
<li *ngIf="!isPortalAdministrator"><a [class]="getSelectedEntities().length == 0 ? 'uk-disabled' : ''"
(click)="toggleEntities(false,getSelectedEntities())"><i></i> Disable
</a>
</li>
<li *ngIf="isPortalAdministrator"><a [class]="getSelectedEntities().length == 0 ? 'uk-disabled' : ''"
(click)="confirmDeleteSelectedEntities()"><i></i> Delete </a></li>
</ul>
</div>
</div>
</div>
<div inner> <div inner>
<div class="uk-section uk-section-small uk-position-relative" style="min-height: 60vh"> <div *ngIf="showLoading" class="uk-position-center">
<div *ngIf="showLoading" class="uk-position-center"> <loading></loading>
<loading></loading> </div>
</div> <div *ngIf="!showLoading">
<ng-container *ngIf="!showLoading"> <table *ngIf="checkboxes.length > 0 " class="uk-table uk-table-striped uk-table-hover uk-table-large">
<div *ngIf="checkboxes.length == 0" <thead class="uk-card-header">
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-top uk-margin-bottom uk-text-bold"> <tr>
<div>No entities found</div> <th class="uk-width-small"></th>
</div> <th>Name</th>
<table *ngIf="checkboxes.length > 0 " class="uk-table uk-table-striped uk-table-large"> <th *ngIf="!isPortalAdministrator">Status</th>
<thead> <th *ngIf="!isPortalAdministrator">Enable/Disable</th>
<tr class="uk-child-width-1-3"> <th *ngIf="isPortalAdministrator">Actions</th>
<th *ngIf="!portal"> </tr>
<label> </thead>
<input id="checkAll" type="checkbox" (click)="selectAll()" class="uk-checkbox" <tbody>
[ngModel]="getSelectedEntities().length ==checkboxes.length"/> <tr *ngFor="let check of checkboxes; let i=index">
</label> <td><input id="{{check.entity._id}}" class="checkBox" type="checkbox"
<span class="uk-margin-left"> name="entitiescb[]" value="{{check.entity._id}}" [(ngModel)]="check.checked">
<button class="uk-button uk-button-link" [class.uk-disabled]="getSelectedEntities().length == 0" [disabled]="getSelectedEntities().length == 0"> </td>
Bulk Actions ({{getSelectedEntities().length}}) <td>
</button> <div class="name" href="#">{{check.entity.name}}</div>
<div uk-dropdown="mode: click"> </td>
<ul class="uk-nav uk-dropdown-nav" <td *ngIf="!isPortalAdministrator">
[attr.uk-tooltip]="getSelectedEntities().length == 0 ? 'pos:left; cls: uk-active' : 'cls: uk-invisible'" <div class="name" href="#">{{check.entity.isEnabled ? "Enabled" : "Disabled"}}</div>
title="Select at least one entity"> </td>
<li *ngIf="isPortalAdministrator"> <td *ngIf="!isPortalAdministrator">
<a (click)="confirmDeleteSelectedEntities()"><i></i>Delete</a> <mat-slide-toggle [checked]="check.entity.isEnabled"
</li> (change)="($event.source.checked = check.entity.isEnabled);toggleEntities(!check.entity.isEnabled,[check.entity._id])"
</ul> uk-tooltip="title:<div class='uk-padding-small uk-width-large'><div class='uk-text-bold '>Disable an entity to hide it from community dashboard portal.</div><div class=' uk-margin-top'>If an entity is disabled, all related search and advanced search pages will be hidden from the community dashborad and a message 'Can't find that page' will appear in case the url of that page is loaded. If the related page belongs to the menu the link will be removed from menu, too.</div></div>"
</div> ></mat-slide-toggle>
</span> </td>
</th>
<th>Name</th> <td *ngIf="isPortalAdministrator">
<th *ngIf="!isPortalAdministrator">Status</th> <div class="actions" href="#">
<th *ngIf="isPortalAdministrator">Actions</th> <icon class="clickable" name="edit" (click)="editEntity(i)"></icon>
</tr> <icon class="clickable uk-margin-small-left" [customClass]="'uk-text-danger'" name="remove" (click)="confirmDeleteEntity(check.entity._id)"></icon>
</thead> </div>
<tbody> </td>
<tr *ngFor="let check of checkboxes; let i=index"> </tr>
<td *ngIf="!portal"> </tbody>
<input id="{{check.entity._id}}" class="uk-checkbox" type="checkbox" </table>
name="entitiescb[]" value="{{check.entity._id}}" [(ngModel)]="check.checked"> <div *ngIf="checkboxes.length == 0"
</td> class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<td> <div>No entities found</div>
<div class="name" href="#">{{check.entity.name}}</div> </div>
</td> </div>
<td *ngIf="!isPortalAdministrator">
<mat-slide-toggle [checked]="check.entity.isEnabled"
(change)="($event.source.checked = check.entity.isEnabled);toggleEntities(!check.entity.isEnabled,[check.entity._id])"
uk-tooltip="title:<div class='uk-padding-small uk-width-large'><div class='uk-text-bold '>Disable an entity to hide it from community dashboard portal.</div><div class=' uk-margin-top'>If an entity is disabled, all related search and advanced search pages will be hidden from the community dashborad and a message 'Can't find that page' will appear in case the url of that page is loaded. If the related page belongs to the menu the link will be removed from menu, too.</div></div>"
></mat-slide-toggle>
</td>
<td *ngIf="isPortalAdministrator">
<div class="uk-flex uk-flex-middle">
<icon class="clickable" [flex]="true" name="edit" [customClass]="'uk-text-primary'" (click)="editEntity(i)"></icon>
<icon class="clickable uk-margin-small-left" [flex]="true" [customClass]="'uk-text-danger'" name="delete" (click)="confirmDeleteEntity(check.entity._id)"></icon>
</div>
</td>
</tr>
</tbody>
</table>
</ng-container>
</div>
</div> </div>
</div> </div>
<modal-alert #editModal (alertOutput)="entitySaveConfirmed($event)" <modal-alert #editModal (alertOutput)="entitySaveConfirmed($event)"
[okDisabled]="entityForm && (entityForm.invalid || !entityForm.dirty)" classTitle="uk-background-primary uk-light"> [okDisabled]="entityForm && (entityForm.invalid || !entityForm.dirty)">
<form *ngIf="entityForm" [formGroup]="entityForm" class="uk-grid uk-child-width-1-1" uk-grid> <form *ngIf="entityForm" [formGroup]="entityForm" class="uk-grid uk-child-width-1-1" uk-grid>
<div input [formInput]="entityForm.get('name')" placeholder="Entity Name"></div> <div dashboard-input [formInput]="entityForm.get('name')"
<div input [formInput]="entityForm.get('pid')" placeholder="Entity Pid"></div> type="text" placeholder="Write a name"
label="Entity Name">
</div>
<div dashboard-input [formInput]="entityForm.get('pid')"
type="text" placeholder="Write a pid"
label="Entity Pid">
</div>
</form> </form>
</modal-alert> </modal-alert>
<modal-alert #relatedPages [overflowBody]="false" (alertOutput)="continueToggling($event)" classTitle="uk-background-primary uk-light"></modal-alert> <modal-alert #relatedPages (alertOutput)="continueToggling($event)"></modal-alert>
<modal-alert #deleteModal [overflowBody]="false" (alertOutput)="confirmedDeleteEntities($event)" classTitle="uk-background-primary uk-light"></modal-alert>
<modal-alert #deleteModal (alertOutput)="confirmedDeleteEntities($event)"></modal-alert>

View File

@ -1,7 +1,7 @@
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {HelpContentService} from '../../services/help-content.service'; import {HelpContentService} from '../../services/help-content.service';
import {UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms'; import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {CheckEntity, Entity} from '../../utils/entities/adminTool/entity'; import {CheckEntity, Entity} from '../../utils/entities/adminTool/entity';
import {Portal} from '../../utils/entities/adminTool/portal'; import {Portal} from '../../utils/entities/adminTool/portal';
import {EnvProperties} from '../../utils/properties/env-properties'; import {EnvProperties} from '../../utils/properties/env-properties';
@ -10,14 +10,11 @@ import {UserManagementService} from '../../services/user-management.service';
import {Subscriber} from "rxjs"; import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment"; import {properties} from "../../../../environments/environment";
import {AlertModal} from "../../utils/modal/alert"; import {AlertModal} from "../../utils/modal/alert";
import {SearchInputComponent} from "../../sharedComponents/search-input/search-input.component";
import {StringUtils} from "../../utils/string-utils.class"; import {StringUtils} from "../../utils/string-utils.class";
import {Title} from "@angular/platform-browser"; import {Title} from "@angular/platform-browser";
import {StakeholderService} from '../../monitor/services/stakeholder.service';
import {CommunityService} from "../../connect/community/community.service"; declare var UIkit;
import {CommunityInfo} from "../../connect/community/communityInfo";
import {Stakeholder} from "../../monitor/entities/stakeholder";
import {ClearCacheService} from "../../services/clear-cache.service";
import {NotificationHandler} from "../../utils/notification-handler";
@Component({ @Component({
selector: 'entities', selector: 'entities',
@ -34,17 +31,13 @@ export class EntitiesComponent implements OnInit {
public entities: Entity[] = []; public entities: Entity[] = [];
public entityForm: UntypedFormGroup; public entityForm: FormGroup;
private searchText: RegExp = new RegExp(''); private searchText: RegExp = new RegExp('');
public keyword = ''; public keyword = '';
public communities: Portal[] = []; public communities: Portal[] = [];
public portal: string; public portal: string;
public type: any;
public name: string;
public entity: CommunityInfo | Stakeholder;
public showLogo: boolean = true;
public toggleIds: string[]; public toggleIds: string[];
public toggleStatus: boolean; public toggleStatus: boolean;
@ -52,17 +45,16 @@ export class EntitiesComponent implements OnInit {
public showLoading = true; public showLoading = true;
public isPortalAdministrator = null; public isPortalAdministrator = null;
public filterForm: UntypedFormGroup; public filterForm: FormGroup;
private subscriptions: any[] = []; private subscriptions: any[] = [];
private index: number; private index: number;
public selectedKeyword: string;
@ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent;
constructor(private element: ElementRef, private route: ActivatedRoute, constructor(private element: ElementRef, private route: ActivatedRoute,
private _router: Router, private title: Title, private _router: Router, private title: Title,
private _helpContentService: HelpContentService, private _helpContentService: HelpContentService,
private userManagementService: UserManagementService, private _fb: UntypedFormBuilder, private userManagementService: UserManagementService, private _fb: FormBuilder) {
private communityService: CommunityService,
private stakeholderService: StakeholderService,
private _clearCacheService: ClearCacheService) {
} }
ngOnInit() { ngOnInit() {
@ -80,28 +72,9 @@ export class EntitiesComponent implements OnInit {
this.userManagementService.getUserInfo().subscribe(user => { this.userManagementService.getUserInfo().subscribe(user => {
this.portal = (this.route.snapshot.data.portal) ? this.route.snapshot.data.portal : this.route.snapshot.params[this.route.snapshot.data.param]; this.portal = (this.route.snapshot.data.portal) ? this.route.snapshot.data.portal : this.route.snapshot.params[this.route.snapshot.data.param];
if (this.route.snapshot.data.portal) { if (this.route.snapshot.data.portal) {
this.name = StringUtils.capitalize(this.portal);
this.title.setTitle(StringUtils.capitalize(this.portal) + ' | Entities'); this.title.setTitle(StringUtils.capitalize(this.portal) + ' | Entities');
} else if (this.route.snapshot.params[this.route.snapshot.data.param]) { } else if (this.route.snapshot.params[this.route.snapshot.data.param]) {
this.type = this.route.snapshot.data.param; this.title.setTitle(this.portal.toUpperCase() + ' | Entities');
if(this.route.snapshot.data.param === 'stakeholder') {
this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
if(stakeholder) {
this.name = stakeholder.name;
this.entity = stakeholder;
this.title.setTitle(this.name + ' | Entities');
}
}));
} else {
this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe(community => {
if(community) {
this.showLogo = false;
this.name = community.shortTitle;
this.entity = community;
this.title.setTitle(this.name + ' | Entities');
}
}));
}
} else { } else {
this.title.setTitle('Administrator Dashboard | Entities'); this.title.setTitle('Administrator Dashboard | Entities');
} }
@ -189,6 +162,8 @@ export class EntitiesComponent implements OnInit {
} }
private confirmDeleteEntitiesModalOpen() { private confirmDeleteEntitiesModalOpen() {
this.deleteModal.cancelButton = true;
this.deleteModal.okButton = true;
this.deleteModal.alertTitle = 'Delete Confirmation'; this.deleteModal.alertTitle = 'Delete Confirmation';
this.deleteModal.message = 'Are you sure you want to delete the selected entity(-ies)?'; this.deleteModal.message = 'Are you sure you want to delete the selected entity(-ies)?';
this.deleteModal.okButtonText = 'Yes'; this.deleteModal.okButtonText = 'Yes';
@ -200,10 +175,12 @@ export class EntitiesComponent implements OnInit {
this._helpContentService.deleteEntities(this.selectedEntities, this.properties.adminToolsAPIURL).subscribe( this._helpContentService.deleteEntities(this.selectedEntities, this.properties.adminToolsAPIURL).subscribe(
_ => { _ => {
this.deleteEntitiesFromArray(this.selectedEntities); this.deleteEntitiesFromArray(this.selectedEntities);
NotificationHandler.rise('Entities have been <b>successfully deleted</b>'); UIkit.notification('Entities have been <b>successfully deleted</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
this.showLoading = false; this.showLoading = false;
this._clearCacheService.clearCache("entities deleted");
this._clearCacheService.purgeBrowserCache("entities deleted", this.portal);
}, },
error => this.handleUpdateError('System error deleting the selected entities', error) error => this.handleUpdateError('System error deleting the selected entities', error)
); );
@ -230,6 +207,8 @@ export class EntitiesComponent implements OnInit {
} }
private entitiesModalOpen(title: string, yesBtn: string) { private entitiesModalOpen(title: string, yesBtn: string) {
this.editModal.cancelButton = true;
this.editModal.okButton = true;
this.editModal.okButtonLeft = false; this.editModal.okButtonLeft = false;
this.editModal.alertTitle = title; this.editModal.alertTitle = title;
this.editModal.okButtonText = yesBtn; this.editModal.okButtonText = yesBtn;
@ -238,24 +217,28 @@ export class EntitiesComponent implements OnInit {
public entitySaveConfirmed(data: any) { public entitySaveConfirmed(data: any) {
this.showLoading = true; this.showLoading = true;
if (this.entityForm.getRawValue()._id) { if (this.entityForm.value._id) {
this._helpContentService.updateEntity( this._helpContentService.updateEntity(
<Entity>this.entityForm.getRawValue(), this.properties.adminToolsAPIURL).subscribe( <Entity>this.entityForm.value, this.properties.adminToolsAPIURL).subscribe(
entity => { entity => {
this.entityUpdatedSuccessfully(entity); this.entityUpdatedSuccessfully(entity);
NotificationHandler.rise('Entity <b>' + entity.name + '</b> has been <b>successfully updated</b>'); UIkit.notification('Entity <b>' + entity.name + '</b> has been <b>successfully updated</b>', {
this._clearCacheService.clearCache("entity updated"); status: 'success',
this._clearCacheService.purgeBrowserCache("entity updated", this.portal); timeout: 6000,
pos: 'bottom-right'
});
}, },
error => this.handleUpdateError('System error updating entity', error) error => this.handleUpdateError('System error updating entity', error)
); );
} else { } else {
this._helpContentService.saveEntity(<Entity>this.entityForm.getRawValue(), this.properties.adminToolsAPIURL).subscribe( this._helpContentService.saveEntity(<Entity>this.entityForm.value, this.properties.adminToolsAPIURL).subscribe(
entity => { entity => {
this.entitySavedSuccessfully(entity); this.entitySavedSuccessfully(entity);
NotificationHandler.rise('Entity <b>' + entity.name + '</b> has been <b>successfully created</b>'); UIkit.notification('Entity <b>' + entity.name + '</b> has been <b>successfully created</b>', {
this._clearCacheService.clearCache("entity saved"); status: 'success',
this._clearCacheService.purgeBrowserCache("entity saved", this.portal) timeout: 6000,
pos: 'bottom-right'
});
}, },
error => this.handleUpdateError('System error creating entity', error) error => this.handleUpdateError('System error creating entity', error)
); );
@ -295,16 +278,18 @@ export class EntitiesComponent implements OnInit {
return status == "all" || (status == "disabled" && !entity.isEnabled) || (status == "enabled" && entity.isEnabled); return status == "all" || (status == "disabled" && !entity.isEnabled) || (status == "enabled" && entity.isEnabled);
} }
handleError(message: string, error = null) { handleError(message: string, error) {
if(error) { UIkit.notification(message, {
console.log('Server responded: ' + error); status: 'danger',
} timeout: 6000,
NotificationHandler.rise(message, 'danger'); pos: 'bottom-right'
});
console.log('Server responded: ' + error);
this.showLoading = false; this.showLoading = false;
} }
handleUpdateError(message: string, error = null) { handleUpdateError(message: string, error) {
if (!error) { if (error == null) {
this.entityForm = this._fb.group({ this.entityForm = this._fb.group({
pid: ['', Validators.required], pid: ['', Validators.required],
name: ['', Validators.required], name: ['', Validators.required],
@ -312,9 +297,13 @@ export class EntitiesComponent implements OnInit {
_id: '' _id: ''
}); });
} else { } else {
UIkit.notification(message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
console.log('Server responded: ' + error); console.log('Server responded: ' + error);
} }
NotificationHandler.rise(message, 'danger');
this.showLoading = false; this.showLoading = false;
} }
@ -330,6 +319,8 @@ export class EntitiesComponent implements OnInit {
} }
private confirmRelatedPagesModalOpen() { private confirmRelatedPagesModalOpen() {
this.relatedPages.cancelButton = true;
this.relatedPages.okButton = true;
this.relatedPages.alertTitle = 'Warning'; this.relatedPages.alertTitle = 'Warning';
this.relatedPages.message = "This action will affect all search pages related to this entity! Pages' status will change to entity's status! Do you want to continue?"; this.relatedPages.message = "This action will affect all search pages related to this entity! Pages' status will change to entity's status! Do you want to continue?";
this.relatedPages.okButtonText = 'Yes'; this.relatedPages.okButtonText = 'Yes';
@ -345,13 +336,20 @@ export class EntitiesComponent implements OnInit {
this.checkboxes[i].entity.isEnabled = this.toggleStatus; this.checkboxes[i].entity.isEnabled = this.toggleStatus;
} }
this.applyCheck(false); this.applyCheck(false);
this._clearCacheService.clearCache("entity's status changed");
this._clearCacheService.purgeBrowserCache("entity's status changed", this.portal);
}, },
error => this.handleUpdateError('System error changing the status of the selected entity(-ies)', error) error => this.handleUpdateError('System error changing the status of the selected entity(-ies)', error)
); );
} }
public onSearchClose() {
this.selectedKeyword = this.filterForm.get('keyword').value;
}
public reset() {
this.selectedKeyword = null;
this.searchInputComponent.reset()
}
selectAll() { selectAll() {
let checked = (this.getSelectedEntities().length != this.checkboxes.length); let checked = (this.getSelectedEntities().length != this.checkboxes.length);
for (let check of this.checkboxes) { for (let check of this.checkboxes) {

View File

@ -12,17 +12,20 @@ import {AdminTabsModule} from "../sharedComponents/admin-tabs/admin-tabs.module"
import {EntitiesRoutingModule} from "./entities-routing.module"; import {EntitiesRoutingModule} from "./entities-routing.module";
import {SearchInputModule} from "../../sharedComponents/search-input/search-input.module"; import {SearchInputModule} from "../../sharedComponents/search-input/search-input.module";
import {IconsModule} from "../../utils/icons/icons.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"; import {LoadingModule} from "../../utils/loading/loading.module";
import {LogoUrlPipeModule} from "../../utils/pipes/logoUrlPipe.module";
@NgModule({ @NgModule({
imports: [ imports: [
EntitiesRoutingModule,
CommonModule, RouterModule, FormsModule, AdminToolServiceModule, CommonModule, RouterModule, FormsModule, AdminToolServiceModule,
AlertModalModule, ReactiveFormsModule, MatSlideToggleModule, InputModule, PageContentModule, AdminTabsModule, SearchInputModule, IconsModule, LoadingModule, LogoUrlPipeModule AlertModalModule, ReactiveFormsModule, MatSlideToggleModule, InputModule, PageContentModule, AdminTabsModule, EntitiesRoutingModule, SearchInputModule, IconsModule, LoadingModule
], ],
declarations: [EntitiesComponent], declarations: [EntitiesComponent],
exports: [EntitiesComponent] exports: [EntitiesComponent]
}) })
export class EntitiesModule { export class EntitiesModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([add, edit, remove]);
}
} }

View File

@ -1,82 +1,87 @@
<div page-content> <div page-content>
<div header> <div header>
<div class="uk-section-xsmall uk-margin-top uk-container"> <div class="uk-margin-top">
<div class="uk-flex-middle uk-grid" uk-grid> <a routerLink="../" [queryParams]=" { 'pageId': pageId }"
<div class="uk-width-expand"> class="uk-text-secondary uk-text-uppercase uk-text-bold uk-text-small">
<a routerLink="../" [queryParams]=" { 'pageId': pageId }" class="uk-flex uk-flex-middle uk-h5 uk-link-reset"> <span class="uk-icon-button uk-icon small uk-button-secondary">
<span class="uk-margin-right"> <icon name="arrow_left"></icon>
<icon name="west" ratio="1.7" [flex]="true"></icon> </span>
</span> <span class="space">
<h1 *ngIf="page" class="uk-h5 uk-margin-remove"> Go back to page help texts list
{{page.name}} - {{pageHelpContent ? 'Update ' : 'Add new '}} page help text </span>
<span *ngIf="myForm.dirty" class="uk-text-large"> (unsaved changes)</span> </a>
</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> </div>
</div> </div>
<div inner> <div inner>
<div class="uk-container"> <div class="uk-card-header">
<div *ngIf="myForm" style="min-height: 60vh" <div class="uk-flex uk-flex-middle uk-child-width-1-1 uk-child-width-1-2@m uk-grid" uk-grid>
class="uk-section uk-section-small uk-position-relative"> <div>
<div *ngIf="showLoading" class="uk-position-center"> <div class="uk-text-small uk-text-muted"> {{pageHelpContent ? 'Update ' : 'Add new '}} page help text</div>
<loading *ngIf="showLoading"></loading> <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.invalid ">Save
</button>
</div>
</div> </div>
<form *ngIf="!showLoading" [formGroup]="myForm">
<div class="uk-grid uk-child-width-1-2">
<div *ngIf="placementsOptions.length > 0" input [formInput]="myForm.get('placement')"
placeholder="Select placement" [options]="placementsOptions" type="select"></div>
<div input [formInput]="myForm.get('order')" placeholder="Select order" [options]="orderOptions" type="select"></div>
</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>
<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 class="uk-animation-fade uk-width-1-1" role="alert">
<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="placementsOptions.length > 0" dashboard-input
[formInput]="myForm.get('placement')"
type="select" placeholder="Select placement"
label="Select placement" [options]="placementsOptions"
>
</div>
<div dashboard-input [formInput]="myForm.get('order')"
type="select" placeholder="Select order"
label="Select order" [options]="orderOptions">
</div>
</div>
<div class="form-group uk-margin-top">
<div class="uk-text-bold uk-margin-medium-bottom">Select Status (Enable/ disable)</div>
<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-medium-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> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
import {ChangeDetectorRef, Component, OnInit, ViewChild} from '@angular/core'; import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router'; 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 {Page} from '../../utils/entities/adminTool/page';
import {HelpContentService} from '../../services/help-content.service'; import {HelpContentService} from '../../services/help-content.service';
import {EnvProperties} from '../../utils/properties/env-properties'; import {EnvProperties} from '../../utils/properties/env-properties';
@ -8,9 +8,8 @@ import {properties} from '../../../../environments/environment';
import {Subscriber, Subscription, zip} from 'rxjs'; import {Subscriber, Subscription, zip} from 'rxjs';
import {HelperFunctions} from '../../utils/HelperFunctions.class'; import {HelperFunctions} from '../../utils/HelperFunctions.class';
import {PageHelpContent} from '../../utils/entities/adminTool/page-help-content'; import {PageHelpContent} from '../../utils/entities/adminTool/page-help-content';
import {ClearCacheService} from "../../services/clear-cache.service";
import {NotificationHandler} from "../../utils/notification-handler"; declare var UIkit;
import {CKEditorComponent} from "ng2-ckeditor";
@Component({ @Component({
selector: 'page-content-form', selector: 'page-content-form',
@ -18,9 +17,8 @@ import {CKEditorComponent} from "ng2-ckeditor";
}) })
export class PageContentFormComponent implements OnInit { export class PageContentFormComponent implements OnInit {
myForm: UntypedFormGroup; myForm: FormGroup;
portal: string; portal: string;
parentClass: string;
pageId: string; pageId: string;
pageContentId: string; pageContentId: string;
page: Page; page: Page;
@ -30,25 +28,23 @@ export class PageContentFormComponent implements OnInit {
public showLoading: boolean = true; public showLoading: boolean = true;
private subs: Subscription[] = []; private subs: Subscription[] = [];
public pageHelpContent: PageHelpContent; public pageHelpContent: PageHelpContent;
@ViewChild('ckEditor') ckEditor: CKEditorComponent;
constructor(private route: ActivatedRoute, private _router: Router, private _fb: FormBuilder, private _helpContentService: HelpContentService) {
constructor(private route: ActivatedRoute, private _router: Router, private _fb: UntypedFormBuilder,
private cdr: ChangeDetectorRef, private _helpContentService: HelpContentService,
private _clearCacheService: ClearCacheService) {
} }
ngOnInit() { ngOnInit() {
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.params.subscribe(params => {
this.parentClass = this.route.snapshot.data.parentClass; 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.subs.push(this.route.queryParams.subscribe(params => {
HelperFunctions.scroll(); HelperFunctions.scroll();
this.pageId = params['pageId']; this.pageId = params['pageId'];
this.myForm = this.form; this.myForm = this.form;
this.pageContentId = params['pageContentId']; this.pageContentId = params['pageContentId'];
if (!this.pageId) { if (!this.pageId) {
this._router.navigate(['../'], {relativeTo: this.route}); this._router.navigate(['../'], {relativeTo: this.route});
} }
this.getInfo(this.pageId); this.getInfo(this.pageId);
}));
})); }));
} }
@ -70,10 +66,16 @@ export class PageContentFormComponent implements OnInit {
this._router.navigate(['../'], {relativeTo: this.route}); this._router.navigate(['../'], {relativeTo: this.route});
} }
let countPageContents = results[1] ? results[1].length : 0; let countPageContents = results[1] ? results[1].length : 0;
console.log(results[1]);
for (let content of (results[1] as Array<PageHelpContent>)) { for (let content of (results[1] as Array<PageHelpContent>)) {
// if(content.page['_id'] == pageId){
// countPageContents++;
if (this.pageContentId && this.pageContentId == content._id) { if (this.pageContentId && this.pageContentId == content._id) {
this.pageHelpContent = content; this.pageHelpContent = content;
// this.pageHelpContent.page = pageId;
// this.pageHelpContent.portal = this.communityPid;
} }
// }
} }
this.setOptions(this.page, countPageContents + (this.pageHelpContent ? 0 : 1)); this.setOptions(this.page, countPageContents + (this.pageHelpContent ? 0 : 1));
if (!this.pageContentId) { if (!this.pageContentId) {
@ -83,30 +85,53 @@ export class PageContentFormComponent implements OnInit {
this.updateForm(this.pageHelpContent); this.updateForm(this.pageHelpContent);
} }
this.showLoading = false; this.showLoading = false;
this.initCKEditor();
}, },
error => this.handleError('System error retrieving page with id: ' + pageId, error) error => this.handleError('System error retrieving page with id: ' + pageId, error)
)); ));
} }
private initCKEditor() { /*private getPage(pageId: string) {
this.cdr.detectChanges(); this.subs.push(this._helpContentService.getPageByPortal(pageId,this.properties.adminToolsAPIURL, this.communityPid).subscribe(
if(this.ckEditor) { page => {
this.ckEditor.instance.on('mode', () => { if(this.properties.adminToolsPortalType != page.portalType) {
let editor = this.ckEditor.instance; this._router.navigate(['../'], {relativeTo: this.route});
if (editor.mode === 'source') { } else {
let editable = editor.editable(); this.page = page;
editable.attachListener(editable, 'input', () => { this.getPageContents(pageId);
this.myForm.get('content').setValue(editor.getData()); }
this.myForm.get('content').markAsDirty(); },
this.cdr.detectChanges(); error => this.handleError('System error retrieving page with id: '+pageId, error)
}); ));
}
});
}
} }
private getPageContents(pageId: string) {
this.subs.push(this._helpContentService.getCommunityPageHelpContents(this.communityPid, this.properties.adminToolsAPIURL).subscribe(
pageHelpContents => {
let countPageContents = 1;
for (let content of (pageHelpContents as Array<PageHelpContent>)) {
if(content.page['_id'] == pageId){
countPageContents++;
}
}
this.setOptions(this.page, countPageContents);
if(!this.pageContentId) {
this.showLoading = false;
this.initFormWithSelectOptions();
}
},
error => this.handleError('System error retrieving page contents with id: ', error)
));
}
private getPageHelpContent(pageContentId: string) {
this.showLoading = true;
this.subs.push(this._helpContentService.getPageHelpContent(pageContentId as string, this.properties.adminToolsAPIURL, this.communityPid).subscribe(
pageHelpContent => {
this.updateForm(pageHelpContent);
this.showLoading = false;
},
error => this.handleError('System error retrieving page help content', error)));
}*/
private updateForm(pageHelpContent: PageHelpContent) { private updateForm(pageHelpContent: PageHelpContent) {
this.pageHelpContent = pageHelpContent; this.pageHelpContent = pageHelpContent;
this.myForm = this.form; this.myForm = this.form;
@ -182,24 +207,32 @@ export class PageContentFormComponent implements OnInit {
this.myForm.markAsPristine(); this.myForm.markAsPristine();
} }
handleError(message: string, error = null) { handleError(message: string, error) {
if(error) { UIkit.notification(message, {
console.error('Server responded: ' + error); status: 'danger',
} timeout: 6000,
NotificationHandler.rise(message, 'danger'); pos: 'bottom-right'
});
console.error('Server responded: ' + error);
this.showLoading = false; this.showLoading = false;
} }
public saveCustom() { public saveCustom() {
if (this.myForm.valid) { if (this.myForm.valid) {
this.showLoading = true; this.showLoading = true;
let pageHelpContent: PageHelpContent = this.myForm.getRawValue(); this.myForm.get('order').enable();
this.myForm.get('placement').enable();
let pageHelpContent: PageHelpContent = this.myForm.value;
this.subs.push(this._helpContentService.savePageHelpContent(pageHelpContent, this.properties.adminToolsAPIURL, this.portal).subscribe( this.subs.push(this._helpContentService.savePageHelpContent(pageHelpContent, this.properties.adminToolsAPIURL, this.portal).subscribe(
_ => { _ => {
NotificationHandler.rise('Page content has been <b>successfully ' + (this.pageContentId ? 'updated' : 'created') + '</b>'); UIkit.notification('Page content has been <b>successfully ' + (this.pageContentId ? 'updated' : 'created') + '</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
this._router.navigate(['../'], {queryParams: {"pageId": this.pageId}, relativeTo: this.route}); this._router.navigate(['../'], {queryParams: {"pageId": this.pageId}, relativeTo: this.route});
this.showLoading = false; this.showLoading = false;
this._clearCacheService.clearCache("page help content saved");
}, },
err => this.handleUpdateError('System error saving page content', err) err => this.handleUpdateError('System error saving page content', err)
)); ));
@ -208,17 +241,24 @@ export class PageContentFormComponent implements OnInit {
} }
} }
public cancelCustom() {
this._router.navigate(['../'], {queryParams: {"pageId": this.pageId}, relativeTo: this.route});
}
public resetCustom() { public resetCustom() {
this.showLoading = true; this.showLoading = true;
this.updateForm(this.pageHelpContent); this.updateForm(this.pageHelpContent);
this.showLoading = false; this.showLoading = false;
} }
handleUpdateError(message: string, error = null) { handleUpdateError(message: string, error) {
if(error) { UIkit.notification(message, {
console.error('Server responded: ' + error); status: 'danger',
} timeout: 6000,
NotificationHandler.rise(message, 'danger'); pos: 'bottom-right'
});
console.error('Server responded: ' + error);
this.showLoading = false; this.showLoading = false;
} }

View File

@ -1,4 +1,4 @@
import {NgModule} from '@angular/core'; import { NgModule } from '@angular/core';
import {CommonModule} from '@angular/common'; import {CommonModule} from '@angular/common';
import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {AlertModalModule} from '../../utils/modal/alertModal.module'; import {AlertModalModule} from '../../utils/modal/alertModal.module';
@ -8,21 +8,27 @@ import {PageContentFormComponent} from './page-help-content-form.component';
import {PageHelpContentFormRoutingModule} from './page-help-content-form-routing.module'; import {PageHelpContentFormRoutingModule} from './page-help-content-form-routing.module';
import {AdminToolServiceModule} from '../../services/adminToolService.module'; import {AdminToolServiceModule} from '../../services/adminToolService.module';
import {InputModule} from '../../sharedComponents/input/input.module'; import {InputModule} from '../../sharedComponents/input/input.module';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import {IconsModule} from '../../utils/icons/icons.module'; import {IconsModule} from '../../utils/icons/icons.module';
import {PageContentModule} from '../sharedComponents/page-content/page-content.module'; import {PageContentModule} from '../sharedComponents/page-content/page-content.module';
import {RouterModule} from '@angular/router'; import {RouterModule} from '@angular/router';
import {LoadingModule} from '../../utils/loading/loading.module'; import {LoadingModule} from '../../utils/loading/loading.module';
import {MatSlideToggleModule} from "@angular/material/slide-toggle"; import {IconsService} from '../../utils/icons/icons.service';
import {arrow_left} from '../../utils/icons/icons';
@NgModule({ @NgModule({
imports: [ imports: [
PageHelpContentFormRoutingModule,
CommonModule, FormsModule, RouterModule, CommonModule, FormsModule, RouterModule,
SafeHtmlPipeModule, CKEditorModule, SafeHtmlPipeModule, CKEditorModule,
AlertModalModule, ReactiveFormsModule, AdminToolServiceModule, InputModule, IconsModule, PageContentModule, LoadingModule, MatSlideToggleModule AlertModalModule, ReactiveFormsModule, PageHelpContentFormRoutingModule, AdminToolServiceModule, InputModule, MatSlideToggleModule, IconsModule, PageContentModule, LoadingModule
], ],
declarations: [PageContentFormComponent], declarations: [
exports: [PageContentFormComponent] PageContentFormComponent
],
exports: [PageContentFormComponent]
}) })
export class PageHelpContentFormModule { export class PageHelpContentFormModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([arrow_left]);
}
} }

View File

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

View File

@ -1,5 +1,5 @@
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {UntypedFormBuilder, UntypedFormControl, UntypedFormGroup} from '@angular/forms'; import {FormBuilder, FormControl, FormGroup} from '@angular/forms';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {HelpContentService} from '../../services/help-content.service'; import {HelpContentService} from '../../services/help-content.service';
import { import {
@ -7,16 +7,18 @@ import {
PageHelpContent, PageHelpContent,
PageHelpContentFilterOptions PageHelpContentFilterOptions
} from '../../utils/entities/adminTool/page-help-content'; } from '../../utils/entities/adminTool/page-help-content';
import {Page} from '../../utils/entities/adminTool/page'; import {CheckPage, Page} from '../../utils/entities/adminTool/page';
import {Portal} from '../../utils/entities/adminTool/portal'; import {Portal} from '../../utils/entities/adminTool/portal';
import {EnvProperties} from '../../utils/properties/env-properties'; import {EnvProperties} from '../../utils/properties/env-properties';
import {Session} from '../../login/utils/helper.class';
import {LoginErrorCodes} from '../../login/utils/guardHelper.class';
import {HelperFunctions} from '../../utils/HelperFunctions.class'; import {HelperFunctions} from '../../utils/HelperFunctions.class';
import {Subscriber} from 'rxjs'; import {Subscriber} from 'rxjs';
import {properties} from '../../../../environments/environment'; import {properties} from '../../../../environments/environment';
import {DomSanitizer} from '@angular/platform-browser'; import {DomSanitizer} from '@angular/platform-browser';
import {SearchInputComponent} from '../../sharedComponents/search-input/search-input.component'; import {SearchInputComponent} from '../../sharedComponents/search-input/search-input.component';
import {ClearCacheService} from "../../services/clear-cache.service";
import {NotificationHandler} from "../../utils/notification-handler"; declare var UIkit;
@Component({ @Component({
selector: 'page-help-contents', selector: 'page-help-contents',
@ -27,7 +29,7 @@ export class PageHelpContentsComponent implements OnInit {
private selectedPageContents: string[] = []; private selectedPageContents: string[] = [];
public checkboxes: CheckPageHelpContent[] = []; public checkboxes: CheckPageHelpContent[] = [];
public pageHelpContents: PageHelpContent[] = []; public pageHelpContents: PageHelpContent[] = [];
public formGroup: UntypedFormGroup; public formGroup: FormGroup;
public pages: Page[]; public pages: Page[];
public checkboxAll: boolean = false; public checkboxAll: boolean = false;
public filters: PageHelpContentFilterOptions = {id: '', active: null, text: new RegExp('')}; public filters: PageHelpContentFilterOptions = {id: '', active: null, text: new RegExp('')};
@ -40,14 +42,12 @@ export class PageHelpContentsComponent implements OnInit {
public page: Page; public page: Page;
public properties: EnvProperties = properties; public properties: EnvProperties = properties;
public showLoading: boolean = true; public showLoading: boolean = true;
public filterForm: UntypedFormControl; public filterForm: FormControl;
private subscriptions: any[] = []; private subscriptions: any[] = [];
public selectedKeyword: string; public selectedKeyword: string;
@ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent; @ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent;
constructor(private element: ElementRef, private route: ActivatedRoute, private router: Router, constructor(private element: ElementRef, private route: ActivatedRoute, private router: Router, private _helpService: HelpContentService, private _fb: FormBuilder, private sanitizer: DomSanitizer) {
private _helpService: HelpContentService, private _fb: UntypedFormBuilder, private sanitizer: DomSanitizer,
private _clearCacheService: ClearCacheService) {
} }
ngOnInit() { ngOnInit() {
@ -152,6 +152,8 @@ export class PageHelpContentsComponent implements OnInit {
} }
private confirmModalOpen() { private confirmModalOpen() {
this.alertModalDeletePageHelpContents.cancelButton = true;
this.alertModalDeletePageHelpContents.okButton = true;
this.alertModalDeletePageHelpContents.alertTitle = 'Delete Confirmation'; this.alertModalDeletePageHelpContents.alertTitle = 'Delete Confirmation';
this.alertModalDeletePageHelpContents.message = 'Are you sure you want to delete the selected page content(s)?'; this.alertModalDeletePageHelpContents.message = 'Are you sure you want to delete the selected page content(s)?';
this.alertModalDeletePageHelpContents.okButtonText = 'Yes'; this.alertModalDeletePageHelpContents.okButtonText = 'Yes';
@ -163,9 +165,12 @@ export class PageHelpContentsComponent implements OnInit {
this.subscriptions.push(this._helpService.deletePageHelpContents(this.selectedPageContents, this.properties.adminToolsAPIURL, this.portal).subscribe( this.subscriptions.push(this._helpService.deletePageHelpContents(this.selectedPageContents, this.properties.adminToolsAPIURL, this.portal).subscribe(
_ => { _ => {
this.deletePageHelpContentsFromArray(this.selectedPageContents); this.deletePageHelpContentsFromArray(this.selectedPageContents);
NotificationHandler.rise('Page content(s) has been <b>successfully deleted</b>'); UIkit.notification('Page content(s) has been <b>successfully deleted</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
this.showLoading = false; this.showLoading = false;
this._clearCacheService.clearCache("Help texts deleted");
}, },
error => this.handleUpdateError('System error deleting the selected page content(s)', error) error => this.handleUpdateError('System error deleting the selected page content(s)', error)
)); ));
@ -207,10 +212,13 @@ export class PageHelpContentsComponent implements OnInit {
let i = this.checkboxes.findIndex(_ => _.pageHelpContent._id == id); let i = this.checkboxes.findIndex(_ => _.pageHelpContent._id == id);
this.checkboxes[i].pageHelpContent.isActive = status; this.checkboxes[i].pageHelpContent.isActive = status;
} }
NotificationHandler.rise('Page content(s) has been <b>successfully updated</b>'); UIkit.notification('Page content(s) has been <b>successfully updated</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
this.countPageHelpContents(); this.countPageHelpContents();
this.applyCheck(false); this.applyCheck(false);
this._clearCacheService.clearCache("Help text's status changed");
}, },
error => this.handleUpdateError('System error changing the status of the selected page content(s)', error) error => this.handleUpdateError('System error changing the status of the selected page content(s)', error)
)); ));
@ -240,19 +248,23 @@ export class PageHelpContentsComponent implements OnInit {
this.applyFilter(); this.applyFilter();
} }
handleError(message: string, error = null) { handleError(message: string, error) {
if(error) { UIkit.notification(message, {
console.log('Server responded: ' + error); status: 'danger',
} timeout: 6000,
NotificationHandler.rise(message, 'danger'); pos: 'bottom-right'
});
console.log('Server responded: ' + error);
this.showLoading = false; this.showLoading = false;
} }
handleUpdateError(message: string, error = null) { handleUpdateError(message: string, error) {
if(error) { UIkit.notification(message, {
console.log('Server responded: ' + error); status: 'danger',
} timeout: 6000,
NotificationHandler.rise(message, 'danger'); pos: 'bottom-right'
});
console.log('Server responded: ' + error);
this.showLoading = false; this.showLoading = false;
} }

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