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
525 changed files with 22063 additions and 38465 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,5 @@
//Classes used in linking / inlinelinking when selecting an entity
import {HelperFunctions} from "../../utils/HelperFunctions.class";
import {OpenaireEntities} from "../../utils/properties/searchFields";
export class ClaimResult {
public source: string;
@ -106,7 +105,7 @@ export class ClaimDBRecord {
targetType: string;
semantics: string;
approved: string;
source: ClaimDBResult | ClaimDBProject | ClaimDBContext;
source: ClaimDBResult | ClaimProject | ClaimContext;
target: ClaimDBResult;
indexed:boolean;
}
@ -143,9 +142,9 @@ export class ShowOptions {
show: string; //show values: source, result, project, context, claim
linkTo: string; // linkTo /values: result, project, context
linkToEntities: string[]; // show linkToEntities /values: result, project, context
basketShowSources: boolean = true;
basketShowLinksTo: boolean = false;
selectOptions= [];
basketShowSources: boolean;
basketShowLinksTo: boolean;
constructor() {
this.show = "source";
this.linkTo = "project";
@ -156,36 +155,23 @@ export class ShowOptions {
showSource() {
this.show = "source";
this.basketswitchToSources();
HelperFunctions.scroll();
}
basketswitchToSources() {
this.basketShowLinksTo = false;
this.basketShowSources = true;
}
basketswitchToLinkTo() {
this.basketShowLinksTo = true;
this.basketShowSources = false;
this.basketShowSources = true;
HelperFunctions.scroll();
}
showLinkTo() {
// console.log(this.linkTo, "showLinkTo")
this.show = this.linkTo;
this.basketswitchToLinkTo();
this.basketShowLinksTo = true;
this.basketShowSources = false;
HelperFunctions.scroll();
}
initSelectOptions(){
let options =[];
if(this.linkToEntities.indexOf('result')!=-1){
options.push({value: 'result',label: OpenaireEntities.RESULTS})
showBasketSources() {
if (this.show != 'source') {
this.basketShowSources = !this.basketShowSources;
this.basketShowLinksTo = !this.basketShowSources;
}
if(this.linkToEntities.indexOf('project')!=-1){
options.push({value: 'project',label: OpenaireEntities.PROJECTS})
}
if(this.linkToEntities.indexOf('context')!=-1){
options.push({value: 'context',label: OpenaireEntities.COMMUNITIES})
}
this.selectOptions = options;
}
}

View File

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

View File

@ -7,7 +7,7 @@ import {ErrorCodes} from '../../utils/properties/errorCodes';
import {StringUtils} from "../../utils/string-utils.class";
import {Filter, Value} from "../../searchPages/searchUtils/searchHelperClasses.class";
import {RangeFilter} from "../../utils/rangeFilter/rangeFilterHelperClasses.class";
import {OpenaireEntities, SearchFields} from "../../utils/properties/searchFields";
import {SearchFields} from "../../utils/properties/searchFields";
import {NewSearchPageComponent} from "../../searchPages/searchUtils/newSearchPage.component";
import {Subscriber} from "rxjs";
@ -20,17 +20,25 @@ declare var UIkit:any;
})
export class ClaimProjectsSearchFormComponent {
ngOnInit() {
// this.getFunders();
// this.search(this.page, this.size);
}
// @ViewChild (ModalLoading) loading : ModalLoading ;
// @Input() public inline: boolean = false ; // for claimed started from landing pages
public query = '';
@Input() public centerAlign: boolean = false;
@Input() public selectedProjects:ClaimEntity[]=[] ;
public elementRef;
// public funders:string[];
// public selectedFunderId:string ="0";
// selectedFunderName:string ="Select funder:";
@Output() projectSelected = new EventEmitter();
@Input() public properties:EnvProperties;
@Input() public inlineClaim:boolean=false;
@Input() localStoragePrefix:string = "";
@Input() basketLimit;
@Input() showOptions;
public errorCodes:ErrorCodes = new ErrorCodes();
public projects:string[];
@ -44,20 +52,23 @@ export class ClaimProjectsSearchFormComponent {
keyword:string = '';
showResults = false;
// public openaireRefineFields: string[] = ["relfunder", "relproject", "resultbestaccessright", "instancetypename", "resultlanguagename", "community"];
// public openaireRefineFieldsQuery: string = "&refine=true&fields=funder&fields=projectstartyear&fields=projectendyear&fields=projectecsc39";
public refineFields: string[] = ["funder"];
public refineFieldsQuery: string = "&refine=true&fields=funder";
filters = [];
prevFilters = [];
// startYear = "";
// endYear = "";
public rangeFilters: RangeFilter[] = [];
public searchFields: SearchFields = new SearchFields();
public rangeFields:string[][] = this.searchFields.PROJECT_RANGE_FIELDS;
openaireEntities = OpenaireEntities;
sub;
constructor(private _service: ProjectService, private _projectService: SearchProjectsService, myElement: ElementRef) {
this.elementRef = myElement;
this.rangeFilters = RangeFilter.parse(this.rangeFields,"project");
}
sub;
ngOnDestroy() {
if (this.sub instanceof Subscriber) {
this.sub.unsubscribe();
@ -88,7 +99,6 @@ export class ClaimProjectsSearchFormComponent {
this.openaireResultsStatus = this.errorCodes.DONE;
if(this.openaireResultsNum == 0){
this.openaireResultsStatus = this.errorCodes.NONE;
this.filters = this.checkSelectedFilters( [], this.prevFilters);
}
}else {
this.openaireResultsStatus = this.errorCodes.ERROR;
@ -275,19 +285,6 @@ export class ClaimProjectsSearchFormComponent {
}
}
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);
}
}
filters.push(filter)
}
}
return filters;
}
totalPages(totalResults: number): number {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@ import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {EnvProperties} from '../../../utils/properties/env-properties';
import {ClaimEntity, ClaimResult} from '../claimHelper.class';
import {catchError, map, timeout} from 'rxjs/operators';
import {catchError, map} from 'rxjs/operators';
import {properties} from "../../../../../environments/environment";
@ -21,14 +21,10 @@ export class SearchDataciteService {
//.catch(this.handleError);
}
getDataciteResultByDOI(doi: string, properties: EnvProperties, parse: boolean = false, file: boolean = false): any {
let timeoutTime: number = properties.environment == "production" ? 6000 : 12000;
let timeoutTimeForFile: number = 20000;
getDataciteResultByDOI(doi: string, properties: EnvProperties, parse: boolean = false): any {
let url = properties.searchDataciteAPIURL + '/' + doi;
let key = url;
return this.http.get((properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(timeout(file ? timeoutTimeForFile : (timeoutTime)))
.pipe(map(request => (parse ? SearchDataciteService.parse([request["data"]])[0] : request)), catchError(err => of(null)));
}
@ -50,6 +46,7 @@ export class SearchDataciteService {
static parse(response): ClaimEntity[] {
const results: ClaimEntity[] = [];
console.log(response);
for (let i = 0; i < response.length; i++) {
const item = response[i];
const entity: ClaimEntity = new ClaimEntity();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,9 +8,6 @@ import {LinkingGenericComponent} from "../linking/linkingGeneric.component";
import {ClaimResultSearchFormComponent} from "../claim-utils/claimResultSearchForm.component";
import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {StringUtils} from "../../utils/string-utils.class";
import {ClaimProjectsSearchFormComponent} from "../claim-utils/claimProjectSearchForm.component";
@Component({
@ -18,6 +15,8 @@ import {ClaimProjectsSearchFormComponent} from "../claim-utils/claimProjectSearc
templateUrl: 'directLinking.component.html'
})
export class DirectLinkingComponent {
@Input() piwikSiteId = null;
@ViewChild(LinkingGenericComponent) linking: LinkingGenericComponent;
results: ClaimEntity[] = [];
@ -29,7 +28,7 @@ export class DirectLinkingComponent {
// linkTo: string = null; // entity type (project or context or entity)
// linkToEntities: string[] = [];
showOptions:ShowOptions = new ShowOptions();
validEntityTypes = ["dataset", "publication", "software", "other", "project", "context"];
validEntityTypes = ["dataset", "publication", "software", "orp", "project", "context"];
sources: ClaimEntity[] = [];
inlineEntity: ClaimEntity = null;
validInput: boolean = null;//'true;
@ -56,6 +55,12 @@ export class DirectLinkingComponent {
if (this.type != null && this.showOptions.linkTo != null) {
this.type = (this.validEntityTypes.indexOf(this.type) != -1) ? this.type : 'publication';
this.showOptions.linkTo = (this.validEntityTypes.indexOf(this.showOptions.linkTo) != -1 || this.showOptions.linkTo == "result") ? this.showOptions.linkTo : 'project';
// this.show = (this.linkTo != "entity") ? "claim" : "entity";
// this.linkType = this.linkTo;
// let isInlineResult: boolean = false; // is a link entity - entity
// if ((this.type == "publication" || this.type == "dataset" || this.type == "software") && ((this.linkTo == "publication" || this.linkTo == "dataset" || this.linkTo == "software" || this.linkTo == "orp") || this.linkTo == "entity")) {
// isInlineResult = true;
// }
this.localStoragePrefix = (this.communityId ? (this.communityId + "_") : '') + this.type.substr(0, 3) + "_" + this.showOptions.linkTo.substr(0, 3) + "_";
if (localStorage.getItem(this.localStoragePrefix + "results")) {
@ -74,7 +79,7 @@ export class DirectLinkingComponent {
this.getResearchResultById("dataset", this.id);
} else if (this.type == "software") {
this.getResearchResultById("software", this.id);
} else if (this.type == "other") {
} else if (this.type == "orp") {
this.getResearchResultById("other", this.id);
} else {
this.validInput = this.isValidInput(null);
@ -110,9 +115,9 @@ export class DirectLinkingComponent {
return false;
} else if (this.type == "project" && this.showOptions.linkTo != "result") {
return false;
} else if (["dataset", "publication", "software", "other"].indexOf(this.type) != -1 && (["project", "context", "result"].indexOf(this.showOptions.linkTo) == -1)) {
} else if (["dataset", "publication", "software", "orp"].indexOf(this.type) != -1 && (["project", "context", "result"].indexOf(this.showOptions.linkTo) == -1)) {
return false;
} else if (["project", "dataset", "publication", "software", "other"].indexOf(this.type) == -1) {
} else if (["project", "dataset", "publication", "software", "orp"].indexOf(this.type) == -1) {
return false;
} else {
return true;
@ -138,7 +143,7 @@ export class DirectLinkingComponent {
err => {
this.validInput = this.isValidInput(null);
//console.log("An error occured")
this.handleError("Error getting "+this.getEntityName(resultType, false)+" by id: " + id, err);
this.handleError("Error getting "+this.getEntityName(resultType, false, true)+" by id: " + id, err);
}));
}
@ -151,7 +156,6 @@ export class DirectLinkingComponent {
entity.type = "project";
entity.title = project.projectName;
entity.project = new ClaimProject();
entity.project.url = properties.searchLinkToProject + entity.id;
entity.project.acronym = project.projectAcronym;
entity.project.code = project.code;
entity.project.endDate = project.endDate;
@ -175,7 +179,15 @@ export class DirectLinkingComponent {
console.error("Direct Linking Page: " + message, error);
}
private getEntityName (entityType:string, plural:boolean) {
return StringUtils.getEntityName(entityType, plural);
private getEntityName (entityType:string, plural:boolean, full:boolean): string {
if(entityType == "publication") {
return "publication" + (plural ? "s" : "");
} else if(entityType == "dataset") {
return (full ? "research data" : ("dataset" + (plural ? "s" : "")));
} else if(entityType == "software") {
return "software";
} else if(entityType == "other") {
return (full ? ("other research product" + (plural ? "s" : "")) : "other");
}
}
}

View File

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

View File

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

View File

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

View File

@ -14,53 +14,46 @@ import {
Message
} from "../../claim-utils/claimHelper.class";
import {UserManagementService} from "../../../services/user-management.service";
import {Subscriber, timer} from "rxjs";
import {map} from "rxjs/operators";
import {LogService} from "../../../utils/log/log.service";
import {Subscriber} from "rxjs";
@Component({
selector: 'claim-insert',
template: `
<div (click)="insert()" class="uk-card-footer uk-flex uk-flex-center clickable"
[class.uk-tile-primary]="(results.length > 0 && (sources.length > 0 || inlineEntity))"
[class.uk-background-muted]="!(results.length > 0 && (sources.length > 0 || inlineEntity))"
[class.uk-disabled]="!(results.length > 0 && (sources.length > 0 || inlineEntity))">
<button class="uk-flex uk-flex-middle uk-button uk-button-text"
[class.uk-disabled]="!(results.length > 0 && (sources.length > 0 || inlineEntity))"
[disabled]="!(results.length > 0 && (sources.length > 0 || inlineEntity))">
<icon name="link" visuallyHidden="link" [flex]="true"></icon>
<div class="uk-width-expand uk-margin-small-left">CONFIRM LINKING</div>
</button>
</div>
<modal-loading [message]="'Please wait...'">
<div *ngIf="claimsJob">
<div *ngIf="claimsJob && claimsJob.insertedIds.length <1" class="uk-text-meta uk-text-small">
Initiating process....</div>
<div *ngIf="claimsJob && claimsJob.insertedIds.length >0" class="uk-text-meta uk-text-small">
{{claimsJob.insertedIds.length}} out of {{claims2Insert}} links created.</div>
<div *ngIf="feedRecordsJob && feedRecordsJob.insertedIds.length >0" class="uk-text-meta uk-text-small">
{{feedRecordsJob.insertedIds.length}} out of {{records2Insert}} records added in the index...</div>
<div *ngIf="claimsJob.status != 'COMPLETE'" class="uk-text-meta uk-text-small">
Please don't close the window, process is ongoing...</div>
<div class="uk-width-1-1">
<modal-loading [message]="'Please wait...'"></modal-loading>
<modal-alert (alertOutput)="confirmClose()">
<h4 class="modal-title uk-text-bold " id="myModalLabel">Confirmation notice</h4>
<p>All the links you provided will be published in the OpenAIRE platform. <br>
Please make sure that the information is valid.<br>
<span class="uk-text-bold">In some cases, links take some time to be published.</span><br>
For more information please check the linking status in My-Links page.
</p>
<p>
Do you confirm the information you provide is valid?
</p>
</modal-alert>
<div class="uk-clearfix">
<div>
<div *ngIf="!claiming " (click)="insert()" style="width: 350px;"
[class]="getButtonClass()">CONFIRM LINKING
<span [class]="(defaultColors?'':' uk-margin-small-top ')+'uk-icon uk-float-right uk-text-bold uk-margin-small-right'">
<svg width="30" height="30" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"
icon="chevron-right" ratio="1.5"><polyline fill="none" stroke="#000" stroke-width="1.03"
points="7 4 13 10 7 16"></polyline></svg>
</span>
</div>
</div>
</div>
</modal-loading>
<modal-alert (alertOutput)="confirmClose()">
<h4 class="modal-title uk-text-bold " id="myModalLabel">Confirmation notice</h4>
<p>All the links you provided will be published in the OpenAIRE platform. <br>
Please make sure that the information is valid.<br>
<span class="uk-text-bold">In some cases, links take some time to be published.</span><br>
For more information please check the linking status in My-Links page.
</p>
<p>
Do you confirm the information you provide is valid?
</p>
</modal-alert>
</div>
`
})
export class ClaimInsertComponent {
constructor(private claimService: ClaimsService, private _router: Router, private route: ActivatedRoute,
private userManagementService: UserManagementService, private _logService: LogService) {
private userManagementService: UserManagementService) {
}
subscriptions = [];
ngOnDestroy() {
@ -74,32 +67,6 @@ export class ClaimInsertComponent {
this.subscriptions.push(this.route.queryParams.subscribe(params => {
this.params = params;
}));
if(localStorage.getItem(this.localStoragePrefix + "claimsJob")){
this.claimsJob = JSON.parse(localStorage.getItem(this.localStoragePrefix + "claimsJob"));
this.feedRecordsJob = JSON.parse(localStorage.getItem(this.localStoragePrefix + "feedRecordsJob"));
if(this.claimsJob.status != "COMPLETE"){
this.claiming = true;
let loadingTimerSubscription = timer(0, 1000).pipe(
map(() => {
if(this.loading) {
this.loading.open();
loadingTimerSubscription.unsubscribe();
}
})
).subscribe();
this.subscriptions.push(loadingTimerSubscription);
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 = {};
@ -124,16 +91,15 @@ export class ClaimInsertComponent {
private errorInClaims: ClaimRecord2Insert[] = [];
private insertedRecords = [];
private errorInRecords = [];
public claimsJob;
public feedRecordsJob;
public claims2Insert;
public records2Insert
infoToLog = [];
public insert() {
this.confirmOpen();
this.confirmOpen();
}
saveAndNavigate(){
this.saveLocalStorage();
localStorage.setItem(this.localStoragePrefix + "results", JSON.stringify(this.results));
if (this.sources != null) {
localStorage.setItem(this.localStoragePrefix + "sources", JSON.stringify(this.sources));
}
this._router.navigate(['/user-info'], {
queryParams: {
"errorCode": LoginErrorCodes.NOT_VALID,
@ -147,7 +113,6 @@ export class ClaimInsertComponent {
this.errorInClaims = [];
this.insertedRecords = [];
this.errorInRecords = [];
this.infoToLog = [];
this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
if (!user) {
this.saveAndNavigate();
@ -193,11 +158,10 @@ export class ClaimInsertComponent {
} else if (entity.project) {
claims.push(ClaimInsertComponent.createProjectClaim(result, entity, user.email, dashboard));
}
this.infoToLog.push([ result.title?result.title: result.id, entity.title?entity.title:entity.id]);
}
if (this.inlineEntity) {
this.infoToLog.push([ this.inlineEntity.title?this.inlineEntity.title: this.inlineEntity.id, entity.title?entity.title:entity.id]);
if (this.inlineEntity.result) {
if (entity.result) {
@ -220,15 +184,12 @@ export class ClaimInsertComponent {
//first call direct index service - when call is done (success or error) call isertBulkClaims method to insert claims in DB
// console.log("directclaims");
// console.log(directclaims);
if (directclaims.length > 0/* && this.properties.environment != "development"*/){
if (directclaims.length > 0 && this.properties.environment != "development"){
this.subscriptions.push(this.claimService.insertDirectRecords(directclaims, this.properties.claimsAPIURL).subscribe(
data => {
this.feedRecordsJob = data.data;
this.records2Insert = directclaims.length;
console.log(data);
// this.insertedRecords = data.insertedIds;
//
// this.errorInRecords = data.errorInClaims;
this.insertedRecords = data.insertedIds;
this.errorInRecords = data.errorInClaims;
this.isertBulkClaims(claims);
},
err => {
@ -236,12 +197,12 @@ export class ClaimInsertComponent {
if (err.code && err.code == 403) {
this.saveAndNavigate();
}
/* if (err.insertedIds && err.insertedIds.length > 0) {
if (err.insertedIds && err.insertedIds.length > 0) {
this.insertedRecords = err.insertedIds;
}
if (err.errorInClaims && err.errorInClaims.length > 0) {
this.errorInRecords = err.errorInClaims;
}*/
}
this.isertBulkClaims(claims);
ClaimInsertComponent.handleError("Error inserting direct records: " + JSON.stringify(directclaims), err);
@ -255,24 +216,30 @@ export class ClaimInsertComponent {
}
private isertBulkClaims(claims: ClaimRecord2Insert[]) {
console.log("claims");
console.log(claims);
this.errors.splice(0, this.errors.length);
this.subscriptions.push(this.claimService.insertBulkClaims(claims, this.properties.claimsAPIURL).subscribe(
data => {
this.claims2Insert = claims.length;
this.claimsJob = data.data;
if(this.properties.logServiceUrl) {
for(let info of this.infoToLog) {
this.subscriptions.push(this._logService.logLink(this.properties, info[0],info[1]).subscribe(res => {
}));
}
this.insertedClaims = data.insertedIds;
this.errorInClaims = data.errorInClaims;
//TODO remove - testing having errors in claims
// this.insertedClaims.pop();
// this.insertedClaims.pop();
// this.errorInClaims.push(claims[1]);
// this.insertedClaims.splice(0,this.insertedClaims.length);
// this.errorInClaims = claims;
//remove till here
if (claims.length != this.insertedClaims.length) {
let error: ClaimsErrorMessage = new ClaimsErrorMessage();
error.type = "claimServiceFail2Insert";
error.inserted = this.insertedClaims.length;
error.failed = this.errorInClaims.length;
this.createErrorMessagesPerEntity((this.insertedClaims.length == 0));
this.errors.push(error);
}
this.saveLocalStorage();
let timerSubscription = timer(0, 10000).pipe(
map(() => {
this.getStatus(); // load data contains the http request
})
).subscribe();
this.subscriptions.push(timerSubscription);
this.afterclaimsInsertion();
},
err => {
err = err && err.error?err.error:err;
@ -375,17 +342,14 @@ export class ClaimInsertComponent {
}
private afterclaimsInsertion() {
this.claiming = false;
this.loading.close();
this.loading.close();
this.claiming = false;
if (this.errorInClaims.length == 0 && this.insertedClaims.length > 0) {
localStorage.removeItem(this.localStoragePrefix + "sources");
localStorage.removeItem(this.localStoragePrefix + "results");
localStorage.removeItem(this.localStoragePrefix + "claimsJob");
localStorage.removeItem(this.localStoragePrefix + "feedRecordsJob");
this._router.navigate([this.properties.myClaimsLink], {queryParams: this.params});
this._router.navigate(['/myclaims'], {queryParams: this.params});
}
}
@ -560,77 +524,10 @@ export class ClaimInsertComponent {
}
if(this.defaultColors){
buttonClass+=" linksbaskettitles uk-padding-small ";
}else{
buttonClass+=" uk-button uk-button-large ";
}
return buttonClass + "uk-text-center ";
}
getStatus(){
if(this.feedRecordsJob && ! (this.feedRecordsJob.status == "COMPLETE" || this.feedRecordsJob.status == "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 { SharedModule } from '../../../../openaireLibrary/shared/shared.module';
import { SharedModule } from '../../../shared/shared.module';
import {AlertModalModule} from '../../../utils/modal/alertModal.module';
import {LoadingModalModule} from '../../../utils/modal/loadingModal.module';
import {ClaimInsertComponent} from './insertClaim.component';
import {ClaimServiceModule} from '../../claim-utils/service/claimsService.module';
import {IconsModule} from "../../../utils/icons/icons.module";
import {LogServiceModule} from "../../../utils/log/LogService.module";
@NgModule({
imports: [
SharedModule, AlertModalModule, LoadingModalModule, ClaimServiceModule, IconsModule, LogServiceModule
SharedModule, AlertModalModule, LoadingModalModule, ClaimServiceModule
],
declarations: [ClaimInsertComponent],
exports:[ ClaimInsertComponent]

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
import {NgModule} from '@angular/core';
import {SharedModule} from '../../../../openaireLibrary/shared/shared.module';
import {SharedModule} from '../../../shared/shared.module';
import {ClaimEntityTitleComponent} from "./ClaimEntityTitle.component";
import {ClaimEntityResultMetadataComponent} from "./ClaimEntityResultMetadata.component";
import {ClaimEntityProjectMetadataComponent} from "./ClaimEntityProjectMetadata.component";

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

View File

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

View File

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

View File

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

View File

@ -12,10 +12,10 @@ import {HelperFunctions} from "../../../utils/HelperFunctions.class";
})
export class MetadataPreviewComponent {
/* showSources = true;
showLinksTo = true;*/
// showErrors = true;
// showWarnings = true;
showSources = true;
showLinksTo = true;
showErrors = true;
showWarnings = true;
@Input() results: ClaimEntity[];
@Input() sources: ClaimEntity[];
@Input() title: string = "Research Results";
@ -40,10 +40,10 @@ export class MetadataPreviewComponent {
ngOnInit() {
this.setEmbargoEndDates();
/* if (this.inlineEntity) {
if (this.inlineEntity) {
this.showSources = true;
this.showLinksTo = true;
}*/
}
this.runValidation(true);
}
setEmbargoEndDates(){

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
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 {HelpContentService} from '../../services/help-content.service';
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 {SearchInputComponent} from '../../sharedComponents/search-input/search-input.component';
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({
selector: 'class-help-contents',
@ -26,7 +27,7 @@ export class ClassHelpContentsComponent implements OnInit {
private selectedPageContents: string[] = [];
public checkboxes: CheckDivHelpContent[] = [];
public divHelpContents: DivHelpContent[] = [];
public formGroup: UntypedFormGroup;
public formGroup: FormGroup;
public pages: Page[];
public checkboxAll: boolean = false;
public filters: PageHelpContentFilterOptions = {id: '', active: null, text: new RegExp('')};
@ -39,12 +40,12 @@ export class ClassHelpContentsComponent implements OnInit {
public page: Page;
public properties: EnvProperties = properties;
public showLoading: boolean = true;
public filterForm: UntypedFormControl;
public filterForm: FormControl;
private subscriptions: any[] = [];
public selectedKeyword: string;
@ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent;
constructor(private element: ElementRef, private route: ActivatedRoute, private router: Router,
private _helpService: HelpContentService, private _fb: UntypedFormBuilder, private sanitizer: DomSanitizer,
private _clearCacheService: ClearCacheService) {
constructor(private element: ElementRef, private route: ActivatedRoute, private router: Router, private _helpService: HelpContentService, private _fb: FormBuilder, private sanitizer: DomSanitizer) {
}
ngOnInit() {
@ -141,9 +142,17 @@ export class ClassHelpContentsComponent implements OnInit {
this.confirmModalOpen();
}
public confirmDeleteSelectedPageHelpContents() {
this.selectedPageContents = this.getSelectedPageHelpContents();
this.confirmModalOpen();
}
private confirmModalOpen() {
this.alertModalDeletePageHelpContents.cancelButton = true;
this.alertModalDeletePageHelpContents.okButton = true;
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.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.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._clearCacheService.clearCache("Class text texts deleted");
},
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[]) {
this.subscriptions.push(this._helpService.toggleDivHelpContents(ids, status, this.properties.adminToolsAPIURL, this.portal).subscribe(
() => {
for (let id of ids) {
let i = this.checkboxes.findIndex(_ => _.divHelpContent._id == id);
this.checkboxes[i].divHelpContent.isActive = status;
if (!Session.isLoggedIn()) {
this.router.navigate(['/user-info'], {
queryParams: {
'errorCode': LoginErrorCodes.NOT_VALID,
'redirectUrl': this.router.url
}
this.countClassHelpContents();
this.applyCheck(false);
NotificationHandler.rise('Page content(s) has been <b>successfully updated</b>');
this._clearCacheService.clearCache("class help text's status changed");
},
error => this.handleUpdateError('System error changing the status of the selected page content(s)', error)
));
});
} else {
this.subscriptions.push(this._helpService.toggleDivHelpContents(ids, status, this.properties.adminToolsAPIURL, this.portal).subscribe(
() => {
for (let id of ids) {
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();
}
handleError(message: string, error = null) {
if(error) {
console.log('Server responded: ' + error);
}
NotificationHandler.rise(message, 'danger');
handleError(message: string, error) {
UIkit.notification(message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
console.log('Server responded: ' + error);
this.showLoading = false;
}
handleUpdateError(message: string, error = null) {
if(error) {
console.log('Server responded: ' + error);
}
NotificationHandler.rise(message, 'danger');
handleUpdateError(message: string, error) {
UIkit.notification(message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
console.log('Server responded: ' + error);
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() {
let checked = (this.getSelectedPageHelpContents().length != this.checkboxes.length);
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 {AlertModalModule} from '../../utils/modal/alertModal.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 {InputModule} from '../../sharedComponents/input/input.module';
import {SearchInputModule} from '../../sharedComponents/search-input/search-input.module';
import {IconsModule} from '../../utils/icons/icons.module';
import {IconsService} from '../../utils/icons/icons.service';
import {add, arrow_left, edit, remove} from '../../utils/icons/icons';
import {LoadingModule} from '../../utils/loading/loading.module';
import {HTMLToStringPipeModule} from '../../utils/pipes/HTMLToStringPipe.module';
import {ClassHelpContentsRoutingModule} from './class-help-contents-routing.module';
@ -19,9 +21,8 @@ import {PageContentModule} from '../sharedComponents/page-content/page-content.m
@NgModule({
imports: [
ClassHelpContentsRoutingModule,
CommonModule, RouterModule, FormsModule, SafeHtmlPipeModule,
AlertModalModule, ReactiveFormsModule, MatSlideToggleModule, AdminToolServiceModule, InputModule,
AlertModalModule, ReactiveFormsModule, MatSlideToggleModule, AdminToolServiceModule, InputModule, ClassHelpContentsRoutingModule,
SearchInputModule, IconsModule, LoadingModule, HTMLToStringPipeModule, PageContentModule
],
declarations: [
@ -30,4 +31,8 @@ import {PageContentModule} from '../sharedComponents/page-content/page-content.m
providers: [IsCommunity, ConnectAdminLoginGuard],
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 header>
<admin-tabs tab="entity" [portal]="portal" [type]="type"></admin-tabs>
<ul *ngIf="!isPortalAdministrator" class="uk-subnav uk-subnav-pill uk-margin-medium-top">
<li [class.uk-active]="filterForm.get('status').value === 'all'"><a
(click)="filterForm.get('status').setValue('all')"><span
class="title">All entities</span></a></li>
<li [class.uk-active]="filterForm.get('status').value === 'enabled'"><a
(click)="filterForm.get('status').setValue('enabled')"><span class="title">Enabled</span></a></li>
<li [class.uk-active]="filterForm.get('status').value === 'disabled'"><a
(click)="filterForm.get('status').setValue('disabled')"><span class="title">Disabled</span></a></li>
</ul>
</div>
<div actions>
<div class="uk-section-xsmall">
<div class="uk-flex uk-flex-right@m uk-flex-center uk-flex-wrap uk-flex-middle uk-grid" uk-grid>
<div search-input [expandable]="true" [searchControl]="filterForm.get('keyword')" searchInputClass="outer" placeholder="Search entity"
[disabled]="showLoading" class="uk-width-1-3@xl uk-width-2-5@l uk-width-1-2@m uk-width-1-1"></div>
<div *ngIf="isPortalAdministrator">
<button class="uk-button uk-button-default uk-flex uk-flex-middle" (click)="newEntity()"
[disabled]="showLoading" [class.uk-disabled]="showLoading">
<icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left uk-text-bold uk-text-uppercase">Add entity</span>
</button>
</div>
</div>
</div>
</div>
<div page-content class="admin-pages">
<div header>
<admin-tabs tab="entity" [portal]="portal"></admin-tabs>
<div *ngIf="!showLoading" class="uk-grid" uk-grid>
<div class="uk-width-1-1">
<ul *ngIf="!isPortalAdministrator" class="uk-subnav uk-subnav-pill">
<li [class.uk-active]="filterForm.get('status').value === 'all'"><a
(click)="filterForm.get('status').setValue('all')"><span
class="title">All entities</span></a></li>
<li [class.uk-active]="filterForm.get('status').value === 'enabled'"><a
(click)="filterForm.get('status').setValue('enabled')"><span class="title">Enabled</span></a></li>
<li [class.uk-active]="filterForm.get('status').value === 'disabled'"><a
(click)="filterForm.get('status').setValue('disabled')"><span class="title">Disabled</span></a></li>
</ul>
</div>
<div class="uk-width-1-1 uk-flex uk-flex-right@m uk-flex-center uk-flex-wrap uk-flex-middle uk-grid uk-margin-remove-top"
uk-grid>
<div #searchInputComponent search-input [control]="filterForm.controls.keyword" [showSearch]="false"
placeholder="Search entity"
[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 *ngIf="isPortalAdministrator">
<a (click)="newEntity()"
class="uk-flex uk-flex-middle uk-text-uppercase">
<button class="large uk-icon-button uk-button-secondary">
<icon name="add"></icon>
</button>
<button class="uk-button uk-button-link uk-margin-small-left uk-text-secondary">Add 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 class="uk-section uk-section-small uk-position-relative" style="min-height: 60vh">
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
<ng-container *ngIf="!showLoading">
<div *ngIf="checkboxes.length == 0"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-top uk-margin-bottom uk-text-bold">
<div>No entities found</div>
</div>
<table *ngIf="checkboxes.length > 0 " class="uk-table uk-table-striped uk-table-large">
<thead>
<tr class="uk-child-width-1-3">
<th *ngIf="!portal">
<label>
<input id="checkAll" type="checkbox" (click)="selectAll()" class="uk-checkbox"
[ngModel]="getSelectedEntities().length ==checkboxes.length"/>
</label>
<span class="uk-margin-left">
<button class="uk-button uk-button-link" [class.uk-disabled]="getSelectedEntities().length == 0" [disabled]="getSelectedEntities().length == 0">
Bulk Actions ({{getSelectedEntities().length}})
</button>
<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 (click)="confirmDeleteSelectedEntities()"><i></i>Delete</a>
</li>
</ul>
</div>
</span>
</th>
<th>Name</th>
<th *ngIf="!isPortalAdministrator">Status</th>
<th *ngIf="isPortalAdministrator">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let check of checkboxes; let i=index">
<td *ngIf="!portal">
<input id="{{check.entity._id}}" class="uk-checkbox" type="checkbox"
name="entitiescb[]" value="{{check.entity._id}}" [(ngModel)]="check.checked">
</td>
<td>
<div class="name" href="#">{{check.entity.name}}</div>
</td>
<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 *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
<div *ngIf="!showLoading">
<table *ngIf="checkboxes.length > 0 " class="uk-table uk-table-striped uk-table-hover uk-table-large">
<thead class="uk-card-header">
<tr>
<th class="uk-width-small"></th>
<th>Name</th>
<th *ngIf="!isPortalAdministrator">Status</th>
<th *ngIf="!isPortalAdministrator">Enable/Disable</th>
<th *ngIf="isPortalAdministrator">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let check of checkboxes; let i=index">
<td><input id="{{check.entity._id}}" class="checkBox" type="checkbox"
name="entitiescb[]" value="{{check.entity._id}}" [(ngModel)]="check.checked">
</td>
<td>
<div class="name" href="#">{{check.entity.name}}</div>
</td>
<td *ngIf="!isPortalAdministrator">
<div class="name" href="#">{{check.entity.isEnabled ? "Enabled" : "Disabled"}}</div>
</td>
<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="actions" href="#">
<icon class="clickable" name="edit" (click)="editEntity(i)"></icon>
<icon class="clickable uk-margin-small-left" [customClass]="'uk-text-danger'" name="remove" (click)="confirmDeleteEntity(check.entity._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 entities found</div>
</div>
</div>
</div>
</div>
<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>
<div input [formInput]="entityForm.get('name')" placeholder="Entity Name"></div>
<div input [formInput]="entityForm.get('pid')" placeholder="Entity Pid"></div>
<div dashboard-input [formInput]="entityForm.get('name')"
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>
</modal-alert>
<modal-alert #relatedPages [overflowBody]="false" (alertOutput)="continueToggling($event)" classTitle="uk-background-primary uk-light"></modal-alert>
<modal-alert #deleteModal [overflowBody]="false" (alertOutput)="confirmedDeleteEntities($event)" classTitle="uk-background-primary uk-light"></modal-alert>
<modal-alert #relatedPages (alertOutput)="continueToggling($event)"></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 {ActivatedRoute, Router} from '@angular/router';
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 {Portal} from '../../utils/entities/adminTool/portal';
import {EnvProperties} from '../../utils/properties/env-properties';
@ -10,14 +10,11 @@ import {UserManagementService} from '../../services/user-management.service';
import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {AlertModal} from "../../utils/modal/alert";
import {SearchInputComponent} from "../../sharedComponents/search-input/search-input.component";
import {StringUtils} from "../../utils/string-utils.class";
import {Title} from "@angular/platform-browser";
import {StakeholderService} from '../../monitor/services/stakeholder.service';
import {CommunityService} from "../../connect/community/community.service";
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";
declare var UIkit;
@Component({
selector: 'entities',
@ -34,17 +31,13 @@ export class EntitiesComponent implements OnInit {
public entities: Entity[] = [];
public entityForm: UntypedFormGroup;
public entityForm: FormGroup;
private searchText: RegExp = new RegExp('');
public keyword = '';
public communities: Portal[] = [];
public portal: string;
public type: any;
public name: string;
public entity: CommunityInfo | Stakeholder;
public showLogo: boolean = true;
public toggleIds: string[];
public toggleStatus: boolean;
@ -52,17 +45,16 @@ export class EntitiesComponent implements OnInit {
public showLoading = true;
public isPortalAdministrator = null;
public filterForm: UntypedFormGroup;
public filterForm: FormGroup;
private subscriptions: any[] = [];
private index: number;
public selectedKeyword: string;
@ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent;
constructor(private element: ElementRef, private route: ActivatedRoute,
private _router: Router, private title: Title,
private _helpContentService: HelpContentService,
private userManagementService: UserManagementService, private _fb: UntypedFormBuilder,
private communityService: CommunityService,
private stakeholderService: StakeholderService,
private _clearCacheService: ClearCacheService) {
private userManagementService: UserManagementService, private _fb: FormBuilder) {
}
ngOnInit() {
@ -80,28 +72,9 @@ export class EntitiesComponent implements OnInit {
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];
if (this.route.snapshot.data.portal) {
this.name = StringUtils.capitalize(this.portal);
this.title.setTitle(StringUtils.capitalize(this.portal) + ' | Entities');
} else if (this.route.snapshot.params[this.route.snapshot.data.param]) {
this.type = this.route.snapshot.data.param;
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');
}
}));
}
this.title.setTitle(this.portal.toUpperCase() + ' | Entities');
} else {
this.title.setTitle('Administrator Dashboard | Entities');
}
@ -189,6 +162,8 @@ export class EntitiesComponent implements OnInit {
}
private confirmDeleteEntitiesModalOpen() {
this.deleteModal.cancelButton = true;
this.deleteModal.okButton = true;
this.deleteModal.alertTitle = 'Delete Confirmation';
this.deleteModal.message = 'Are you sure you want to delete the selected entity(-ies)?';
this.deleteModal.okButtonText = 'Yes';
@ -200,10 +175,12 @@ export class EntitiesComponent implements OnInit {
this._helpContentService.deleteEntities(this.selectedEntities, this.properties.adminToolsAPIURL).subscribe(
_ => {
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._clearCacheService.clearCache("entities deleted");
this._clearCacheService.purgeBrowserCache("entities deleted", this.portal);
},
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) {
this.editModal.cancelButton = true;
this.editModal.okButton = true;
this.editModal.okButtonLeft = false;
this.editModal.alertTitle = title;
this.editModal.okButtonText = yesBtn;
@ -238,24 +217,28 @@ export class EntitiesComponent implements OnInit {
public entitySaveConfirmed(data: any) {
this.showLoading = true;
if (this.entityForm.getRawValue()._id) {
if (this.entityForm.value._id) {
this._helpContentService.updateEntity(
<Entity>this.entityForm.getRawValue(), this.properties.adminToolsAPIURL).subscribe(
<Entity>this.entityForm.value, this.properties.adminToolsAPIURL).subscribe(
entity => {
this.entityUpdatedSuccessfully(entity);
NotificationHandler.rise('Entity <b>' + entity.name + '</b> has been <b>successfully updated</b>');
this._clearCacheService.clearCache("entity updated");
this._clearCacheService.purgeBrowserCache("entity updated", this.portal);
UIkit.notification('Entity <b>' + entity.name + '</b> has been <b>successfully updated</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
},
error => this.handleUpdateError('System error updating entity', error)
);
} else {
this._helpContentService.saveEntity(<Entity>this.entityForm.getRawValue(), this.properties.adminToolsAPIURL).subscribe(
this._helpContentService.saveEntity(<Entity>this.entityForm.value, this.properties.adminToolsAPIURL).subscribe(
entity => {
this.entitySavedSuccessfully(entity);
NotificationHandler.rise('Entity <b>' + entity.name + '</b> has been <b>successfully created</b>');
this._clearCacheService.clearCache("entity saved");
this._clearCacheService.purgeBrowserCache("entity saved", this.portal)
UIkit.notification('Entity <b>' + entity.name + '</b> has been <b>successfully created</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
},
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);
}
handleError(message: string, error = null) {
if(error) {
console.log('Server responded: ' + error);
}
NotificationHandler.rise(message, 'danger');
handleError(message: string, error) {
UIkit.notification(message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
console.log('Server responded: ' + error);
this.showLoading = false;
}
handleUpdateError(message: string, error = null) {
if (!error) {
handleUpdateError(message: string, error) {
if (error == null) {
this.entityForm = this._fb.group({
pid: ['', Validators.required],
name: ['', Validators.required],
@ -312,9 +297,13 @@ export class EntitiesComponent implements OnInit {
_id: ''
});
} else {
UIkit.notification(message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
console.log('Server responded: ' + error);
}
NotificationHandler.rise(message, 'danger');
this.showLoading = false;
}
@ -330,6 +319,8 @@ export class EntitiesComponent implements OnInit {
}
private confirmRelatedPagesModalOpen() {
this.relatedPages.cancelButton = true;
this.relatedPages.okButton = true;
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.okButtonText = 'Yes';
@ -345,13 +336,20 @@ export class EntitiesComponent implements OnInit {
this.checkboxes[i].entity.isEnabled = this.toggleStatus;
}
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)
);
}
public onSearchClose() {
this.selectedKeyword = this.filterForm.get('keyword').value;
}
public reset() {
this.selectedKeyword = null;
this.searchInputComponent.reset()
}
selectAll() {
let checked = (this.getSelectedEntities().length != this.checkboxes.length);
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 {SearchInputModule} from "../../sharedComponents/search-input/search-input.module";
import {IconsModule} from "../../utils/icons/icons.module";
import {IconsService} from "../../utils/icons/icons.service";
import {add, edit, remove} from "../../utils/icons/icons";
import {LoadingModule} from "../../utils/loading/loading.module";
import {LogoUrlPipeModule} from "../../utils/pipes/logoUrlPipe.module";
@NgModule({
imports: [
EntitiesRoutingModule,
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],
exports: [EntitiesComponent]
})
export class EntitiesModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([add, edit, remove]);
}
}

View File

@ -1,82 +1,87 @@
<div page-content>
<div header>
<div class="uk-section-xsmall uk-margin-top uk-container">
<div class="uk-flex-middle uk-grid" uk-grid>
<div class="uk-width-expand">
<a routerLink="../" [queryParams]=" { 'pageId': pageId }" class="uk-flex uk-flex-middle uk-h5 uk-link-reset">
<span class="uk-margin-right">
<icon name="west" ratio="1.7" [flex]="true"></icon>
</span>
<h1 *ngIf="page" class="uk-h5 uk-margin-remove">
{{page.name}} - {{pageHelpContent ? 'Update ' : 'Add new '}} page help text
<span *ngIf="myForm.dirty" class="uk-text-large"> (unsaved changes)</span>
</h1>
</a>
</div>
<div class="uk-width-auto">
<button class="uk-button uk-button-default uk-margin-right"
(click)="resetCustom()" [class.uk-disabled]="!myForm.dirty"
[disabled]="!myForm.dirty || showLoading">Reset
</button>
<button class="uk-button uk-button-primary" [class.uk-disabled]="myForm.invalid || !myForm.dirty || myForm.disabled"
(click)="saveCustom()" [disabled]="myForm.invalid ||!myForm.dirty || myForm.disabled || showLoading">Save
</button>
</div>
</div>
<div class="uk-margin-top">
<a routerLink="../" [queryParams]=" { 'pageId': pageId }"
class="uk-text-secondary uk-text-uppercase uk-text-bold uk-text-small">
<span class="uk-icon-button uk-icon small uk-button-secondary">
<icon name="arrow_left"></icon>
</span>
<span class="space">
Go back to page help texts list
</span>
</a>
</div>
</div>
<div inner>
<div class="uk-container">
<div *ngIf="myForm" style="min-height: 60vh"
class="uk-section uk-section-small uk-position-relative">
<div *ngIf="showLoading" class="uk-position-center">
<loading *ngIf="showLoading"></loading>
<div class="uk-card-header">
<div class="uk-flex uk-flex-middle uk-child-width-1-1 uk-child-width-1-2@m uk-grid" uk-grid>
<div>
<div class="uk-text-small uk-text-muted"> {{pageHelpContent ? 'Update ' : 'Add new '}} page help text</div>
<div>
<span *ngIf="page" class="uk-text-bold">{{page.name}}</span>
<span *ngIf="myForm.dirty"> (unsaved changes)</span>
</div>
</div>
<div class=" uk-flex uk-flex-right">
<button (click)="resetCustom()" [disabled]="showLoading || !myForm.dirty"
class="uk-button uk-button-secondary outlined uk-margin-small-right">Reset
</button>
<button (click)="saveCustom()" class="uk-button uk-button-secondary uk-margin-small-right"
[disabled]="showLoading || !myForm.dirty || myForm.invalid ">Save
</button>
</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 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>

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 {UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {Page} from '../../utils/entities/adminTool/page';
import {HelpContentService} from '../../services/help-content.service';
import {EnvProperties} from '../../utils/properties/env-properties';
@ -8,9 +8,8 @@ import {properties} from '../../../../environments/environment';
import {Subscriber, Subscription, zip} from 'rxjs';
import {HelperFunctions} from '../../utils/HelperFunctions.class';
import {PageHelpContent} from '../../utils/entities/adminTool/page-help-content';
import {ClearCacheService} from "../../services/clear-cache.service";
import {NotificationHandler} from "../../utils/notification-handler";
import {CKEditorComponent} from "ng2-ckeditor";
declare var UIkit;
@Component({
selector: 'page-content-form',
@ -18,9 +17,8 @@ import {CKEditorComponent} from "ng2-ckeditor";
})
export class PageContentFormComponent implements OnInit {
myForm: UntypedFormGroup;
myForm: FormGroup;
portal: string;
parentClass: string;
pageId: string;
pageContentId: string;
page: Page;
@ -30,25 +28,23 @@ export class PageContentFormComponent implements OnInit {
public showLoading: boolean = true;
private subs: Subscription[] = [];
public pageHelpContent: PageHelpContent;
@ViewChild('ckEditor') ckEditor: CKEditorComponent;
constructor(private route: ActivatedRoute, private _router: Router, private _fb: UntypedFormBuilder,
private cdr: ChangeDetectorRef, private _helpContentService: HelpContentService,
private _clearCacheService: ClearCacheService) {
constructor(private route: ActivatedRoute, private _router: Router, private _fb: FormBuilder, private _helpContentService: HelpContentService) {
}
ngOnInit() {
this.portal = (this.route.snapshot.data.portal) ? this.route.snapshot.data.portal : this.route.snapshot.params[this.route.snapshot.data.param];
this.parentClass = this.route.snapshot.data.parentClass;
this.subs.push(this.route.queryParams.subscribe(params => {
HelperFunctions.scroll();
this.pageId = params['pageId'];
this.myForm = this.form;
this.pageContentId = params['pageContentId'];
if (!this.pageId) {
this._router.navigate(['../'], {relativeTo: this.route});
}
this.getInfo(this.pageId);
this.subs.push(this.route.params.subscribe(params => {
this.portal = (this.route.snapshot.data.portal) ? this.route.snapshot.data.portal : this.route.snapshot.params[this.route.snapshot.data.param];
this.subs.push(this.route.queryParams.subscribe(params => {
HelperFunctions.scroll();
this.pageId = params['pageId'];
this.myForm = this.form;
this.pageContentId = params['pageContentId'];
if (!this.pageId) {
this._router.navigate(['../'], {relativeTo: this.route});
}
this.getInfo(this.pageId);
}));
}));
}
@ -70,10 +66,16 @@ export class PageContentFormComponent implements OnInit {
this._router.navigate(['../'], {relativeTo: this.route});
}
let countPageContents = results[1] ? results[1].length : 0;
console.log(results[1]);
for (let content of (results[1] as Array<PageHelpContent>)) {
// if(content.page['_id'] == pageId){
// countPageContents++;
if (this.pageContentId && this.pageContentId == content._id) {
this.pageHelpContent = content;
// this.pageHelpContent.page = pageId;
// this.pageHelpContent.portal = this.communityPid;
}
// }
}
this.setOptions(this.page, countPageContents + (this.pageHelpContent ? 0 : 1));
if (!this.pageContentId) {
@ -83,30 +85,53 @@ export class PageContentFormComponent implements OnInit {
this.updateForm(this.pageHelpContent);
}
this.showLoading = false;
this.initCKEditor();
},
error => this.handleError('System error retrieving page with id: ' + pageId, 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 getPage(pageId: string) {
this.subs.push(this._helpContentService.getPageByPortal(pageId,this.properties.adminToolsAPIURL, this.communityPid).subscribe(
page => {
if(this.properties.adminToolsPortalType != page.portalType) {
this._router.navigate(['../'], {relativeTo: this.route});
} else {
this.page = page;
this.getPageContents(pageId);
}
},
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) {
this.pageHelpContent = pageHelpContent;
this.myForm = this.form;
@ -182,24 +207,32 @@ export class PageContentFormComponent implements OnInit {
this.myForm.markAsPristine();
}
handleError(message: string, error = null) {
if(error) {
console.error('Server responded: ' + error);
}
NotificationHandler.rise(message, 'danger');
handleError(message: string, error) {
UIkit.notification(message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
console.error('Server responded: ' + error);
this.showLoading = false;
}
public saveCustom() {
if (this.myForm.valid) {
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(
_ => {
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.showLoading = false;
this._clearCacheService.clearCache("page help content saved");
},
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() {
this.showLoading = true;
this.updateForm(this.pageHelpContent);
this.showLoading = false;
}
handleUpdateError(message: string, error = null) {
if(error) {
console.error('Server responded: ' + error);
}
NotificationHandler.rise(message, 'danger');
handleUpdateError(message: string, error) {
UIkit.notification(message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
console.error('Server responded: ' + error);
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 {FormsModule, ReactiveFormsModule} from '@angular/forms';
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 {AdminToolServiceModule} from '../../services/adminToolService.module';
import {InputModule} from '../../sharedComponents/input/input.module';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import {IconsModule} from '../../utils/icons/icons.module';
import {PageContentModule} from '../sharedComponents/page-content/page-content.module';
import {RouterModule} from '@angular/router';
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({
imports: [
PageHelpContentFormRoutingModule,
CommonModule, FormsModule, RouterModule,
SafeHtmlPipeModule, CKEditorModule,
AlertModalModule, ReactiveFormsModule, AdminToolServiceModule, InputModule, IconsModule, PageContentModule, LoadingModule, MatSlideToggleModule
AlertModalModule, ReactiveFormsModule, PageHelpContentFormRoutingModule, AdminToolServiceModule, InputModule, MatSlideToggleModule, IconsModule, PageContentModule, LoadingModule
],
declarations: [PageContentFormComponent],
exports: [PageContentFormComponent]
declarations: [
PageContentFormComponent
],
exports: [PageContentFormComponent]
})
export class PageHelpContentFormModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([arrow_left]);
}
}

View File

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

View File

@ -1,5 +1,5 @@
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 {HelpContentService} from '../../services/help-content.service';
import {
@ -7,16 +7,18 @@ import {
PageHelpContent,
PageHelpContentFilterOptions
} 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 {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 {Subscriber} from 'rxjs';
import {properties} from '../../../../environments/environment';
import {DomSanitizer} from '@angular/platform-browser';
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({
selector: 'page-help-contents',
@ -27,7 +29,7 @@ export class PageHelpContentsComponent implements OnInit {
private selectedPageContents: string[] = [];
public checkboxes: CheckPageHelpContent[] = [];
public pageHelpContents: PageHelpContent[] = [];
public formGroup: UntypedFormGroup;
public formGroup: FormGroup;
public pages: Page[];
public checkboxAll: boolean = false;
public filters: PageHelpContentFilterOptions = {id: '', active: null, text: new RegExp('')};
@ -40,14 +42,12 @@ export class PageHelpContentsComponent implements OnInit {
public page: Page;
public properties: EnvProperties = properties;
public showLoading: boolean = true;
public filterForm: UntypedFormControl;
public filterForm: FormControl;
private subscriptions: any[] = [];
public selectedKeyword: string;
@ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent;
constructor(private element: ElementRef, private route: ActivatedRoute, private router: Router,
private _helpService: HelpContentService, private _fb: UntypedFormBuilder, private sanitizer: DomSanitizer,
private _clearCacheService: ClearCacheService) {
constructor(private element: ElementRef, private route: ActivatedRoute, private router: Router, private _helpService: HelpContentService, private _fb: FormBuilder, private sanitizer: DomSanitizer) {
}
ngOnInit() {
@ -152,6 +152,8 @@ export class PageHelpContentsComponent implements OnInit {
}
private confirmModalOpen() {
this.alertModalDeletePageHelpContents.cancelButton = true;
this.alertModalDeletePageHelpContents.okButton = true;
this.alertModalDeletePageHelpContents.alertTitle = 'Delete Confirmation';
this.alertModalDeletePageHelpContents.message = 'Are you sure you want to delete the selected page content(s)?';
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.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._clearCacheService.clearCache("Help texts deleted");
},
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);
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.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)
));
@ -240,19 +248,23 @@ export class PageHelpContentsComponent implements OnInit {
this.applyFilter();
}
handleError(message: string, error = null) {
if(error) {
console.log('Server responded: ' + error);
}
NotificationHandler.rise(message, 'danger');
handleError(message: string, error) {
UIkit.notification(message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
console.log('Server responded: ' + error);
this.showLoading = false;
}
handleUpdateError(message: string, error = null) {
if(error) {
console.log('Server responded: ' + error);
}
NotificationHandler.rise(message, 'danger');
handleUpdateError(message: string, error) {
UIkit.notification(message, {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
console.log('Server responded: ' + error);
this.showLoading = false;
}

View File

@ -5,21 +5,22 @@ import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {AlertModalModule} from '../../utils/modal/alertModal.module';
import {PageHelpContentsComponent} from './page-help-contents.component';
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 {InputModule} from '../../sharedComponents/input/input.module';
import {PageHelpContentsRoutingModule} from './page-help-contents-routing.module';
import {PageContentModule} from '../sharedComponents/page-content/page-content.module';
import {SearchInputModule} from '../../sharedComponents/search-input/search-input.module';
import {IconsModule} from '../../utils/icons/icons.module';
import {IconsService} from '../../utils/icons/icons.service';
import {add, arrow_left, edit, remove} from '../../utils/icons/icons';
import {LoadingModule} from '../../utils/loading/loading.module';
import {HTMLToStringPipeModule} from '../../utils/pipes/HTMLToStringPipe.module';
@NgModule({
imports: [
PageHelpContentsRoutingModule,
CommonModule, RouterModule, FormsModule, SafeHtmlPipeModule,
AlertModalModule, ReactiveFormsModule, MatSlideToggleModule, AdminToolServiceModule, InputModule, PageContentModule,
AlertModalModule, ReactiveFormsModule, MatSlideToggleModule, AdminToolServiceModule, InputModule, PageHelpContentsRoutingModule, PageContentModule,
SearchInputModule, IconsModule, LoadingModule, HTMLToStringPipeModule
],
declarations: [
@ -27,4 +28,8 @@ import {HTMLToStringPipeModule} from '../../utils/pipes/HTMLToStringPipe.module'
],
exports: [PageHelpContentsComponent]
})
export class PageHelpContentsModule {}
export class PageHelpContentsModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([add, arrow_left, edit, remove])
}
}

View File

@ -1,250 +1,168 @@
<div page-content>
<div header>
<admin-tabs tab="menu" [portal]="portal" [type]="type"></admin-tabs>
</div>
<div actions>
<div class="uk-section-xsmall">
<div class="uk-flex uk-flex-center uk-flex-wrap uk-flex-middle uk-grid" uk-grid
[class]="isPortalAdministrator ? 'uk-flex-between@m':'uk-flex-right@m'">
<div>
<div input inputClass="border-bottom" type="select" [options]="menuTypes" [(value)]="selectedMenuType" (valueChange)="valueChange()"
*ngIf="isPortalAdministrator"></div>
</div>
<div>
<button class="uk-button uk-button-default uk-flex uk-flex-middle"
[disabled]="showLoading" [class.uk-disabled]="showLoading"
(click)="newMenuItem()"
uk-tooltip="title:<div><div class='uk-margin-small-bottom uk-text-bold'>Add new menu item</div><div>Creating a menu item for your customized navigation bar.</div><div>Menu items can be either linked to an existing page or to an external link.</div></div>">
<icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left">New Menu Item</span>
</button>
</div>
</div>
</div>
</div>
<div page-content class="admin-pages">
<div header>
<admin-tabs tab="menu" [portal]="portal"></admin-tabs>
<div *ngIf="!showLoading" class="uk-grid" uk-grid>
<div class="uk-width-1-1">
<ul *ngIf="!isPortalAdministrator" class="uk-subnav uk-subnav-pill uk-flex uk-flex-middle">
<li *ngFor="let item of rootMenuItems; let i=index" [class.uk-active]="activeRootMenuId==item['_id']"
class="uk-visible-toggle uk-position-relative uk-padding-remove-horizontal">
<span>
<a (click)="changeActiveRootMenuItem(item)">
<span class="title">{{item.title}}</span>
</a>
<span class="uk-invisible-hover uk-position-center-right color z-index-2">
<span class="clickable" uk-icon="more-vertical"></span>
<div #element uk-dropdown="mode: click; pos: bottom-right; offset: 20; delay-hide: 0; flip: false">
<ul class="uk-nav uk-dropdown-nav">
<li (click)="editMenuItem(item, false)">
<a>Edit</a>
</li>
<hr class="uk-nav-divider">
<li (click)="confirmDeleteMenuItem(item._id, false)">
<a>Delete</a>
</li>
</ul>
</div>
</span>
</span>
</li>
<li (click)="newMenuItem(false)" class="uk-visible-toggle">
<span class="clickable">
<span class="uk-icon-button small portal-icon-button">
<icon name="add"></icon>
</span>
<span class="space" [class.uk-hidden-hover]="rootMenuItems.length != 0">
Create new root menu
</span>
</span>
</li>
</ul>
</div>
</div>
<div *ngIf="!activeRootMenu.isFeatured"
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"
uk-grid>
<div #searchInputComponent search-input [control]="filterForm.controls.keyword" [showSearch]="false"
placeholder="Search menu item"
[selected]="selectedKeyword" (closeEmitter)="onSearchClose()" (resetEmitter)="reset()"
[bordered]="true" colorClass="uk-text-secondary"
class="uk-width-1-3@xl uk-width-2-5@l uk-width-1-2@m uk-width-1-1"></div>
<div>
<a (click)="newMenuItem(true)" class="uk-flex uk-flex-middle uk-text-uppercase">
<button class="large uk-icon-button uk-button-secondary">
<icon name="add"></icon>
</button>
<button class="uk-button uk-button-link uk-margin-small-left uk-text-secondary">
Add new menu item
</button>
</a>
</div>
</div>
</div>
<div inner>
<div class="uk-section uk-section-small uk-position-relative" style="min-height: 60vh">
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
<div *ngIf="!showLoading">
<div class="uk-grid" uk-grid>
<div #elements transition-group class="uk-width-3-4@m">
<div *ngFor="let item of displayMenuItems; let i = index;" transition-group-item>
<div class="uk-width-2-3@m uk-margin-bottom uk-padding-small menu-item">
<div class="uk-flex uk-flex-middle uk-flex-between">
<div>
{{item.title}}
</div>
<div class="uk-flex uk-flex-middle uk-flex-center">
<span *ngIf="item.type == 'external'" class="uk-text-meta uk-text-small uk-margin-small-right">External URL</span>
<span *ngIf="item.type == 'internal'" class="uk-text-meta uk-text-small uk-margin-small-right">Internal page</span>
<span *ngIf="item.type == 'noAction'" class="uk-text-meta uk-text-small uk-margin-small-right"></span>
<a class="uk-link-reset" (click)="toggleMenuItem(item)">
<icon *ngIf="!item.isOpen" name="arrow_drop_down" [flex]="true"></icon>
<icon *ngIf="item.isOpen" name="arrow_drop_up" [flex]="true"></icon>
</a>
</div>
<div *ngIf="showLoading" class="uk-position-center">
<loading></loading>
</div>
<div *ngIf="!showLoading">
<ul *ngIf='activeRootMenuId' class="uk-list submenu-items">
<li *ngFor="let child of childrenMenuItems" class="uk-card uk-card-default uk-margin-bottom">
<div class="uk-grid uk-grid-divider uk-padding" uk-grid>
<div class="uk-width-4-5">
<div class="uk-grid uk-flex uk-flex-middle">
<div class="uk-width-expand uk-margin-medium-bottom">
{{child.title}}
</div>
<div *ngIf="child.url && child.type == 'external'" class="uk-grid uk-width-1-1 uk-margin-left">
<span class="title uk-padding-remove">URL: </span><a href="{{child.url}}" target="_blank"
class="uk-padding-remove uk-margin-left">{{child.url}}</a>
</div>
<div *ngIf="child.route && child.type == 'internal'" class="uk-grid uk-width-1-1 uk-margin-left">
<span class="title uk-padding-remove">Route: </span><span
class="uk-padding-remove uk-margin-left">{{child.route}}</span>
</div>
<div *ngIf="(menuRouteStatus != null && !menuRouteStatus.get(child._id) && child.type == 'internal')" class="uk-grid uk-width-1-1 uk-margin-left">
<span class="uk-padding-remove uk-text-warning">The item is not used either because the required page does not exist or it is disabled</span>
</div>
<ng-container *ngIf="item.isOpen">
<div *ngIf="item.type != 'noAction'" class="uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-text-meta uk-text-small uk-margin-xsmall-bottom">
Target {{item.type == 'external' ? 'URL' : 'Route'}}
</div>
<div>
{{item.type == 'external' ? item.url : item.route}}
</div>
<div *ngIf="item.type == 'internal' && item.route && pageStatus != null && !pageStatus.get(item.route)" class="uk-text-small uk-text-warning uk-margin-small-top">
This menu item will not visible because the page is disabled
</div>
</div>
<div class="uk-flex uk-flex-middle uk-flex-center">
<button class="uk-button uk-button-link uk-flex uk-flex-middle uk-margin-medium-right" (click)="editMenuItem(i, item, false)">
<icon name="edit" [flex]="true"></icon>
<span class="uk-margin-xsmall-left">Edit</span>
</button>
<button class="uk-button uk-button-link uk-flex uk-flex-middle" (click)="confirmDeleteMenuItem(item._id, false)">
<icon name="delete" [flex]="true"></icon>
<span class="uk-margin-xsmall-left">Delete</span>
</button>
</div>
<div *ngIf="displayMenuItems.length > 1" class="uk-margin-medium-top uk-flex uk-flex-middle uk-text-small">
<span class="uk-text-meta uk-margin-small-right">
Move:
</span>
<a *ngIf="i != 0" class="uk-link uk-link-text uk-margin-right"
(click)="moveElement(i, i - 1)">
<div class="uk-flex uk-flex-middle">
<icon name="north" [flex]="true"></icon>
<span class="uk-margin-xsmall-left">Up</span>
</div>
</a>
<a *ngIf="i != (displayMenuItems.length - 1)" class="uk-link uk-link-text"
(click)="moveElement(i, i + 1)">
<div class="uk-flex uk-flex-middle">
<icon name="south" [flex]="true"></icon>
<span class="uk-margin-xsmall-left">Down</span>
</div>
</a>
</div>
</ng-container>
</div>
<div *ngIf="item.items && item.items.length" #subElements transition-group>
<div *ngFor="let subItem of item.items; let j = index" transition-group-item>
<div class="uk-margin-medium-left uk-width-2-3@m uk-margin-bottom uk-padding-small menu-item">
<div class="uk-flex uk-flex-middle uk-flex-between">
<div>
{{subItem.title}}
</div>
<div class="uk-flex uk-flex-middle uk-flex-center">
<span *ngIf="subItem.type == 'external'" class="uk-text-meta uk-text-small uk-margin-small-right">External URL</span>
<span *ngIf="subItem.type == 'internal'" class="uk-text-meta uk-text-small uk-margin-small-right">Internal page</span>
<a class="uk-link-reset" (click)="toggleMenuItem(subItem)">
<icon *ngIf="!subItem.isOpen" name="arrow_drop_down" [flex]="true"></icon>
<icon *ngIf="subItem.isOpen" name="arrow_drop_up" [flex]="true"></icon>
</a>
</div>
</div>
<ng-container *ngIf="subItem.isOpen">
<div class="uk-margin-medium-top uk-margin-medium-bottom">
<div class="uk-text-meta uk-text-small uk-margin-xsmall-bottom">
Target {{subItem.type == 'external' ? 'URL' : 'Route'}}
</div>
<div>
{{subItem.type == 'external' ? subItem.url : subItem.route}}
</div>
</div>
<div class="uk-flex uk-flex-middle uk-flex-center">
<button class="uk-button uk-button-link uk-flex uk-flex-middle uk-margin-medium-right" (click)="editMenuItem(j, subItem, true)">
<icon name="edit" [flex]="true"></icon>
<span class="uk-margin-xsmall-left">Edit</span>
</button>
<button class="uk-button uk-button-link uk-flex uk-flex-middle" (click)="confirmDeleteMenuItem(subItem._id, true, subItem.parentItemId)">
<icon name="delete" [flex]="true"></icon>
<span class="uk-margin-xsmall-left">Delete</span>
</button>
</div>
<div *ngIf="item.items.length > 1" class="uk-margin-medium-top uk-flex uk-flex-middle uk-text-small">
<span class="uk-text-meta uk-margin-small-right">
Move:
</span>
<a *ngIf="j != 0" class="uk-link uk-link-text uk-margin-right"
(click)="moveElement(j, j - 1, item.items)">
<div class="uk-flex uk-flex-middle">
<icon name="north" [flex]="true"></icon>
<span class="uk-margin-xsmall-left">Up</span>
</div>
</a>
<a *ngIf="j != (item.items.length - 1)" class="uk-link uk-link-text"
(click)="moveElement(j, j + 1, item.items)">
<div class="uk-flex uk-flex-middle">
<icon name="south" [flex]="true"></icon>
<span class="uk-margin-xsmall-left">Down</span>
</div>
</a>
</div>
</ng-container>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="displayMenuItems && displayMenuItems.length > 0" class="uk-width-1-4@m">
<h6>Menu visibility</h6>
<div class="uk-margin-small-bottom">
<label (click)="toggleMenu(true, selectedMenuType == 'normalMenu'? false : true )">
<input class="uk-radio" type="radio" name="menu" [checked]="(selectedMenuType == 'normalMenu' && showNormalMenu) || (selectedMenuType == 'customMenu' && showFeaturedMenu)">
<span class="uk-margin-small-left">Visible</span>
</label>
</div>
<div>
<label (click)="toggleMenu(false, selectedMenuType == 'normalMenu'? false : true )">
<input class="uk-radio" type="radio" name="menu" [checked]="(selectedMenuType == 'normalMenu' && !showNormalMenu) || (selectedMenuType == 'customMenu' && !showFeaturedMenu)">
<span class="uk-margin-small-left">Hidden</span>
</label>
</div>
<h6 class="uk-margin-medium-top">Menu alignment</h6>
<div *ngIf="selectedMenuType == 'customMenu'">
<div>
<label (click)="alignMenu('LEFT')">
<input class="uk-radio" type="radio" name="menuAlign" [checked]="(featuredAlignment == 'LEFT')">
<span class="uk-margin-small-left">Left</span>
</label>
</div>
<div>
<label (click)="alignMenu('CENTER')">
<input class="uk-radio" type="radio" name="menuAlign" [checked]="(featuredAlignment == 'CENTER')">
<span class="uk-margin-small-left">Center</span>
</label>
</div>
<div>
<label (click)="alignMenu('RIGHT')">
<input class="uk-radio" type="radio" name="menuAlign" [checked]="(featuredAlignment == 'RIGHT')">
<span class="uk-margin-small-left">Right</span>
</label>
</div>
</div>
</div>
</div>
<div *ngIf="displayMenuItems && displayMenuItems.length == 0"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div>No menu items found</div>
</div>
</div>
</div>
<div class="uk-width-1-5">
<div class="uk-flex uk-flex-center uk-flex-column uk-height-1-1">
<div class="uk-flex uk-flex-center">
<div class="actions">
<button class="uk-button action uk-margin-top uk-flex uk-flex-middle"
(click)="editMenuItem(child, true)">
<icon name="edit"></icon>
<span class="uk-margin-small-left"> Edit</span>
</button>
<button class="uk-button action uk-margin-top uk-flex uk-flex-middle"
(click)="confirmDeleteMenuItem(child._id, true)">
<icon name="remove"></icon>
<span class="uk-margin-small-left"> Delete</span>
</button>
</div>
</div>
</div>
</div>
</div>
</li>
</ul>
<div *ngIf="childrenMenuItems.length == 0 && !activeRootMenu.isFeatured"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div>No menu items found</div>
</div>
<div *ngIf="activeRootMenu.isFeatured"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div>Featured menu items can't have any sub menu items</div>
</div>
</div>
</div>
</div>
<modal-alert #editModal (alertOutput)="menuItemSaveConfirmed($event)"
[okDisabled]="menuItemForm && (menuItemForm.invalid || !menuItemForm.dirty)" classTitle="uk-background-primary uk-light">
[okDisabled]="menuItemForm && (menuItemForm.invalid || !menuItemForm.dirty)">
<form *ngIf="menuItemForm" [formGroup]="menuItemForm" class="uk grid uk-child-width-1-1" uk-grid>
<div input [formInput]="menuItemForm.get('title')" type="text"
placeholder="Name"></div>
<!-- Selecting parent of menu item -->
<div input *ngIf="selectedMenuType == 'normalMenu' && isPortalAdministrator" [formInput]="menuItemForm.get('parentItemId')" type="select"
placeholder="Parent" [options]="parentOptions" [tooltip]="false" [disabled]="menuItemForm.get('_id').value"></div>
<!-- Selecting type of menu item -->
<div input [formInput]="menuItemForm.get('type')" type="select" placeholder="Type"
[options]="getTypeOptions(menuItemForm.get('isFeatured').value, menuItemForm.get('parentItemId').value)" [tooltip]="false"></div>
<div dashboard-input [formInput]="menuItemForm.get('title')" type="text" label="Name"
placeholder="Write a name"></div>
<div class="uk-flex" *ngIf="activeRootMenu && !activeRootMenu.items.length">
<div class="uk-text-bold uk-form-label uk-margin-small-right">Featured</div>
<mat-slide-toggle [formControl]="menuItemForm.get('isFeatured')"
uk-tooltip="title:<div class='uk-padding-small uk-width-large'><div class='uk-text-bold '>Enable this to show your custom menu item in the community-specific navigation bar.</div><div class=' uk-margin-top'>If disabled, your custom menu item will appear in the default navigation bar.</div><div class=' uk-margin-top'>*Note that featured menu items can't have any children menu items(as a dropdown).</div></div>">
</mat-slide-toggle>
</div>
<div dashboard-input [formInput]="menuItemForm.get('type')" type="select" label="Type" placeholder="Choose a type"
[options]="getTypeOptions(menuItemForm.get('isFeatured').value)" [tooltip]="false"></div>
<!-- Workflow for EXTERNAL -->
<div input *ngIf="menuItemForm.get('type').value === 'external'" [formInput]="menuItemForm.get('url')"
[validators]="menuItemForm.get('url').validator" type="URL" placeholder="URL"></div>
<div dashboard-input *ngIf="menuItemForm.get('type').value === 'external'" [formInput]="menuItemForm.get('url')"
[validators]="menuItemForm.get('url').validator" type="URL" label="URL" placeholder="Write a URL"></div>
<!-- Workflow for INTERNAL -->
<div *ngIf="menuItemForm.get('type').value === 'internal'">
<div class="uk-text-center uk-margin-small-bottom">Select one of the pages</div>
<div input [formInput]="menuItemForm.get('route')" [validators]="menuItemForm.get('route').validator"
type="autocomplete" label="Page" placeholder="Search all pages" [options]="allPages"
[showOptionsOnEmpty]="false" class="uk-margin-bottom">
<div class="uk-text-center">Select one of the pages</div>
<div dashboard-input [formInput]="menuItemForm.get('route')" [validators]="menuItemForm.get('route').validator"
type="autocomplete" label="Page" placeholder="Search all pages" [options]="allPages"
[showOptionsOnEmpty]="false" class="uk-margin-bottom">
</div>
<div *ngIf="pageStatus != null && !pageStatus.get(menuItemForm.get('route').value) && menuItemForm.get('route').dirty" class="uk-text-center">
<span class="uk-text-warning">The item is not used because the required page is disabled</span>
<div *ngIf="(menuRouteStatus != null && !menuRouteStatus.get(menuItemForm.get('_id').value) && !menuItemForm.get('route').dirty)" class="uk-text-center">
<span class="uk-text-warning">The item is not used either because the required page does not exist or it is disabled</span>
</div>
<!-- <div *ngIf="selectedMenuType == 'customMenu'" class="uk-text-center uk-margin-top">Or <a (click)="newPageWindow()">create a new one</a></div>-->
<!-- <div *ngIf="newPageWindowOpen" class="uk-card uk-card-default uk-card-body uk-margin-top">-->
<!-- <div>-->
<!-- <button (click)="newPageWindow()" class="uk-close uk-icon uk-float-right" uk-close></button>-->
<!-- <h6 class="uk-text-bold uk-margin-remove-top">Create New Page</h6>-->
<!-- </div>-->
<!-- <form *ngIf="pageForm" [formGroup]="pageForm" class="uk grid uk-child-width-1-1" uk-grid>-->
<!-- <div input [formInput]="pageForm.get('name')" type="text" label="Name"-->
<!-- placeholder="Name"></div>-->
<!-- <div input [formInput]="pageForm.get('route')" type="text"-->
<!-- placeholder="Route"></div>-->
<!-- <div class="uk-flex uk-flex-right">-->
<!-- <button [disabled]="!(pageForm.get('name').value && pageForm.get('route').value)"-->
<!-- class="uk-button uk-button-secondary outlined" (click)="createPage()">Create Page-->
<!-- </button>-->
<!-- </div>-->
<!-- </form>-->
<!-- </div>-->
<div class="uk-text-center uk-margin-top">Or <a (click)="newPageWindow()">create a new one</a></div>
<div *ngIf="newPageWindowOpen" class="uk-card uk-card-default uk-card-body uk-margin-top">
<div>
<button (click)="newPageWindow()" class="uk-close uk-icon uk-float-right" uk-close></button>
<h6 class="uk-text-bold uk-margin-remove-top">Create New Page</h6>
</div>
<form *ngIf="pageForm" [formGroup]="pageForm" class="uk grid uk-child-width-1-1" uk-grid>
<div dashboard-input [formInput]="pageForm.get('name')" type="text" label="Name"
placeholder="Write a name"></div>
<div dashboard-input [formInput]="pageForm.get('route')" type="text" label="Route"
placeholder="Write a route"></div>
<div class="uk-flex uk-flex-right">
<button [disabled]="!(pageForm.get('name').value && pageForm.get('route').value)"
class="uk-button uk-button-secondary outlined" (click)="createPage()">Create Page
</button>
</div>
</form>
</div>
</div>
<!-- <div class="uk-flex" *ngIf="isPortalAdministrator">
<div class="uk-form-label uk-margin-small-right">Featured</div>
<mat-slide-toggle [formControl]="menuItemForm.get('isFeatured')"
uk-tooltip="title:<div class='uk-width-large'><div class='uk-text-bold '>Enable this to show your custom menu item in the community-specific navigation bar.</div><div class=' uk-margin-top'>If disabled, your custom menu item will appear in the default navigation bar.</div><div class=' uk-margin-top'>*Note that featured menu items can't have any children menu items(as a dropdown).</div></div>">
</mat-slide-toggle>
</div> -->
</form>
</modal-alert>
<modal-alert #deleteModal [overflowBody]="false" (alertOutput)="confirmedDeleteMenuItem($event)" classTitle="uk-background-primary uk-light"></modal-alert>
<modal-alert #deleteModal (alertOutput)="confirmedDeleteMenuItem($event)"></modal-alert>

View File

@ -1,8 +0,0 @@
@import (reference) "~src/assets/openaire-theme/less/_import-variables";
.menu-item {
background: @global-inverse-color;
border: 1px solid @global-muted-background;
border-radius: @global-border-radius;
color: @global-emphasis-color;
}

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