git subrepo clone git@github.com:madgeek-arc/dataSpaceUI.git src/dataSpaceUI

subrepo:
  subdir:   "src/dataSpaceUI"
  merged:   "e447c6a"
upstream:
  origin:   "git@github.com:madgeek-arc/dataSpaceUI.git"
  branch:   "main"
  commit:   "e447c6a"
git-subrepo:
  version:  "0.4.6"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "110b9eb"
This commit is contained in:
John Balasis 2024-05-27 12:15:53 +03:00
parent 1127620b2c
commit 72e6d3a060
151 changed files with 14595 additions and 0 deletions

12
src/dataSpaceUI/.gitrepo Normal file
View File

@ -0,0 +1,12 @@
; DO NOT EDIT (unless you know what you are doing)
;
; This subdirectory is a git "subrepo", and this file is maintained by the
; git-subrepo command. See https://github.com/ingydotnet/git-subrepo#readme
;
[subrepo]
remote = git@github.com:madgeek-arc/dataSpaceUI.git
branch = main
commit = e447c6a254fecf2c133ffee8c32e9cba5e1e0dca
parent = 1127620b2cc05c9c197413027b3fae40209ef1c5
method = merge
cmdver = 0.4.6

201
src/dataSpaceUI/LICENSE Normal file
View File

@ -0,0 +1,201 @@
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

@ -0,0 +1 @@
# dataSpaceUI

View File

@ -0,0 +1,142 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {HomeComponent} from "./pages/home/home.component";
import {IntelcompSearchComponent} from "./pages/search/intelcomp-search.component";
import {DatasetLandingPageComponent} from "./pages/landingpages/datasets/dataset-landing-page.component";
import {RequestDataComponent} from "./pages/requestdata/request-data.component";
import {FormComponent} from "./pages/form/form.component";
import {BrowseJobsComponent} from "./pages/browse-jobs/browse-jobs.component";
import {RoleAuthGuardComponent} from "./services/role-auth-guard.component";
import {PayloadComponent} from "./pages/landingpages/payload/payload.component";
import {ResourceSearchComponent} from "./pages/search/resource-search/resource-search.component";
import {environment} from "../environments/environment";
import {HomeDashboardComponent} from "./pages/home/dashboard/home-dashboard.component";
import {LoginGuardComponent} from "./services/login-guard.component";
const dataSpaceRoutes: Routes = [
{
path: '',
redirectTo: 'home',
pathMatch: 'full'
},
{
path: 'home',
component: HomeComponent
},
{
path: 'dashboard',
component: HomeDashboardComponent,
canActivate: [LoginGuardComponent]
},
{
path: 'search',
component: IntelcompSearchComponent
},
{
path: 'search/:resourceType',
component: ResourceSearchComponent
},
{
path: 'resource/:id',
component: DatasetLandingPageComponent
},
{
path: 'request-data',
component: RequestDataComponent
},
{
path: 'browseJobs',
component: BrowseJobsComponent
},
{
path: 'landingPage/:resourceType/:identifierValue',
component: PayloadComponent
},
{
path: 'form/:resourceTypeModel',
component: FormComponent,
canActivate: [RoleAuthGuardComponent],
data: {
roles: ["OPERATOR_DATASET-INGESTOR", "OPERATOR_DEVELOPER"]
}
},
{
path: 'form/:resourceTypeModel/:id',
component: FormComponent,
canActivate: [RoleAuthGuardComponent],
data: {
roles: ["OPERATOR_DATASET-INGESTOR", "OPERATOR_DEVELOPER"]
}
}
];
const opixRoutes: Routes = [
{
path: '',
redirectTo: 'home',
pathMatch: 'full'
},
// {
// path: 'home',
// component: HomeComponent
// },
{
path: 'search',
component: IntelcompSearchComponent,
canActivate: [RoleAuthGuardComponent],
data: {
roles: ["OPERATOR_DATASET-INGESTOR", "OPERATOR_DEVELOPER", 'OPERATOR_DATASET-OWNER', 'OPERATOR_DATA-PROCESSOR']
}
},
{
path: 'search/:resourceType',
component: ResourceSearchComponent,
canActivate: [RoleAuthGuardComponent],
data: {
roles: ["OPERATOR_DATASET-INGESTOR", "OPERATOR_DEVELOPER", 'OPERATOR_DATASET-OWNER', 'OPERATOR_DATA-PROCESSOR']
}
},
{
path: 'resource/:id',
component: DatasetLandingPageComponent
},
{
path: 'request-data',
component: RequestDataComponent
},
{
path: 'browseJobs',
component: BrowseJobsComponent
},
{
path: 'form/:resourceTypeModel',
component: FormComponent,
canActivate: [RoleAuthGuardComponent],
data: {
roles: ["OPERATOR_DATASET-INGESTOR", "OPERATOR_DEVELOPER"]
}
}
];
@NgModule({
imports: [RouterModule.forChild(environment.projectName === 'Opix' ? opixRoutes : dataSpaceRoutes)],
exports: [RouterModule]
})
export class DataSpaceUIRoutingModule { }

View File

@ -0,0 +1,80 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {NgModule} from '@angular/core';
import {DataSpaceUIRoutingModule} from './dataSpaceUI-routing.module';
import {HomeComponent} from "./pages/home/home.component";
import {HttpClientModule} from "@angular/common/http";
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {CatalogueUiModule} from "../catalogue-ui/catalogue-ui.module";
import {IntelcompSearchComponent} from "./pages/search/intelcomp-search.component";
import {DatasetLandingPageComponent} from "./pages/landingpages/datasets/dataset-landing-page.component";
import {IntelcompFooterComponent} from "./shared/footer/footer.component";
import {RequestDataComponent} from "./pages/requestdata/request-data.component";
import {NavigationService} from "./services/navigation.service";
import {CatalogueService} from "./services/catalogue.service";
import {FormComponent} from "./pages/form/form.component";
import {DynamicFormModule} from "../catalogue-ui/pages/dynamic-form/dynamic-form.module";
import {BrowseJobsComponent} from "./pages/browse-jobs/browse-jobs.component";
import {ReusableComponentsModule} from "./shared/reusablecomponents/reusable-components.module";
import {AuthenticationService} from "./services/authentication.service";
import {UserService} from "./services/user.service";
import {NgSelectModule} from "@ng-select/ng-select";
import {CommonModule} from "@angular/common";
import {RoleAuthGuardComponent} from "./services/role-auth-guard.component";
import {PayloadComponent} from "./pages/landingpages/payload/payload.component";
import {ResourceSearchComponent} from "./pages/search/resource-search/resource-search.component";
import {HomeDashboardComponent} from "./pages/home/dashboard/home-dashboard.component";
import {LoginGuardComponent} from "./services/login-guard.component";
@NgModule({
declarations: [
HomeComponent,
HomeDashboardComponent,
IntelcompFooterComponent,
IntelcompSearchComponent,
DatasetLandingPageComponent,
RequestDataComponent,
FormComponent,
BrowseJobsComponent,
PayloadComponent,
ResourceSearchComponent
],
imports: [
CommonModule,
HttpClientModule,
FormsModule,
ReactiveFormsModule,
ReusableComponentsModule,
CatalogueUiModule,
DynamicFormModule,
NgSelectModule,
DataSpaceUIRoutingModule
],
providers: [
CatalogueService,
NavigationService,
AuthenticationService,
UserService,
RoleAuthGuardComponent,
LoginGuardComponent
],
exports: [
IntelcompFooterComponent
]
})
export class DataSpaceUIModule { }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
export class Job {
callerAttributes: string;
jobArguments: JobArgument[];
serviceArguments: ServiceArgument;
constructor() {
this.callerAttributes = ''
this.jobArguments = [];
this.serviceArguments = new ServiceArgument();
}
}
export class JobArgument {
name: string;
value: string[] | string;
constructor(name: string, value: string[] | string) {
this.name = name;
this.value = value;
}
}
export class ServiceArgument {
infraId: string;
processId: string;
user: string;
constructor() {
this.infraId = null;
this.processId = null;
this.user = null;
}
}
export class BrowseJob {
id: string;
name: string;
label: string;
createdAt: string;
launchedAt: string;
finishedAt: string;
user: string;
infraId: string;
callerAttributes: string;
callerAttributesObj: object;
mergedStatus: string;
status: Status[];
}
export class Status {
id: string;
timestamp: string;
status: string;
source: string;
payload: string;
}

View File

@ -0,0 +1,22 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
/**
* Created by stefania on 9/6/16.
*/
export class SearchQuery {
query: string;
}

View File

@ -0,0 +1,93 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Section} from "../../catalogue-ui/domain/dynamic-form-model";
export class Survey {
id: string;
name: string;
description: string;
notice: string;
type: string;
creationDate: string;
createdBy: string;
modificationDate: string;
modifiedBy: string;
chapters: Section[];
}
export class SurveyAnswer {
id: string;
modelId: string;
stakeholderId: string;
chapterAnswers: Map<string, ChapterAnswer>;
metadata: Metadata;
validated: boolean;
published: boolean;
chapterId: string;
constructor(chapterAnswers: Map<string, ChapterAnswer>, surveyId: string) {
this.id = null;
this.chapterAnswers = chapterAnswers;
this.modelId = surveyId;
this.metadata = null;
}
}
export class ChapterAnswer {
chapterId: string;
answer: Object;
metadata: Metadata;
id: string;
constructor(chapterId: string, answer: Object) {
this.chapterId = chapterId;
this.answer = answer;
}
}
export class ResourcePermission {
resourceId: string;
permissions: string[];
}
export class Metadata {
creationDate: string;
createdDy: string;
modificationDate: string;
modifiedBy: string;
}
export class SurveyInfo {
surveyId: string;
surveyAnswerId: string;
surveyName: string;
validated: boolean;
published: boolean;
lastUpdate: Date;
editedBy: string[];
progressRequired: Progress;
progressTotal: Progress;
stakeholder: string;
}
export class Progress {
current: number;
total: number;
}

View File

@ -0,0 +1,24 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
export class UserInfo {
sub: string;
email: string;
name: string;
surname: string;
fullname: string;
roles: string[];
}

View File

@ -0,0 +1,54 @@
<div class="uk-section uk-section-default">
<div *ngIf="jobs.length > 0" class="uk-container uk-container-large uk-margin">
<h4 class="uk-margin">My Data Requests</h4>
<div class="uk-card uk-card-default uk-card-body uk-margin-medium-top">
<table class="uk-table uk-table-divider">
<thead>
<tr>
<th>Dataset</th>
<th>Entity</th>
<th>Status</th>
<th class="uk-width-medium">Data path</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let job of jobs">
<td>
<div>{{getValueFromObject(job.callerAttributesObj, 'name')}}</div>
<div>({{getValueFromObject(job.callerAttributesObj, 'version')}})</div>
</td>
<td>
<div>{{getValueFromObject(job.callerAttributesObj, 'entity')}}</div>
<div class="uk-margin-top uk-text-meta">Filters</div>
<div *ngFor="let attr of getJobArguments(job.callerAttributesObj)">
<ng-container *ngIf="attr['name'] !== 'datasetId'">
{{attr['name']}}: {{attr['value']}}
</ng-container>
</div>
</td>
<td>
<div class="uk-margin-bottom"><strong>{{job.mergedStatus}}</strong></div>
<div *ngIf="job.createdAt">Created: {{job.createdAt | date:'medium'}}</div>
<div *ngIf="job.status && job.status.length>0 && (job.status[0].status=='FINISHED' || job.status[0].status=='finished')">Finished: {{job.status[0].timestamp | date:'medium'}}</div>
<div *ngIf="job.status && job.status.length>0 && (job.status[0].status=='FAILED' || job.status[0].status=='failed')">Failed: {{job.status[0].timestamp | date:'medium'}}</div>
</td>
<td>
<ng-container *ngFor="let status of job.status">
<ng-container *ngIf="status.status=='finished' && status.source=='spark'">
{{status.payload}}
</ng-container>
</ng-container>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!--<pre>{{jobs | json}}</pre>-->
</div>

View File

@ -0,0 +1,82 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Component, OnDestroy, OnInit} from "@angular/core";
import {CatalogueService} from "../../services/catalogue.service";
import {BrowseJob} from "../../domain/job";
import {Subscriber} from "rxjs";
@Component({
selector: 'pages-browse-jobs',
templateUrl: 'browse-jobs.component.html'
})
export class BrowseJobsComponent implements OnInit, OnDestroy {
subscriptions = [];
jobs: BrowseJob[] = [];
constructor(private catalogueService: CatalogueService) {
}
ngOnInit() {
this.subscriptions.push(
this.catalogueService.getJobs().subscribe(
res => {this.jobs = res},
error => {console.log(error)},
() => {
for (const job of this.jobs) {
job.callerAttributesObj = JSON.parse(job.callerAttributes);
}
}
)
);
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
}
});
}
getJobArguments(obj: object) {
for (const [key, value] of Object.entries(obj)) {
// console.log(`key: ${key} value: ${value}`);
for (const [subKey, subValue] of Object.entries(value)) {
if (subKey === 'jobArguments') {
// console.log(subValue);
return subValue as [object];
}
}
}
return []
}
getValueFromObject(obj: object, keyName: string) {
for (const [key, value] of Object.entries(obj)) {
for (const [subKey, subValue] of Object.entries(value)) {
if (subKey === keyName) {
return subValue;
}
}
}
return null;
}
}

View File

@ -0,0 +1,9 @@
<div *ngIf="ready" class="uk-section-default uk-section uk-section-small uk-padding-remove-bottom" style="min-height: 90vh;">
<div class="uk-container uk-container-expand uk-margin-left uk-margin-right uk-margin-top">
<app-survey [payload]="payload" [model]="model" [tabsHeader]="tabsHeader" [downloadPDF]="downloadPDF"
(submit)="submitForm($event)" [mandatoryFieldsText]="mandatoryFieldsText" [subType]="subType"
[activeUsers]="[]" [vocabulariesMap]="vocabulariesMap" [successMessage]="successMessage"
[errorMessage]="errorMessage">
</app-survey>
</div>
</div>

View File

@ -0,0 +1,152 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Component, OnDestroy, OnInit, ViewChild} from "@angular/core";
import {ActivatedRoute, Router} from "@angular/router";
import {CatalogueService} from "../../services/catalogue.service";
import {Subscriber, zip} from "rxjs";
import {FormControlService} from "../../../catalogue-ui/services/form-control.service";
import {Model} from "../../../catalogue-ui/domain/dynamic-form-model";
import {SurveyComponent} from "../../../catalogue-ui/pages/dynamic-form/survey.component";
import {ResourcePayloadService} from "../../services/resource-payload.service";
@Component({
selector: 'pages-form',
templateUrl: 'form.component.html',
providers: [FormControlService, ResourcePayloadService]
})
export class FormComponent implements OnInit, OnDestroy {
@ViewChild(SurveyComponent) child: SurveyComponent;
subscriptions = [];
tabsHeader: string = null;
mandatoryFieldsText: string = 'Fields with (*) are mandatory.';
payload: {answer: object} = null
vocabulariesMap: Map<string, object[]> = null
resourceType: string;
resourceId: string;
model: Model = null;
subType: string = null;
downloadPDF: boolean = false;
ready = false;
successMessage = null;
errorMessage = null;
constructor(private activatedRoute: ActivatedRoute, private catalogueService: CatalogueService,
private formService: FormControlService, private payloadService: ResourcePayloadService,
private router: Router) {
}
ngOnInit() {
this.ready = false;
// this.resourceType = this.activatedRoute.snapshot.params['resourceTypeModel'];
this.subscriptions.push(
this.activatedRoute.params.subscribe(
params => {
this.resourceType = params['resourceTypeModel'];
if (params['id']) {
this.resourceId = params['id'];
this.getResourceForEdit();
} else {
this.subscriptions.push(
zip(
this.formService.getFormModelByResourceType(this.resourceType),
this.catalogueService.getUiVocabularies()).subscribe(
res => {
this.model = res[0].results[0];
this.vocabulariesMap = res[1]
},
error => {console.log(error)},
() => {this.ready = true}
)
);
}
}
)
);
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
}
});
}
submitForm(value) {
// this.child.onSubmit();
// console.log(value);
if (value[0].invalid) {
value[0].markAllAsTouched();
}
if (value[1]) {
this.formService.putGenericItem(this.resourceId, this.resourceType, value[0].value).subscribe(
res => {
this.successMessage = 'Updated successfully!';
this.payload.answer['Intelcomp tool'] = res;
},
error => {
this.errorMessage = 'Something went bad, server responded: ' + JSON.stringify(error?.error?.message);
},
() => {
this.child.closeSuccessAlert();
// this.showLoader = false;
}
);
} else {
this.formService.postGenericItem(value[2], value[0].value).subscribe(
res => {
this.successMessage = 'Created successfully!';
this.payload = {answer: {'Intelcomp tool' : null}};
this.payload.answer['Intelcomp tool'] = res;
},
error => {
this.errorMessage = 'Something went bad, server responded: ' + JSON.stringify(error?.error?.message);
},
() => {
this.router.navigate([`/form/${this.resourceType}/${this.payload.answer['Intelcomp tool'].id}`]);
this.child.closeSuccessAlert();
// this.showLoader = false;
}
);
}
}
getResourceForEdit() {
this.subscriptions.push(
zip(
this.formService.getFormModelByResourceType(this.resourceType),
this.catalogueService.getUiVocabularies(),
this.payloadService.getItemById(this.resourceType, this.resourceId)).subscribe(
res => {
this.model = res[0].results[0];
this.vocabulariesMap = res[1];
// let name = this.model.name
this.payload = {answer: {}};
this.payload.answer[this.model.name] = res[2];
},
error => {console.log(error)},
() => {this.ready = true}
)
);
}
}

View File

@ -0,0 +1,153 @@
<div class="uk-section">
<div class="uk-container uk-container-expand">
<div class="uk-grid uk-child-width-1-4 uk-grid-match">
<!-- <div>-->
<!-- <div class="uk-card uk-card-default uk-card-body uk-card-small uk-flex uk-flex-middle">-->
<!-- <div><span class="material-icons uk-margin-right md-36 icons-secondary">analytics</span></div>-->
<!-- <div>-->
<!-- <div class="uk-margin-small-bottom uk-text-muted">Analyses submitted</div>-->
<!-- <div class="uk-text-bold">{{jobs.length}}</div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<div>
<div class="uk-card uk-card-default uk-card-body uk-card-small uk-flex uk-flex-middle">
<div><span class="material-icons uk-margin-right md-36 icons-secondary">dataset</span></div>
<div>
<div class="uk-margin-small-bottom uk-text-muted">Datasets available</div>
<div class="uk-text-bold">{{datasetCount}}</div>
</div>
</div>
</div>
<div>
<div class="uk-card uk-card-default uk-card-body uk-card-small uk-flex uk-flex-middle">
<div><span class="material-icons uk-margin-right md-36 icons-secondary">build</span></div>
<div>
<div class="uk-margin-small-bottom uk-text-muted">Tools available</div>
<div class="uk-text-bold">{{toolsCount}}</div>
</div>
</div>
</div>
</div>
<!-- <div class="uk-margin-medium-top uk-grid uk-child-width-1-2 uk-grid-match" uk-height-match="target: > div > .uk-card">-->
<!-- <div>-->
<!-- <div class="uk-card uk-card-default uk-card-body uk-card-small uk-flex uk-flex-column uk-flex-between">-->
<!-- <div class="uk-grid">-->
<!-- <div class="uk-width-3-5">-->
<!-- <h5>Patent analytics</h5>-->
<!-- <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi</p>-->
<!-- </div>-->
<!-- <div class="uk-width-2-5">-->
<!-- <img src="https://ipexcel.com/in/images/Patent-analytics.jpg">-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="uk-flex uk-flex-between uk-margin-medium-top">-->
<!-- <button class="uk-button uk-button-link" [routerLink]="['/landingPage/tool/patent-analytics']">Learn more</button>-->
<!-- <button class="uk-button uk-button-primary">Start now</button>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div>-->
<!-- <div class="uk-card uk-card-default uk-card-body uk-card-small uk-flex uk-flex-column uk-flex-between">-->
<!-- <div class="uk-grid">-->
<!-- <div class="uk-width-3-5">-->
<!-- <h5>Bibliometric analysis</h5>-->
<!-- <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,</p>-->
<!-- </div>-->
<!-- <div class="uk-width-2-5">-->
<!-- <img src="https://media.springernature.com/lw685/springer-static/image/art%3A10.1007%2Fs11192-018-2765-z/MediaObjects/11192_2018_2765_Fig5_HTML.gif">-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="uk-flex uk-flex-between uk-margin-medium-top">-->
<!-- <button class="uk-button uk-button-link" [routerLink]="['/landingPage/tool/bibliometric-analysis']">Learn more</button>-->
<!-- <button class="uk-button uk-button-primary">Start now</button>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="uk-margin-medium-top uk-grid">-->
<!-- <div class="uk-width-4-5">-->
<!-- <div class="uk-card uk-card-default uk-card-body uk-card-small">-->
<!-- <div class="uk-margin-bottom">-->
<!-- Latest analyses-->
<!-- </div>-->
<!-- <div>-->
<!-- <table class="uk-table card-table">-->
<!-- <thead>-->
<!-- <tr>-->
<!-- <th>Type</th>-->
<!-- <th>Filters</th>-->
<!-- <th>Dates</th>-->
<!-- <th>Status</th>-->
<!-- <th></th>-->
<!-- </tr>-->
<!-- </thead>-->
<!-- <tbody>-->
<!-- <ng-container *ngIf="jobs?.length == 0">-->
<!-- <tr>-->
<!-- <td colspan="5">No past analyses to show</td>-->
<!-- </tr>-->
<!-- </ng-container>-->
<!-- <ng-container *ngIf="jobs?.length > 0">-->
<!-- <tr *ngFor="let job of jobs | slice:0:3">-->
<!-- <td>-->
<!-- <ng-container *ngIf="this.getWorkflowType(job.callerAttributesObj)==='patentAnalytics'">Patent Analytics</ng-container>-->
<!-- <ng-container *ngIf="this.getWorkflowType(job.callerAttributesObj)!=='patentAnalytics'">Bibliometrics Analysis</ng-container>-->
<!-- </td>-->
<!-- <td>-->
<!-- <a class="uk-link">{{this.getNumberOfFilters(job.callerAttributesObj)}} filters selected</a>-->
<!-- <div uk-dropdown="mode: click; pos: bottom-left" class="filters-dropdown" style="max-width: 300px !important;">-->
<!-- <div class="uk-padding-small">-->
<!-- <h6>Filters</h6>-->
<!-- <div *ngFor="let filter of getFiltersAsAMap(job.callerAttributesObj) | keyvalue" class="uk-margin-top">-->
<!-- <span>{{filter.key}}: </span>-->
<!-- <span>{{filter.value}}</span>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </td>-->
<!-- <td>-->
<!-- <div *ngIf="job.createdAt" class="uk-margin-small-bottom">-->
<!-- <span class="uk-text-muted">Submitted on:</span> {{job.createdAt | date:'medium'}}-->
<!-- </div>-->
<!-- <div *ngIf="job.status && job.status.length>0 && (job.status[0].status=='FINISHED' || job.status[0].status=='finished' || job.status[0].status=='FAILED' || job.status[0].status=='failed')">-->
<!-- <span class="uk-text-muted">Finished at:</span> {{job.status[0].timestamp | date:'medium'}}-->
<!-- </div>-->
<!-- </td>-->
<!-- <td>-->
<!-- <ng-container *ngIf="job.mergedStatus==='FINISHED'"><label class="uk-label uk-label-success">{{job.mergedStatus}}</label></ng-container>-->
<!-- <ng-container *ngIf="job.mergedStatus==='FAILED'"><label class="uk-label uk-label-danger">{{job.mergedStatus}}</label></ng-container>-->
<!-- <ng-container *ngIf="job.mergedStatus==='QUEUED'"><label class="uk-label uk-label-info">{{job.mergedStatus}}</label></ng-container>-->
<!-- </td>-->
<!-- <td>-->
<!-- <ng-container *ngIf="job.mergedStatus === 'FINISHED'">-->
<!-- <a [routerLink]="['/result', job.id]" uk-tooltip="View results..">-->
<!-- <span class="material-icons icons-secondary">arrow_forward</span>-->
<!-- </a>-->
<!-- </ng-container>-->
<!-- </td>-->
<!-- </tr>-->
<!-- </ng-container>-->
<!-- </tbody>-->
<!-- </table>-->
<!-- </div>-->
<!-- <div class="uk-margin-top">-->
<!-- <a class="uk-link" [routerLink]="['/workflowSearch']">-->
<!-- <span>Show more ...</span>-->
<!--&lt;!&ndash; <span class="material-icons uk-margin-small-left">east</span>&ndash;&gt;-->
<!-- </a>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div *ngFor="let job of jobs | slice:0:3">-->
<!-- {{job.id}}-->
<!-- </div>-->
</div>
</div>

View File

@ -0,0 +1,47 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Component, OnInit} from "@angular/core";
import {ResourcePayloadService} from "../../../services/resource-payload.service";
import {CatalogueService} from "../../../services/catalogue.service";
import {BrowseJob} from "../../../domain/job";
import {AuthenticationService} from "../../../services/authentication.service";
@Component({
selector: 'home-dashboard',
templateUrl: 'home-dashboard.component.html',
providers: [ResourcePayloadService, CatalogueService]
})
export class HomeDashboardComponent implements OnInit {
toolsCount = 0;
datasetCount = 0;
jobs: BrowseJob[] = []
constructor(private resourceService: ResourcePayloadService, private catalogueService: CatalogueService,
private authService: AuthenticationService) {
}
ngOnInit() {
this.resourceService.getItemsWithQueryParams('dataset_type').subscribe(res=> {
this.datasetCount = res.total;
});
this.resourceService.getItemsWithQueryParams('tool').subscribe(res=> {
this.toolsCount = res.total;
});
}
}

View File

@ -0,0 +1,25 @@
<div class="uk-section uk-section-secondary uk-preserve-color home-hero" style="">
<div class="uk-container uk-container-large">
<!--<img src="https://intelcomp.eu/themes/custom/basetheme/images/img-background.svg" class="uk-background-cover">-->
<div class="uk-grid uk-flex uk-flex-center uk-margin-xlarge-top">
<div class="uk-width-1-2 uk-card uk-card-default uk-card-body uk-margin-large-top uk-text-center">
<h4>Find a dataset</h4>
<div class="search_box_bg uk-margin-large-bottom" style="text-align:center">
<form [formGroup]="searchForm" (ngSubmit)="this.onSubmit(searchForm.value)">
<input aria-describedby="sizing-addon2" class="uk-input uk-width-2-3 uk-comment uk-comment-meta uk-search-field menuSearch"
name="keyword" placeholder="Which dataset are you looking for?" type="text"
formControlName="query">
<button class=" uk-button uk-button-primary" type="submit">Search</button>
</form>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,41 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import { Component } from '@angular/core';
import {FormBuilder, FormGroup} from "@angular/forms";
import {Router} from "@angular/router";
import {SearchQuery} from "../../domain/search-query";
@Component({
selector: 'pages-home',
templateUrl: './home.component.html',
})
export class HomeComponent {
title = 'catalogue-ui';
searchForm: FormGroup;
constructor(public fb: FormBuilder, public router: Router) {
this.searchForm = fb.group({'query': ['']});
}
onSubmit(searchValue: SearchQuery) {
// console.log('searchValue =>', searchValue);
if(searchValue.query=='')
return this.router.navigate(['/search']);
return this.router.navigate(['/search', searchValue]);
}
}

View File

@ -0,0 +1,199 @@
<ng-container *ngIf="dataset !== null">
<div class="uk-section uk-section-primary uk-preserve-color">
<div class="uk-container uk-container-large">
<div class="uk-grid">
<div class="uk-width-2-3">
<h3 class="uk-margin-remove uk-text-left@m uk-text-center uk-scrollspy-inview uk-animation-fade uk-inline" uk-scrollspy-class="" style="">
{{dataset['name'] || "Not Available"}}
</h3>
<div *ngIf="dataset['identifier']" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="">
<span class="field-label">Identifier: {{dataset['identifier']['value'] + ' (' + dataset['identifier']['identifierType'] + ')'}}</span>
</div>
<div *ngIf="dataset['metadata']['publisher']" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="">
<span class="field-label">Publisher: {{dataset['metadata']['publisher']}}</span>
</div>
<div *ngIf="dataset['metadata']['languages'][0] !== ''" class="uk-margin-top uk-scrollspy-inview uk-animation-fade" uk-scrollspy-class="" style="">
<!--<span class="field-label">Language: </span>-->
<span *ngFor="let language of dataset['metadata']['languages']" class="field-value uk-label uk-margin-small-right">{{language}}</span>
</div>
</div>
<div class="uk-width-1-3">
<div class="uk-padding-remove uk-overlay uk-overlay-default service-image">
<img src="{{dataset['metadata']['logo']}}" style="max-height: 200px;">
</div>
<div *ngIf="hasRole()" class="uk-flex uk-flex-right uk-margin-medium-top">
<div title="Edit">
<a [routerLink]="['/form', 'dataset_type', dataset?.['id']]" class="uk-button uk-button-default uk-flex uk-flex-middle" style="padding: 5px 15px">
<span class="material-icons">mode_edit</span>
</a>
</div>
<div class="uk-margin-small-left" title="Delete">
<button class="uk-button uk-button-danger uk-flex uk-flex-middle" uk-toggle="target: #delete-modal" style="padding: 5px 15px">
<span class="material-icons">delete</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!--<hr>-->
<div class="uk-section uk-section-default">
<div class="uk-container uk-container-large">
<div class="uk-grid">
<div class="uk-width-2-3">
<div class="uk-margin-small-top uk-scrollspy-inview uk-animation-fade serviceDescription" uk-scrollspy-class="" style="">
{{dataset['metadata']['descriptions'][0]?.['value']}}
</div>
<!-- subject -->
<div *ngIf="dataset['metadata']['subjects'][0] !== ''" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="" style="">
<span class="field-label">Subjects: </span>
<ng-container *ngFor="let item of dataset['metadata']['subjects']; let i=index" class="field-value uk-margin-small-left">
<span>{{(i === 0 ? '' : ', ') + item}}</span>
</ng-container>
</div>
<!-- type -->
<div *ngIf="dataset['metadata']['type']" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="" style="">
<span class="field-label">Type: {{dataset['metadata']['type']['clazz'] + ' ' + dataset['metadata']['type']['value']}}</span>
</div>
<!-- format -->
<div *ngIf="dataset['metadata']['formats'][0] !== ''" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="" style="">
<span class="field-label">Formats: </span>
<span *ngFor="let item of dataset['metadata']['formats']" class="field-value uk-margin-small-left">{{item}}</span>
</div>
<!-- webpage -->
<div *ngIf="dataset['metadata']['webpage']" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="">
<span class="field-label">Webpage: </span> <a href="{{dataset['metadata']['webpage']}}" target="_blank">{{dataset['metadata']['webpage']}}</a>
</div>
<!-- source -->
<div *ngIf="dataset['metadata']['source']" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="" style="">
<span class="field-label">Source: {{dataset['metadata']['source']}}</span>
</div>
<!-- related --><!--TODO ADD DATA TO CHECK FUNCTIONALITY-->
<div *ngIf="dataset['metadata']['relatedIdentifiers']?.length > 0" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="" style="">
<span class="field-label">Related Identifiers: {{dataset['metadata']['relatedIdentifiers']}}</span>
</div>
<!-- coverage --> <!--TODO ADD DATA TO CHECK FUNCTIONALITY-->
<div *ngIf="dataset['metadata']['geoLocations']?.length > 0" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="" style="">
<span class="field-label">Coverage: {{dataset['metadata']['geoLocations']}}</span>
</div>
</div>
<div class="uk-width-1-3">
<div *ngIf="instances?.length > 0" class="uk-card uk-card-default uk-card-body">
<h6 class="field-label">Instances / Versions</h6>
<div class="uk-flex">
<ul>
<li *ngFor="let instance of instances">
<span>{{instance['metadata']['version']}}</span><br>
<span>({{instance['metadata']['dates'][0]['value']}})</span>
</li>
</ul>
</div>
<a uk-toggle="target: #modal-dataset-instances">More details...</a>
</div>
<div *ngIf="tools?.results?.length > 0" class="uk-card uk-card-default uk-card-body uk-margin-top">
<h6 class="field-label">Available Tools</h6>
<div class="uk-flex">
<ul>
<li *ngFor="let tool of tools.results">
<a [routerLink]="['/landingPage/tool/',tool.identifier.value]"><span>{{tool['titles'][0]['value']}}</span></a>
</li>
</ul>
</div>
</div>
<div *ngIf="dataset['metadata']['contact']" class="uk-card uk-card-default uk-card-body uk-margin-top">
<h6 class="field-label">Contact</h6>
<div class="uk-flex">
<div>
<span uk-icon="icon: mail"></span>
</div>
<div class="uk-margin-left">
<div> {{dataset['metadata']['contact']['name']}} </div>
<span>{{dataset['metadata']['contact']['email'].replace('@', ' [at] ')}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-container>
<div id="modal-dataset-instances" class="uk-modal-container" uk-modal>
<div class="uk-modal-dialog uk-modal-body">
<button class="uk-modal-close-default" type="button" uk-close></button>
<h4 class="uk-modal-title">Dataset instances</h4>
<div *ngIf="instances !== null">
<table class="uk-table uk-table-divider">
<thead>
<tr>
<th>Version</th>
<th>Identifiers</th>
<th>Creator</th>
<th>Creation date</th>
<th>Sizes</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let instance of instances">
<td>{{instance['metadata']['version']}}</td>
<td><span *ngIf="instance['metadata']['identifier']">{{instance['metadata']['identifier']['value']}}</span></td>
<td><span *ngFor="let creator of instance['metadata']['creators']">
<span>{{creator['creatorName']}}</span><br>
<span *ngIf="creator['nameIdentifier']">{{creator['nameIdentifier']['value']}}</span><br>
</span></td>
<td>{{instance['metadata']['dates'][0]['value']}}</td>
<td><span *ngFor="let size of instance['metadata']['sizes']; let i=index">
<span *ngIf="i !== 0">,<br></span>{{size}}
</span></td>
<td>
<button *ngIf="userInfo?.roles.includes('OPERATOR_DATA-PROCESSOR')
&& (dataset['name']==='OpenAIRE Graph'
|| dataset['name']==='Clinical Trials'
|| dataset['name']==='NIH Research Portfolios'
|| dataset['name']==='European Job Portal'
|| dataset['name']==='Semantic Scholar'
|| dataset['name']==='Spanish Job Portal tecnoempleo.com')"
class="uk-button uk-button-default" (click)="gotoRequestData(instance['metadata']['version'], dataset['id'])">Select</button>
<button *ngIf="instance['location']['files']['baseDir'] !== ''" class="uk-button uk-button-default"
(click)="download(instance['location']['files']['baseDir'])">Download</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="delete-modal" uk-modal>
<div class="uk-modal-dialog uk-modal-body">
<button class="uk-modal-close-default" type="button" uk-close></button>
<h6>Permanently delete this dataset?</h6>
<p class="uk-text-right">
<button class="uk-button uk-button-default uk-modal-close uk-margin-small-right" type="button">Cancel</button>
<button class="uk-button uk-button-danger uk-modal-close" type="button" (click)="deleteItem()" >Delete</button>
</p>
</div>
</div>

View File

@ -0,0 +1,109 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Component} from "@angular/core";
import {LandingPageService} from "../../../../catalogue-ui/services/landing-page.service";
import {LandingPageComponent} from "../../../../catalogue-ui/pages/landingpages/dataset/landing-page.component";
import {environment} from "../../../../../environments/environment";
import {ActivatedRoute, Router} from "@angular/router";
import {NavigationService} from "../../../services/navigation.service";
import {UserService} from "../../../services/user.service";
import {UserInfo} from "../../../domain/userInfo";
import {ResourcePayloadService} from "../../../services/resource-payload.service";
import {Paging} from "../../../../catalogue-ui/domain/paging";
import {AuthenticationService} from "../../../services/authentication.service";
declare var UIkit: any;
@Component({
selector: 'pages-dataset',
templateUrl: 'dataset-landing-page.component.html',
providers: [LandingPageService, ResourcePayloadService]
})
export class DatasetLandingPageComponent extends LandingPageComponent {
userInfo: UserInfo = null;
projectName: string = null;
tools: Paging<any> = null;
constructor(protected override route: ActivatedRoute,
protected override landingPageService: LandingPageService,
protected navigationService: NavigationService,
protected router: Router, private authService: AuthenticationService,
protected userService: UserService,
protected resourcePayloadService: ResourcePayloadService) {
super(route, landingPageService)
}
override ngOnInit() {
super.ngOnInit();
this.projectName = environment.projectName;
if (this.userService.userInfo !== null) {
this.userInfo = this.userService.userInfo;
} else {
this.subscriptions.push(
this.userService.getUserInfo().subscribe(
res => {
this.userInfo = res;
this.userService.roleToSessionStorage(res);
},
error => {
console.log(error);
this.userService.clearUserInfo();
}
)
);
}
this.route.params.subscribe(params => {
this.resourcePayloadService.getItemsByResourceType('tool', params['id']).subscribe(
next => {
this.tools = next;
},
error => {console.log(error);}
)
});
}
gotoRequestData(instanceVersion, datasetId) {
console.log('running on landing page');
UIkit.modal('#modal-dataset-instances').hide();
this.navigationService.setDataRequestIds(instanceVersion, datasetId);
this.router.navigate([`/request-data`]).then();
}
deleteItem() {
this.resourcePayloadService.deleteItem(this.dataset['id'], 'dataset_type').subscribe(
res => {
// UIkit.modal('#delete-modal').hide();
this.router.navigate([`/search`]);
},
error => {
// UIkit.modal('#delete-modal').hide();
console.error(error);
}
);
}
hasRole() {
return this.authService.userRoles.includes('OPERATOR_DATASET-INGESTOR');
}
download(url: string) {
window.open(url, '_blank');
}
}

View File

@ -0,0 +1,153 @@
<div class="uk-section uk-section-primary uk-preserve-color">
<div class="uk-container uk-container-large">
<div class="uk-grid">
<div class="uk-width-2-3">
<h3 class="uk-margin-remove uk-text-left@m uk-text-center uk-scrollspy-inview uk-animation-fade uk-inline" uk-scrollspy-class="" style="">
{{payload?.titles[0]?.value || "Not Available"}}
</h3>
<div *ngIf="payload?.identifier" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="">
<span class="field-label">Identifier: {{payload['identifier']['value'] + ' (' + payload['identifier']['identifierType'] + ')'}}</span>
</div>
<div *ngIf="payload?.publisher" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="">
<span class="field-label">Publisher: {{payload.publisher.value}}</span>
</div>
</div>
<div *ngIf="payload && hasRole()" class="uk-width-1-3 uk-flex uk-flex-right">
<div title="Edit">
<a [routerLink]="['/form', resourceType, payload['id']]" class="uk-button uk-button-default uk-flex uk-flex-middle" style="padding: 5px 15px">
<span class="material-icons">mode_edit</span>
</a>
</div>
<div class="uk-margin-small-left" title="Delete">
<button class="uk-button uk-button-danger uk-flex uk-flex-middle" uk-toggle="target: #delete-modal" style="padding: 5px 15px">
<span class="material-icons">delete</span>
</button>
</div>
<!-- <div class="uk-padding-remove uk-overlay uk-overlay-default service-image">-->
<!-- <img src="{{dataset['metadata']['logo']}}" style="max-height: 200px;">-->
<!-- </div>-->
</div>
</div>
</div>
</div>
<!--<hr>-->
<div class="uk-section uk-section-default">
<div class="uk-container uk-container-large">
<div class="uk-grid">
<div class="uk-width-2-3">
<div *ngIf="payload?.descriptions?.length > 0" class="uk-margin-small-top uk-scrollspy-inview uk-animation-fade serviceDescription" uk-scrollspy-class="" style="">
<h6 class="field-label">Descriptions</h6>
<div class="">
<div *ngFor="let description of payload.descriptions" class="uk-margin-bottom">
<dt>{{description.descriptionType}}</dt>
<dd>{{description.content}}</dd>
</div>
<!-- <ul>-->
<!-- <li *ngFor="let description of payload.descriptions">-->
<!-- <span>{{description.content}}</span>-->
<!-- </li>-->
<!-- </ul>-->
</div>
</div>
<!-- subject -->
<div *ngIf="payload?.subjects?.length > 0" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="" style="">
<span class="field-label">Subjects: </span>
<ng-container *ngFor="let subject of payload.subjects; let i=index" class="field-value uk-margin-small-left">
<span>{{(i === 0 ? '' : ', ') + subject.value}}</span>
</ng-container>
</div>
<!-- type -->
<div *ngIf="payload?.resourceType" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="" style="">
<span class="field-label">Type: {{payload.resourceType.value}}</span>
</div>
<!-- formats -->
<div *ngIf="payload?.formats?.length > 0" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="" style="">
<span class="field-label">Formats: </span>
<ng-container *ngFor="let format of payload.formats; let i=index" class="field-value uk-margin-small-left">
<span>{{(i === 0 ? '' : ', ') + format}}</span>
</ng-container>
</div>
<!-- version -->
<div *ngIf="payload?.version" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="" style="">
<span class="field-label">Version: {{payload.version}}</span>
</div>
<!-- publication year -->
<div *ngIf="payload?.publicationYear" class="uk-margin-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="" style="">
<span class="field-label">Publication year: </span>
<span class="field-value uk-margin-small-left">{{payload.publicationYear}}</span>
</div>
</div>
<div class="uk-width-1-3">
<div *ngIf="payload?.creators?.length > 0" class="uk-card uk-card-default uk-card-body uk-margin-top">
<h6 class="field-label">Creators</h6>
<div class="uk-flex">
<ul>
<li *ngFor="let creator of payload.creators">
<span>{{creator.creatorName.value}}</span>
</li>
</ul>
</div>
</div>
<div *ngIf="payload?.contributors?.length > 0" class="uk-card uk-card-default uk-card-body uk-margin-top">
<h6 class="field-label">Contributors</h6>
<div class="uk-flex">
<ul>
<li *ngFor="let contributor of payload.contributors">
<span>{{contributor.contributorName.value}}</span>
</li>
</ul>
</div>
</div>
<div *ngIf="relatedDatasets?.length > 0" class="uk-card uk-card-default uk-card-body uk-margin-top">
<h6 class="field-label">Related datasets</h6>
<div class="uk-flex">
<ul>
<li *ngFor="let relatedIdentifier of relatedDatasets">
<a [routerLink]="['/dataset', relatedIdentifier.id]">{{relatedIdentifier.name}}</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<!--<div>-->
<!-- <pre>{{payload | json}}</pre>-->
<!--</div>-->
<div id="delete-modal" uk-modal>
<div class="uk-modal-dialog uk-modal-body">
<button class="uk-modal-close-default" type="button" uk-close></button>
<h6>Permanently delete this {{resourceType === 'tool' ? 'tool':'model'}}?</h6>
<p class="uk-text-right">
<button class="uk-button uk-button-default uk-modal-close uk-margin-small-right" type="button">Cancel</button>
<button class="uk-button uk-button-danger uk-modal-close" type="button" (click)="deleteItem()" >Delete</button>
</p>
</div>
</div>

View File

@ -0,0 +1,83 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Component, OnInit} from "@angular/core";
import {ActivatedRoute, Router} from "@angular/router";
import {ResourcePayloadService} from "../../../services/resource-payload.service";
import {LandingPageService} from "../../../../catalogue-ui/services/landing-page.service";
import {environment} from "../../../../environments/environment";
import {AuthenticationService} from "../../../services/authentication.service";
import UIkit from "uikit";
@Component({
selector: 'app-payload-landing',
templateUrl: 'payload.component.html',
providers: [ResourcePayloadService, LandingPageService, AuthenticationService]
})
export class PayloadComponent implements OnInit{
projectName = environment.projectName
payload = null;
resourceType: string = null;
relatedDatasets: {id: string, name: string}[] = [];
constructor(private route: ActivatedRoute, private resourcePayloadService: ResourcePayloadService,
private landingPageService: LandingPageService, protected authService: AuthenticationService,
private router: Router) {
}
ngOnInit() {
this.route.params.subscribe(params => {
this.resourceType = params['resourceType'];
this.resourcePayloadService.getItem(params['resourceType'], params['identifierValue']).subscribe(
next => {this.payload = next;},
error => {console.log(error);},
() => {
this.relatedDatasets = [];
for (let i = 0; i < this.payload?.relatedIdentifiers?.length; i++) {
if (this.payload.relatedIdentifiers[i].resourceTypeGeneral === 'DATASET') {
this.landingPageService.getDataset(this.payload.relatedIdentifiers[i].value).subscribe(
next => {
this.relatedDatasets.push({id: this.payload.relatedIdentifiers[i].value, name: next['name']});
}
);
}
}
}
);
});
}
deleteItem() {
this.resourcePayloadService.deleteItem(this.payload['id'], this.resourceType).subscribe(
res => {
// UIkit.modal('#delete-modal').hide();
this.router.navigate([`/search/${this.resourceType}`]);
},
error => {
// UIkit.modal('#delete-modal').hide();
console.error(error);
}
);
}
hasRole() {
return this.authService.userRoles.includes('OPERATOR_DEVELOPER');
}
}

View File

@ -0,0 +1,171 @@
<div class="uk-section uk-section-default" style="min-height: 100vh">
<div class="uk-container uk-container-large uk-margin">
<h4 class="uk-margin">Request Data</h4>
<div *ngIf="!instance">
<div class="uk-grid uk-child-width-1-3">
<a [routerLink]="['/search']">
<div class="uk-card uk-card-default uk-card-hover uk-card-body">
<div class="uk-placeholder">
Select dataset....
</div>
</div>
</a>
</div>
</div>
<div *ngIf="instance" class="uk-margin-medium-top">
<form [formGroup]="dataForm" role="form" class="uk-form">
<h6>Selected Dataset</h6>
<div class="uk-grid uk-child-width-1-2">
<div>
<div class="uk-card uk-card-default uk-card-body">
<div class="">
<div class="">
<div>{{instance['metadata']['version']}} of {{instance['type']}}</div>
<div>created on {{instance['metadata']['dates'][0]['value']}} by {{instance['metadata']['creators'][0]['creatorName']}}</div>
</div>
</div>
</div>
</div>
</div>
<h6>Apply Filters</h6>
<div class="uk-card uk-card-default uk-card-body">
<div class="">
<div class="uk-margin-medium-bottom">
<div class="uk-inline uk-margin-right">
<label class="" for="entity">Entity </label>
<div class="uk-inline">
<select class="uk-input uk-select" id="entity">
<!-- <select class="uk-input uk-select" id="entity" formControlName="entity">-->
<option value="publication" selected>Publication</option>
</select>
</div>
</div>
<div class="uk-inline">
<a style="background:none; border:none;" (click)="sampleModal()">View Sample</a>
</div>
</div>
<div class="uk-margin-medium-bottom">
<label class="uk-form-label uk-text-right" for="dateFrom">Date From</label>
<div class="uk-form-controls uk-margin-top">
<input id="dateFrom" class="uk-input uk-width-9-10" type="date" lang="gr" formControlName="dateFrom">
</div>
</div>
<div class="uk-margin-medium-bottom">
<label class="uk-form-label uk-text-right" for="dateTo">Date To</label>
<div class="uk-form-controls uk-margin-top">
<input id="dateTo" class="uk-input uk-width-9-10" type="date" lang="gr" formControlName="dateTo">
</div>
</div>
<div formArrayName="funder" class="uk-margin-medium-bottom">
<label class="uk-form-label uk-text-right" for="funder">Publisher</label>
<div class="uk-form-controls uk-margin-top">
<div *ngFor="let funder of getFieldAsFormArray('funder').controls; let i=index"
class="uk-margin-bottom uk-flex uk-flex-middle">
<input id="funder" class="uk-input uk-width-9-10 uk-animation-slide-top-small" type="text" [formControlName]="i">
<a *ngIf="getFieldAsFormArray('funder').length > 1" class="remove-element uk-padding-small"
(click)="remove('funder', i)">
<span class="material-icons">clear</span>
</a>
</div>
<div class="uk-width-9-10 uk-text-center uk-margin-medium-top">
<a class="add-new-element" (click)="push('funder')">
<i class="" aria-hidden="true"></i>+ Add Publisher
</a>
</div>
</div>
</div>
<div formArrayName="journal" class="uk-margin-medium-bottom">
<label class="uk-form-label uk-text-right" for="journal">Journal</label>
<div class="uk-form-controls uk-margin-top">
<div *ngFor="let journal of getFieldAsFormArray('journal').controls; let i=index"
class="uk-margin-bottom uk-flex uk-flex-middle">
<input id="journal" class="uk-input uk-width-9-10 uk-animation-slide-top-small" type="text" [formControlName]="i">
<a *ngIf="getFieldAsFormArray('journal').length > 1" class="remove-element uk-padding-small"
(click)="remove('journal', i)">
<span class="material-icons">clear</span>
</a>
</div>
<div class="uk-width-9-10 uk-text-center uk-margin-medium-top">
<a class="add-new-element" (click)="push('journal')">
<i class="" aria-hidden="true"></i>+ Add Journal
</a>
</div>
</div>
</div>
<div class="uk-margin-medium-bottom">
<label class="uk-form-label uk-text-right">Projects</label>
<div class="uk-form-controls uk-margin-top">
<div formArrayName="projects" *ngFor="let project of projectArray.controls; let i = index" class="uk-flex uk-flex-top">
<div [formGroupName]="i" class="uk-margin-bottom formGroupElement uk-width-9-10 uk-display-inline-block">
<div class="">
<label class="uk-form-label uk-text-right" for="name">Project Name</label>
<div class="uk-form-controls uk-margin-top">
<input id="name" class="uk-input" type="text" formControlName="name">
</div>
</div>
<div class="uk-margin-small-top">
<label class="uk-form-label uk-text-right" for="acronym">Project Acronym</label>
<div class="uk-form-controls uk-margin-top">
<input id="acronym" class="uk-input" type="text" formControlName="acronym">
</div>
</div>
</div>
<a *ngIf="getFieldAsFormArray('projects').length > 1" class="remove-element uk-padding-small"
(click)="removeProject(i)">
<span class="material-icons">clear</span>
</a>
</div>
<div class="uk-width-9-10 uk-text-center uk-margin-top">
<a class="add-new-element" (click)="pushProject()">
<i class="" aria-hidden="true"></i>+ Add Project
</a>
</div>
</div>
</div>
</div>
<div class="uk-flex uk-flex-right">
<button type="submit" class="uk-button uk-button-primary uk-margin-medium-top"
[ngClass]="!dataForm.touched?'uk-disabled':''" (click)="submit()">
Get my data
</button>
</div>
</div>
</form>
</div>
</div>
</div>
<!--fixme sample is per entity-->
<!--fixme find a better way to format sample-->
<div id="sampleModal" class="uk-flex-top uk-modal-container" uk-modal="bg-close: true; esc-close: true;">
<div class="uk-modal-dialog uk-modal-body uk-margin-auto-vertical">
<div *ngIf="dataset">
<ng-container *ngIf="dataset['schema']['entities'][0]['sample']">
<code><pre>{{this.formatXml(dataset['schema']['entities'][0]['sample'], '\t')}}</pre></code>
</ng-container>
</div>
</div>
</div>

View File

@ -0,0 +1,254 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Component, OnDestroy, OnInit} from "@angular/core";
import {FormArray, FormBuilder, FormGroup} from '@angular/forms';
import {NavigationService} from "../../services/navigation.service";
import {CatalogueService} from "../../services/catalogue.service";
import {Job, JobArgument} from "../../domain/job";
import {Router} from "@angular/router";
import {Subscriber} from "rxjs";
declare var UIkit: any;
@Component({
selector: 'pages-request-data',
templateUrl: 'request-data.component.html'
})
export class RequestDataComponent implements OnInit, OnDestroy {
formPrepare = {
entity: 'publication',
dateFrom: '',
dateTo: '',
funder: this.fb.array([this.fb.control('')]),
journal: this.fb.array([this.fb.control('')]),
projects: this.fb.array([
this.fb.group({
name: [''],
acronym: ['']
})
])
};
dataForm: FormGroup
instance: Object = null;
dataset: Object = null;
internalId: string;
job: Job = new Job();
jobArguments = [];
subscriptions = [];
constructor(
private fb: FormBuilder,
public router: Router,
private navigationService: NavigationService,
private catalogueService: CatalogueService,
) {}
ngOnInit() {
console.log('running on init');
this.dataForm = this.fb.group(this.formPrepare);
this.subscriptions.push(
this.navigationService.dataRequestIds.subscribe(
dataRequestIds => {
console.log(dataRequestIds);
if (dataRequestIds?.datasetId != null && dataRequestIds?.instanceVersion != null) {
this.subscriptions.push(
this.catalogueService.getResourceTypeById(dataRequestIds.datasetId, 'dataset_type').subscribe(
res => {
this.dataset = res;
this.subscriptions.push(
this.catalogueService.searchDatasetInstance('dataset_instance', this.dataset['name'], dataRequestIds.instanceVersion,).subscribe(
res => {
this.instance = res.results[0];
this.subscriptions.push(
this.catalogueService.getInternalId(this.dataset['name'], dataRequestIds.instanceVersion).subscribe(
res => {
this.internalId = res.toString();
this.navigationService.setDataRequestIds(null, null);
},
error => {console.log(error);}
)
);
}
)
);
}
)
);
} else {
console.log('There is no dataRequestIds');
}
},
error => {
console.log(error);
},
() => {}
)
);
}
ngOnDestroy(): void {
// this.navigationService.setDataRequestIds(null, null);
this.instance = null;
this.dataset = null;
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
}
});
}
submit() {
// this.job.jobArguments.push(new JobArguments('datasetId', this.instance['id']));
this.job.jobArguments.push(new JobArgument('datasetId', this.internalId));
for (const [key, value] of Object.entries(this.dataForm.getRawValue())) {
if (typeof value === 'object' && !Array.isArray(value) && value !== null) {
for (const [subKey, subValue] of Object.entries(this.dataForm.get(key).value)) {
// console.log(`${subKey}: ${subValue}`);
}
} else if (typeof value === 'object' && Array.isArray(value) && value !== null) {
let tmpArr = this.dataForm.get(key) as FormArray;
for (let i = 0; i < value.length; i++) {
if (typeof value[i] === 'object' && !Array.isArray(value[i])) {
for (let j = 0; j < tmpArr.length; j++) {
// console.log(tmpArr[j]);
}
// for (const [subKey, subValue] of Object.entries(this.dataForm.get(key)[i].value)) {
// console.log(`${subKey}: ${subValue}`);
// console.log(this.dataForm.get(key).get(subKey).value);
// }
} else if (value[i] !== '') {
// console.log(`${key}: ${value[i]}`);
this.job.jobArguments.push(new JobArgument(key, value[i].toString()));
}
}
} else if (value !== '' && key !== 'entity') {
// console.log(`${key}: ${value}`);
this.job.jobArguments.push(new JobArgument(key, value.toString()));
}
}
this.jobArguments.push({'jobArguments': this.job.jobArguments})
this.jobArguments.push({'version': this.instance['metadata']['version']});
this.jobArguments.push({'name': this.dataset['name']});
this.jobArguments.push({'entity': this.dataForm.get('entity').value});
this.job.callerAttributes = JSON.stringify(this.jobArguments);
// TODO: Fix manual processId setting when supported
switch (this.instance['type']) {
case 'OpenAIRE Graph': {
this.job.serviceArguments.processId = 'openaire-graph-kubernetes';
break;
}
case 'Clinical Trials': {
this.job.serviceArguments.processId = 'clinical-trials-kubernetes';
break;
}
case 'NIH Research Portfolios': {
this.job.serviceArguments.processId = 'nih-kubernetes';
break;
}
case 'European Job Portal': {
this.job.serviceArguments.processId = 'euraxess-kubernetes';
break;
}
case 'Semantic Scholar': {
this.job.serviceArguments.processId = 'semanticscholar-kubernetes';
break;
}
case 'Spanish Job Portal tecnoempleo.com': {
this.job.serviceArguments.processId = 'tecnoempleo-kubernetes';
break;
}
}
this.subscriptions.push(
this.catalogueService.addJob(this.job).subscribe(
res => {
this.router.navigate([`/browseJobs`]);
},
error => {
this.job = new Job();
console.log(error);
}
)
);
}
/** manage form arrays--> **/
getFieldAsFormArray(field: string) {
return this.dataForm.get(field) as FormArray;
}
push(field: string) {
this.getFieldAsFormArray(field).push(this.fb.control(''));
}
remove(field: string, i: number) {
this.getFieldAsFormArray(field).removeAt(i);
}
/** projects **/
newProject(): FormGroup {
return this.fb.group({
name: [''],
acronym: ['']
});
}
get projectArray() {
return this.dataForm.get('projects') as FormArray;
}
pushProject() {
this.projectArray.push(this.newProject());
}
removeProject(index: number) {
this.projectArray.removeAt(index);
}
/** <--manage form arrays **/
sampleModal() {
UIkit.modal('#sampleModal').show();
}
formatXml(xml, tab) { // tab = optional indent value, default is tab (\t)
var formatted = '', indent= '';
tab = tab || '\t';
xml.split(/>\s*</).forEach(function(node) {
if (node.match( /^\/\w/ )) indent = indent.substring(tab.length); // decrease indent by one 'tab'
formatted += indent + '<' + node + '>\r\n';
if (node.match( /^<?\w[^>]*[^\/]$/ )) indent += tab; // increase indent
});
return formatted.substring(1, formatted.length-3);
}
}

View File

@ -0,0 +1,257 @@
<div id="tm-main" class="tm-main uk-section uk-section-default uk-section-small" uk-height-viewport="expand: true" style="box-sizing: border-box;">
<div class="uk-container uk-container-large">
<!--FILTERS LAPTOP & PAD LANDSCAPE-->
<div id="" class="uk-card uk-card-default uk-card-body">
<div *ngIf="searchResults != null" class="sidemenu refines">
<!--<div class="">Filter datasets</div>-->
<div class="uk-grid uk-margin-bottom">
<div class="uk-width-1-1">
<form class="" [formGroup]="searchForm"
(ngSubmit)="onSubmit(searchForm.controls['query'].value)">
<!-- <div class="uk-visible@m uk-margin-right">-->
<!-- <select *ngIf="showSearchFieldDropDown" class="uk-select menuSearchFields"-->
<!-- (change)="updateSearchField($event)" formControlName="searchFields">-->
<!-- <option value="">&#45;&#45;Search field&#45;&#45;</option>-->
<!-- <option *ngFor="let field of searchFields" value="{{field}}">{{field}}</option>-->
<!-- </select>-->
<!-- </div>-->
<div class="uk-inline uk-width-2-3@l uk-width-2-3@m uk-width-1-1@s">
<span class="uk-form-icon" uk-icon="icon: search"></span>
<input type="text" class="uk-input menuSearch" placeholder="Search a resource..." name="keyword" formControlName="query">
</div>
</form>
</div>
</div>
<div class="uk-grid">
<ng-template ngFor let-facet [ngForOf]="searchResults.facets">
<div *ngIf="facet.field === 'publisher' || facet.field === 'languages' || facet.field === 'rights'" class="uk-width-1-3@l uk-width-1-3@m uk-width-1-1@s uk-margin-bottom">
<div class="uk-flex uk-flex-bottom">
<!--<p class="big-text uk-margin-remove">{{facet.label}}</p>-->
<div class="uk-margin-small-bottom">{{facet.label}}</div>
<!-- <a class="uk-margin-left" (click)="clearSelections($event, facet.field)">Clear</a>-->
</div>
<ng-select class="uk-width-1-1 ng-select"
[items]="facet.values"
[multiple]="true"
[closeOnSelect]="false"
[hideSelected]="false"
[clearable]="false"
(remove)="clearFilter($event, facet.field)"
(add)="addFilter($event, facet.field)"
bindLabel="value"
[(ngModel)]="this[facet.field+'Filters']">
<ng-template ng-option-tmp let-item="item" let-item$="item$" let-index="index">
<input (change)="this.onSelection($event, facet.field, item.value)" id="item-{{index}}"
type="checkbox" [(ngModel)]="item$.selected" [checked]="item['isChecked']"/>
{{item.value + ' (' + item.count + ')'}}
</ng-template>
</ng-select>
<!-- <div class="refineOption uk-margin-top" *ngFor="let facetValue of facet.values">-->
<!-- <input type="checkbox" (change)="this.onSelection($event, facet.field, facetValue.value)"-->
<!-- [checked]="facetValue.isChecked">-->
<!-- {{facetValue.value}}-->
<!-- <span>({{facetValue.count}})</span>-->
<!-- </div>-->
</div>
</ng-template>
</div>
</div>
</div>
<div class="uk-width-expand@m uk-first-column">
<div *ngIf="errorMessage" class="">
<div data-uk-alert="" class="uk-alert uk-alert-danger">
<p>{{errorMessage}}</p>
</div>
</div>
<div *ngIf="!errorMessage && searchResults != null" class="">
<div *ngIf="!foundResults">
<div data-uk-alert="" class="uk-alert uk-alert-warning">
<p>No results found</p>
</div>
</div>
<div *ngIf="loading" class="whiteFilm">
<i class="fa fa-spinner fa-spin fa-5x uk-position-center loader" aria-hidden="true"></i>
</div>
<div *ngIf="searchResults.results != null && searchResults.results.length > 0">
<div class="uk-grid uk-row-first uk-margin-bottom uk-margin-large-top">
<div class="uk-width-1-1">
<div class="uk-flex uk-flex-between uk-flex-middle">
<div class=" uk-margin-remove">
Showing <span class="uk-text-bold">{{searchResults.from + 1}}</span> - <span class="uk-text-bold">{{searchResults.to}}</span> of <span class="uk-text-bold">{{searchResults.total}}</span> resources
<!--<span class="uk-text-bold">{{searchResults.total}}</span> Datasets, Page <span class="uk-text-bold">{{currentPage}}</span> of {{totalPages}}-->
</div>
<ng-container *ngIf="pages.length>1">
<ul class="uk-pagination uk-visible@m">
<li *ngIf="currentPage>2 && pageTotal>5"><a (click)="goToPage(1)"><span uk-pagination-previous></span><span uk-pagination-previous></span></a></li>
<li *ngIf="currentPage!==1"><a (click)="previousPage()"><span uk-pagination-previous></span></a></li>
<li *ngFor="let i of pages" [ngClass]="i === currentPage ? 'uk-active': ''">
<a (click)="goToPage(i)">{{i}}</a>
</li>
<li *ngIf="currentPage!==pageTotal"><a (click)="nextPage()"><span uk-pagination-next></span></a></li>
<li *ngIf="currentPage<pageTotal-1 && pageTotal>5"><a (click)="goToPage(pageTotal)"><span uk-pagination-next></span><span uk-pagination-next></span></a></li>
</ul>
</ng-container>
</div>
</div>
</div>
<div class="uk-grid-margin-small">
<ng-container *ngFor="let resourceInfo of searchResults.results; let i = index">
<a [routerLink]="[itemPath + resourceInfo['id']]" class="serviceDetails">
<div class="uk-card uk-card-default uk-card-hover uk-margin-bottom">
<!--LAPTOP & PAD LANDSCAPE-->
<div class="uk-card-body uk-visible@m">
<div>
<div class="uk-grid">
<div class="uk-width-2-3@m">
<div>
<h5 class="uk-margin-remove uk-text-left@m uk-text-center uk-scrollspy-inview uk-animation-fade uk-inline"
uk-scrollspy-class="" style="">
{{resourceInfo['name'] || "Not Available"}}
</h5>
</div>
<div class="uk-margin-small-top uk-scrollspy-inview uk-animation-fade serviceDescription line-clamp"
uk-scrollspy-class="" style="">
{{resourceInfo['metadata']['descriptions'][0]?.['value']}}
</div>
<div *ngIf="resourceInfo['metadata']['publisher']" class="uk-margin-small-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="">
<span class="field-label">Publisher: {{resourceInfo['metadata']['publisher']}}</span>
</div>
<div *ngIf="resourceInfo['metadata']['languages'][0] !== ''" class="uk-margin-small-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="" style="">
<span class="field-label">Language: </span>
<span *ngFor="let language of resourceInfo['metadata']['languages']" class="field-value uk-margin-small-left">{{language}}</span>
</div>
</div>
<div class="uk-width-1-3@m uk-padding-remove">
<div class="uk-flex uk-flex-right">
<img src="{{resourceInfo['metadata']['logo']}}" style="max-width: 300px;">
</div>
</div>
</div>
</div>
</div>
<!--MOBILE & PAD PORTRAIT-->
<div class="service-details-card-content uk-hidden@m">
<div class="uk-padding-remove service-image uk-flex uk-flex-center">
<img src="{{resourceInfo['metadata']['logo']}}" style="max-width: 250px;" class="uk-padding uk-padding-remove-bottom">
</div>
<div class="">
<!--<div class="uk-grid" uk-grid="">-->
<div>
<div class="uk-card-body">
<div>
<h5 class="uk-margin-remove uk-text-left uk-scrollspy-inview uk-animation-fade uk-inline"
uk-scrollspy-class="" style="">
{{resourceInfo['name'] || "Not Available"}}
</h5>
</div>
<div class="uk-margin-small-top uk-scrollspy-inview uk-animation-fade serviceDescription line-clamp"
uk-scrollspy-class="" style="">
{{resourceInfo['metadata']['descriptions'][0]?.['value']}}
</div>
<div *ngIf="resourceInfo['metadata']['publisher']" class="uk-margin-small-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="">
<span class="field-label">Publisher: {{resourceInfo['metadata']['publisher']}}</span>
</div>
<div *ngIf="resourceInfo['metadata']['languages'][0] !== ''" class="uk-margin-small-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="" style="">
<span class="field-label">Language: </span>
<span *ngFor="let language of resourceInfo['metadata']['languages']" class="field-value uk-margin-small-left">{{language}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</a>
</ng-container>
</div>
<ng-container *ngIf="pages.length>1">
<ul class="uk-pagination uk-flex-right uk-margin">
<li *ngIf="currentPage>2 && pageTotal>5"><a (click)="goToPage(1)"><span uk-pagination-previous></span><span uk-pagination-previous></span></a></li>
<li *ngIf="currentPage!==1"><a (click)="previousPage()"><span uk-pagination-previous></span></a></li>
<li *ngFor="let i of pages" [ngClass]="i === currentPage ? 'uk-active': ''">
<a (click)="goToPage(i)">{{i}}</a>
</li>
<li *ngIf="currentPage!==pageTotal"><a (click)="nextPage()"><span uk-pagination-next></span></a></li>
<li *ngIf="currentPage<pageTotal-1 && pageTotal>5"><a (click)="goToPage(pageTotal)"><span uk-pagination-next></span><span uk-pagination-next></span></a></li>
</ul>
</ng-container>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="searchResults != null" id="offcanvas-filters" uk-offcanvas="overlay: true">
<div class="uk-offcanvas-bar uk-padding-remove">
<div class="header uk-padding uk-flex uk-flex-middle">
<button class="uk-offcanvas-close" type="button" uk-close></button>
<p class="big-text-header uk-width-1-1 uk-text-center uk-margin-remove">Filters</p>
</div>
<div class="uk-padding">
<ng-template ngFor let-facet [ngForOf]="searchResults.facets">
<div *ngIf="facet.field === 'languages' || facet.field === 'rights' || facet.field === 'publisher'" class="uk-margin-medium-bottom">
<read-more [maxHeight]="235">
<p class="big-text uk-inline">{{facet.label}}</p><a class="uk-inline uk-link uk-margin-left uk-margin-small-bottom"
(click)="clearSelections($event, facet.field)">Clear</a>
<div class="refineOption" *ngFor="let facetValue of facet.values">
<input type="checkbox" class=""
(change)="this.onSelection($event, facet.field, facetValue.value)"
[checked]="facetValue.isChecked">
{{facetValue.value}}
<span>({{facetValue.count}})</span>
</div>
</read-more>
</div>
</ng-template>
</div>
</div>
</div>

View File

@ -0,0 +1,46 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Component} from "@angular/core";
import {SearchComponent} from "../../../catalogue-ui/pages/search/search.component";
import {SearchService} from "../../../catalogue-ui/services/search.service";
@Component({
selector: 'pages-intelcomp-search',
// templateUrl: '../../../catalogue-ui/pages/search/search.component.html',
templateUrl: './intelcomp-search.component.html',
providers: [SearchService]
})
export class IntelcompSearchComponent extends SearchComponent{
override itemPath = '/resource/';
rightsFilters = [];
languagesFilters = [];
publisherFilters = [];
clearFilter(e, filterType: string) {
e.value.isChecked = false;
let tmp = {'target': {'checked': false}};
this.onSelection(tmp, filterType, e.value.value);
}
addFilter(e, filterType: string) {
let tmp = {'target': {'checked': true}};
this.onSelection(tmp, filterType, e.value);
}
// makes more sense for Search component to be implemented and not to be extended
}

View File

@ -0,0 +1,168 @@
<div id="tm-main" class="tm-main uk-section uk-section-default uk-section-small" uk-height-viewport="expand: true" style="box-sizing: border-box;">
<div class="uk-container uk-container-large">
<div class="uk-grid uk-margin-bottom">
<div class="uk-width-1-1">
<div class="uk-flex uk-flex-center">
<div class="uk-inline uk-width-1-3@l uk-width-1-3@m uk-width-1-1@s">
<span class="uk-form-icon" uk-icon="icon: search"></span>
<input type="text" #searchInput class="uk-input menuSearch" placeholder="Search for tools..." [(ngModel)]="searchQuery"
[ngModelOptions]="{standalone: true}">
</div>
</div>
</div>
</div>
<div class="uk-width-expand@m uk-first-column">
<!-- <div *ngIf="errorMessage" class="">-->
<!-- <div data-uk-alert="" class="uk-alert uk-alert-danger">-->
<!-- <p>{{errorMessage}}</p>-->
<!-- </div>-->
<!-- </div>-->
<div *ngIf="payload != null" class="">
<div *ngIf="payload?.results?.length === 0; else results">
<div data-uk-alert="" class="uk-alert uk-alert-warning">
<p>No results found</p>
</div>
</div>
<!-- <div *ngIf="loading" class="whiteFilm">-->
<!-- <i class="fa fa-spinner fa-spin fa-5x uk-position-center loader" aria-hidden="true"></i>-->
<!-- </div>-->
<ng-template #results>
<div class="uk-grid uk-row-first uk-margin-bottom uk-margin-large-top">
<div class="uk-width-1-1">
<div class="uk-flex uk-flex-between uk-flex-middle">
<div class=" uk-margin-remove">
Showing <span class="uk-text-bold">{{payload.from + 1}}</span> - <span class="uk-text-bold">{{payload.to}}</span> of
<span class="uk-text-bold">{{payload.total}}</span> {{resourceType === 'tool' ? 'tools' : 'models'}}
<!--<span class="uk-text-bold">{{payload.total}}</span> Datasets, Page <span class="uk-text-bold">{{currentPage}}</span> of {{totalPages}}-->
</div>
<ng-container *ngIf="pages.length > 0">
<ul class="uk-pagination uk-visible@m">
<li *ngIf="currentPage > 2 && pageTotal > 5"><a (click)="goToPage(0)"><span uk-pagination-previous></span><span uk-pagination-previous></span></a></li>
<li *ngIf="currentPage > 0"><a (click)="previousPage()"><span uk-pagination-previous></span></a></li>
<li *ngFor="let i of pages" [ngClass]="i === currentPage ? 'uk-active': ''">
<a (click)="goToPage(i)">{{i+1}}</a>
</li>
<li *ngIf="currentPage < pageTotal-1"><a (click)="nextPage()"><span uk-pagination-next></span></a></li>
<li *ngIf="currentPage<pageTotal-1 && pageTotal>5"><a (click)="goToPage(pageTotal - 1)"><span uk-pagination-next></span><span uk-pagination-next></span></a></li>
</ul>
</ng-container>
</div>
</div>
</div>
<div class="uk-grid-margin-small">
<ng-container *ngFor="let result of payload.results; let i = index">
<a [routerLink]="['/landingPage', resourceType, result.identifier.value]" class="serviceDetails">
<div class="uk-card uk-card-default uk-card-hover uk-margin-bottom">
<!--LAPTOP & PAD LANDSCAPE-->
<div class="uk-card-body uk-visible@m">
<div>
<div class="uk-grid">
<div class="uk-width-2-3@m">
<div>
<h5 class="uk-margin-remove uk-text-left@m uk-text-center uk-scrollspy-inview uk-animation-fade uk-inline" uk-scrollspy-class="" style="">
{{result.titles[0]?.value}}
</h5>
</div>
<div *ngFor="let description of result?.descriptions">
<span *ngIf="description.descriptionType === 'ABSTRACT'" class="field-label">
Abstract: {{description.content}}
</span>
</div>
<div *ngIf="result?.resourceType?.value" class="uk-margin-small-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="">
<span class="field-label">Type: {{result?.resourceType?.value}}</span>
</div>
<div *ngIf="result?.version" class="uk-margin-small-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="">
<span class="field-label">Version: {{result?.version}}</span>
</div>
<div *ngIf="result?.publicationYear" class="uk-margin-small-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="">
<span class="field-label">Publication year: {{result?.publicationYear}}</span>
</div>
</div>
</div>
</div>
</div>
<!--MOBILE & PAD PORTRAIT-->
<div class="service-details-card-content uk-hidden@m">
<!-- <div class="uk-padding-remove service-image">-->
<!-- <img src="{{result['metadata']['logo']}}" style="max-height: 200px;">-->
<!-- </div>-->
<div class="">
<!--<div class="uk-grid" uk-grid="">-->
<div>
<div class="uk-card-body">
<div>
<h5 class="uk-margin-remove uk-text-left uk-scrollspy-inview uk-animation-fade uk-inline" uk-scrollspy-class="" style="">
{{result.titles[0]?.value}}
</h5>
</div>
<div *ngIf="result?.resourceType?.value" class="uk-margin-small-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="">
<span class="field-label">Type: {{result?.resourceType?.value}}</span>
</div>
<div *ngIf="result?.version" class="uk-margin-small-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="">
<span class="field-label">Version: {{result?.version}}</span>
</div>
<div *ngIf="result?.publicationYear" class="uk-margin-small-top uk-scrollspy-inview uk-animation-fade service-users" uk-scrollspy-class="">
<span class="field-label">Publication year: {{result?.publicationYear}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</a>
</ng-container>
</div>
<ng-container *ngIf="pages.length > 0">
<ul class="uk-pagination uk-flex-right uk-margin">
<li *ngIf="currentPage > 2 && pageTotal > 5"><a (click)="goToPage(0)"><span uk-pagination-previous></span><span uk-pagination-previous></span></a></li>
<li *ngIf="currentPage > 0"><a (click)="previousPage()"><span uk-pagination-previous></span></a></li>
<li *ngFor="let i of pages" [ngClass]="i === currentPage ? 'uk-active': ''">
<a (click)="goToPage(i)">{{i+1}}</a>
</li>
<li *ngIf="currentPage < pageTotal-1"><a (click)="nextPage()"><span uk-pagination-next></span></a></li>
<li *ngIf="currentPage<pageTotal-1 && pageTotal>5"><a (click)="goToPage(pageTotal-1)"><span uk-pagination-next></span><span uk-pagination-next></span></a></li>
</ul>
</ng-container>
</ng-template>
</div>
</div>
</div>
</div>
<!--<pre>{{payload.results | json}}</pre>-->

View File

@ -0,0 +1,144 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Component, ElementRef, OnInit, ViewChild} from "@angular/core";
import {ResourcePayloadService} from "../../../services/resource-payload.service";
import {Paging} from "../../../../catalogue-ui/domain/paging";
import {ActivatedRoute, Router} from "@angular/router";
import {URLParameter} from "../../../../catalogue-ui/domain/url-parameter";
import {debounceTime, distinctUntilChanged, filter, fromEvent} from "rxjs";
import {map} from "rxjs/operators";
@Component({
selector: 'app-tool-search',
templateUrl: 'resource-search.component.html',
providers: [ResourcePayloadService]
})
export class ResourceSearchComponent implements OnInit {
@ViewChild('searchInput', { static: true }) searchInput: ElementRef;
resourceType: string = null;
payload: Paging<any> = null
urlParameters: {key: string, values: string[]}[] = [];
pages: number[] = [];
pageTotal: number = 0;
pageSize: number = 10;
currentPage: number = 0;
searchQuery: string = null;
constructor(private resourcePayloadService: ResourcePayloadService, private route: ActivatedRoute,
private router: Router) {}
ngOnInit() {
this.route.params.subscribe(params => {
this.resourceType = params['resourceType'];
this.route.queryParams.subscribe(params => {
for (const [key, value] of Object.entries(params)) {
if (key === 'query') {
this.searchQuery = value;
}
}
this.resourcePayloadService.getItemsWithQueryParams(this.resourceType, params).subscribe(
next => {
this.payload = next;
this.initPagination(this.payload.from, this.payload.total);
},
error => {console.log(error)},
() => {}
)
})
});
fromEvent(this.searchInput.nativeElement, 'keyup').pipe(
map((event: any) => { // get value
return event.target.value;
})
// , filter(res => res.length > 2) // if character length greater then 2
, debounceTime(500) // Time in milliseconds between key events
, distinctUntilChanged() // If previous query is diffent from current
).subscribe((text: string) => {
this.updateURLParameters('query', text);
this.navigateUsingParameters();
}
);
}
updateURLParameters(key, value) {
for (const urlParameter of this.urlParameters) {
if (urlParameter.key === key) {
urlParameter.values = [value];
return;
}
}
this.urlParameters.push({key: key, values: [value]});
}
navigateUsingParameters() {
const map: { [name: string]: string; } = {};
for (const urlParameter of this.urlParameters) {
map[urlParameter.key] = urlParameter.values.join(',');
}
return this.router.navigate([`/search/${this.resourceType}`], {queryParams: map});
}
initPagination(from, total) {
this.currentPage = from / this.pageSize;
this.pageTotal = Math.ceil(total/this.pageSize);
this.pages = Array(this.pageTotal).fill(1).map((x,i)=>i);
}
goToPage(page: number) {
this.currentPage = page;
let from: number = (this.currentPage) * this.pageSize
this.updateURLParameters('from', from);
return this.navigateUsingParameters();
}
previousPage() {
if (this.currentPage > 0) {
this.currentPage--;
let from: number = (this.currentPage) * this.pageSize;
this.updateURLParameters('from', from);
this.navigateUsingParameters();
}
}
nextPage() {
if (this.currentPage < this.pageTotal-1) {
this.currentPage++;
let from: number = (this.currentPage) * this.pageSize;
this.updateURLParameters('from', from);
this.navigateUsingParameters();
}
}
searchOnEnter(e) {
if(e.key === 'Enter') {
// returning false will prevent the event from bubbling up.
this.updateURLParameters('query', this.searchQuery);
this.navigateUsingParameters();
return false;
} else{
return true;
}
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Injectable} from "@angular/core";
import {Router} from "@angular/router";
import {deleteCookie, getCookie} from "../../catalogue-ui/shared/reusable-components/cookie-management";
import {environment} from "../../../environments/environment";
import {UserService} from "./user.service";
@Injectable()
export class AuthenticationService {
base = environment.API_ENDPOINT;
loginEndPoint = environment.API_LOGIN;
cookieName = 'AccessToken';
constructor(private router: Router, private userService: UserService) {
}
tryLogin() {
if (getCookie(this.cookieName) === null) {
console.log('Didn\'t find cookie, user is not logged in.' );
sessionStorage.setItem('redirectUrl', window.location.pathname);
this.login();
} else {
console.log('found cookie, user is logged in');
}
}
login() {
sessionStorage.setItem('redirectUrl', window.location.pathname)
window.location.href = this.base + this.loginEndPoint;
}
logout() {
sessionStorage.clear();
deleteCookie(this.cookieName);
this.userService.clearUserInfo();
window.location.href = this.base + '/logout';
}
get userRoles(): string[] {
if (!sessionStorage.getItem('userRoles'))
return [];
return sessionStorage.getItem('userRoles').split(',');
}
get authenticated(): boolean {
// console.log(atob(getCookie(this.cookieName).split('.')[1]));
if (getCookie(this.cookieName) === null) {
sessionStorage.clear();
deleteCookie(this.cookieName);
this.userService.clearUserInfo();
return false;
}
return getCookie(this.cookieName) !== null;
}
redirect() {
if (sessionStorage.getItem('redirectUrl') !== null) {
let url = sessionStorage.getItem('redirectUrl');
// if (url === '/home')
// return;
sessionStorage.removeItem('redirectUrl');
this.router.navigate([url]);
}
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Injectable} from "@angular/core";
import {environment} from "../../../environments/environment";
import {HttpClient, HttpParams} from "@angular/common/http";
import {SurveyAnswer} from "../domain/survey";
import {BrowseJob, Job} from "../domain/job";
import {Paging} from "../../catalogue-ui/domain/paging";
@Injectable()
export class CatalogueService {
private options = {withCredentials: true};
base = environment.API_ENDPOINT;
constructor(public http: HttpClient) {
}
getResourceTypeById(id: string, resourceType: string) {
// console.log('knocking on:', this.base + `/items/${id}?resourceType=${resourceType}`);
return this.http.get(this.base + `/items/${id}?resourceType=${resourceType}`);
}
searchDatasetInstance(resourceType: string, datasetName: string, version?: string) {
let params = new HttpParams();
params = params.append('resourceType', resourceType);
params = params.append('type', datasetName);
if (version) {
params = params.append('version', version);
}
return this.http.get<Paging<any>>(this.base + '/items', {params});
}
getDatasetAnswer(id: string) {
return this.http.get<SurveyAnswer>(this.base + `/datasets/${id}`);
}
getJobs() {
return this.http.post<BrowseJob[]>(this.base + '/jobs', {})
}
addJob(job: Job) {
return this.http.post(this.base + '/jobs/execute', job) ;
}
getInternalId(type: string, version: string) {
return this.http.get(this.base + `/datasets/instances/${type}/${version}/internalid`, { responseType: 'text'});
}
getUiVocabularies() {
return this.http.get<Map<string, object[]>>(this.base + '/ui/vocabularies/map');
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Injectable} from "@angular/core";
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpErrorResponse} from "@angular/common/http";
import {Observable, throwError} from "rxjs";
import {catchError} from "rxjs/operators";
import {Router} from "@angular/router";
import {AuthenticationService} from "./authentication.service";
@Injectable()
export class HttpInterceptorService implements HttpInterceptor {
constructor(public router: Router, private authenticationService: AuthenticationService) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
catchError((response: HttpErrorResponse) => {
// console.log("error is intercept", response);
if (response.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', response.error.message);
} else {
if (response.status === 401) {
// console.log('trying to login');
this.authenticationService.tryLogin();
}
}
return throwError(response.message);
})
);
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Injectable} from "@angular/core";
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from "@angular/router";
import {Observable} from "rxjs";
import {AuthenticationService} from "./authentication.service";
@Injectable()
export class LoginGuardComponent implements CanActivate {
constructor(private authService: AuthenticationService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
if (this.authService.authenticated) {
return true;
}
this.router.navigate(['/home']);
return false;
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Injectable} from '@angular/core';
import {BehaviorSubject} from 'rxjs';
@Injectable()
export class NavigationService {
public dataRequestIds: BehaviorSubject<{instanceVersion:string, datasetId:string}> = new BehaviorSubject<{instanceVersion:string, datasetId:string}>(null);
constructor() {
}
go(url: string) {
location.href = url;
}
goOffsite(url: string) {
window.location.href = url;
}
public setDataRequestIds(instanceVersion: string, datasetId: string) {
console.log('instanceVersion: ' + instanceVersion + ', datasetId : ' + datasetId);
this.dataRequestIds.next({instanceVersion:instanceVersion, datasetId:datasetId});
}
public get dataRequestIds$() {
// console.log('get dataRequestIdsObservable', this.dataRequestIds);
return this.dataRequestIds.asObservable();
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Injectable} from "@angular/core";
import {environment} from "../../environments/environment";
import {HttpClient, HttpParams} from "@angular/common/http";
import {Paging} from "../../catalogue-ui/domain/paging";
import {Params} from "@angular/router";
@Injectable()
export class ResourcePayloadService {
base = environment.API_ENDPOINT;
constructor(private http: HttpClient) {}
getItemsByResourceType(resourceType: string, datasetId?: string) {
if (datasetId)
return this.http.get<Paging<any>>(this.base + `/items?resourceType=${resourceType}&datasets=${datasetId}`);
return this.http.get<Paging<any>>(this.base + `/items?resourceType=${resourceType}`);
}
getItemsWithQueryParams(resourceType: string, queryParameters?: Params) {
let params = new HttpParams();
if (!queryParameters)
return this.http.get<Paging<any>>(this.base + `/items?resourceType=${resourceType}`);
for (const [key, value] of Object.entries(queryParameters)) {
params = params.append(key, value);
}
return this.http.get<Paging<any>>(this.base + `/items?resourceType=${resourceType}`, {params: params});
}
getItem(resourceType: string, identifierValue: string) {
return this.http.get(this.base + `/items/search?resourceType=${resourceType}&field=identifier&value=${identifierValue}`);
}
getItemById(resourceType: string, id: string) {
return this.http.get(this.base + `/items/${id}?resourceType=${resourceType}`);
}
deleteItem(id: string, resourceType: string) {
return this.http.delete(this.base + `/items/${id}?resourceType=${resourceType}`);
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Injectable} from "@angular/core";
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from "@angular/router";
import {Observable} from "rxjs";
import {AuthenticationService} from "./authentication.service";
@Injectable()
export class RoleAuthGuardComponent implements CanActivate {
constructor(private authService: AuthenticationService, private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
let url: string = state.url;
return this.checkUserLogin(route, url);
}
checkUserLogin(route: ActivatedRouteSnapshot, url: any): boolean {
if (this.authService.authenticated && this.authService.userRoles) {
const userRoles = this.authService.userRoles;
if (userRoles.filter(value => route.data['roles'].includes(value)).length === 0){
this.router.navigate(['/home']);
return false;
}
return true;
}
this.router.navigate(['/home']);
return false;
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Injectable} from "@angular/core";
import {environment} from "../../../environments/environment";
import {HttpClient} from "@angular/common/http";
import {UserInfo} from "../domain/userInfo";
@Injectable()
export class UserService {
base = environment.API_ENDPOINT;
userInfo: UserInfo = null
constructor(public http: HttpClient) {}
getUserInfo() {
return this.http.get<UserInfo>(this.base + '/user/info');
}
getUserToken() {
return this.http.get(this.base + '/user/token');
}
roleToSessionStorage(userInfo: UserInfo) {
this.userInfo = userInfo;
sessionStorage.setItem('userRoles', userInfo.roles.toString());
}
clearUserInfo() {
this.userInfo = null;
sessionStorage.removeItem('userRoles')
}
}

View File

@ -0,0 +1,11 @@
.sidebar-actions-mobile {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 980;
}
.sidebar-actions-mobile > div {
padding: 10px 20px;
}

View File

@ -0,0 +1,29 @@
<!--MOBILE-->
<div class="sidebar-actions-mobile uk-background-secondary uk-hidden@m">
<div class="uk-container uk-flex-middle uk-grid uk-text-xsmall uk-text-meta uk-child-width-1-3">
<div>
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset">
<span class="uk-text-primary">
<div name="description" type="outlined" class="ng-star-inserted">
<span class="uk-flex ng-star-inserted">
<span class="material-icons outlined" style="font-size: 40px;">home</span>
</span>
</div>
</span>
<span>Home</span>
</a>
</div>
<div *ngIf="userInfo?.roles && hasRole('OPERATOR-WORKFLOW_PROCESSOR')">
<a class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-link-reset">
<span class="uk-text-primary">
<div name="description" type="outlined" class="ng-star-inserted">
<span class="uk-flex ng-star-inserted">
<span class="material-icons outlined" style="font-size: 40px;">analytics</span>
</span>
</div>
</span>
<span>Analyses</span>
</a>
</div>
</div>
</div>

View File

@ -0,0 +1,67 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Component, Input, OnDestroy, OnInit, ViewChild} from "@angular/core";
import {UserService} from "../../services/user.service";
import {UserInfo} from "../../domain/userInfo";
import {Subscriber} from "rxjs";
@Component({
selector: 'app-dashboard-navigation-mobile',
templateUrl: 'dashboard-navigation-mobile.component.html',
styleUrls: ['./dashboard-navigation-mobile.component.css']
})
export class DashboardNavigationMobileComponent implements OnInit, OnDestroy {
subscriptions = [];
toggle: number[] = [];
userInfo: UserInfo;
// roles = ['OPERATOR_DATA-PROCESSOR','OPERATOR_DATASET-INGESTOR','OPERATOR_DATASET-OWNER','OPERATOR_DEVELOPER']
constructor(private userService: UserService) {
}
ngOnInit() {
this.subscriptions.push(
this.userService.getUserInfo().subscribe(
res => {
this.userInfo = res;
this.userService.roleToSessionStorage(res);
// console.log(this.userInfo);
}, error => {
console.log(error);
this.userService.clearUserInfo()
}
)
);
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
}
});
}
hasRole(role: string) {
// console.log(role);
// console.log(this.userInfo.roles.indexOf(role) > -1);
return this.userInfo.roles.indexOf(role) > -1;
// return this.roles.indexOf(role) > -1;
}
}

View File

@ -0,0 +1,48 @@
/*#footer#3 {*/
/*margin-right: 280px;*/
/*}*/
/*#footer#9 a, #footer#11 a, #footer#13 a {*/
/*color: #dedede;*/
/*line-height: 22px;*/
/*padding: 2px 0;*/
/*}*/
#footer\#9 a, #footer\#11 a, #footer\#13 a {
color: #dedede;
line-height: 22px;
padding: 2px 0;
}
#footer\#9 a:hover, #footer\#11 a:hover, #footer\#13 a:hover {
color: rgba(255, 255, 255, 0.5);
}
@media all and (min-width: 640px) {
#footer\#3 {
margin-right: 280px;
}
}
#footer\#7 a {
color: rgba(255, 255, 255, 0.7) !important;
text-align: left;
font-size: 14px;
}
.uk-block-secondary {
background: #003D8C none repeat scroll 0 0;
}
.uk-block-secondary:not(.tm-block-texture) {
border-color: #003D8C;
}
.tm-bottom-d {
color: #ffffff;
font-size: 10px;
letter-spacing: 4px;
text-transform: uppercase;
}

View File

@ -0,0 +1,161 @@
<div class="uk-section uk-section-secondary footerSection uk-preserve-color">
<div class="uk-container uk-container-small uk-container-center">
<div class="uk-grid uk-padding">
<div class="uk-width-1-4@m uk-width-1-4@l uk-width-1-1@s">
<div class="uk-flex uk-flex-center uk-margin-medium-bottom">
<img src="/dataSpaceUI/assets/images/intelcomp-blanco-01.svg" style="max-width: 240px">
</div>
</div>
<div class="uk-width-3-4@m uk-width-3-4@l uk-width-1-1@s">
<div class="uk-flex uk-flex-stretch">
<span class="uk-margin-right footerImage">
<img src="/dataSpaceUI/assets/images/flag_of_europe.png" style="max-width: 80px">
</span>
<span>This project has received funding from the European Unions Horizon 2020 research and innovation programme
under grant agreement No. 101004870. H2020-SC6-GOVERNANCE-2018-2019-2020 / H2020-SC6-GOVERNANCE-2020</span>
</div>
<!--&lt;!&ndash;MOBILE & PAD PORTRAIT&ndash;&gt;-->
<!--<div class="uk-hidden@m">-->
<!--<div class="uk-margin-medium-top uk-text-left@s uk-text-center">-->
<!--<div class="uk-child-width-auto uk-grid-small uk-flex-left@s uk-flex-center uk-grid" uk-grid="">-->
<!--<div class="uk-first-column">-->
<!--<a href="http://www.twitter.com/OpenAIRE_eu" target="_blank" class="el-link uk-icon-button uk-icon">-->
<!--<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">-->
<!--<path d="M19,4.74 C18.339,5.029 17.626,5.229 16.881,5.32 C17.644,4.86 18.227,4.139 18.503,3.28 C17.79,3.7 17.001,4.009 16.159,4.17 C15.485,3.45 14.526,3 13.464,3 C11.423,3 9.771,4.66 9.771,6.7 C9.771,6.99 9.804,7.269 9.868,7.539 C6.795,7.38 4.076,5.919 2.254,3.679 C1.936,4.219 1.754,4.86 1.754,5.539 C1.754,6.82 2.405,7.95 3.397,8.61 C2.79,8.589 2.22,8.429 1.723,8.149 L1.723,8.189 C1.723,9.978 2.997,11.478 4.686,11.82 C4.376,11.899 4.049,11.939 3.713,11.939 C3.475,11.939 3.245,11.919 3.018,11.88 C3.49,13.349 4.852,14.419 6.469,14.449 C5.205,15.429 3.612,16.019 1.882,16.019 C1.583,16.019 1.29,16.009 1,15.969 C2.635,17.019 4.576,17.629 6.662,17.629 C13.454,17.629 17.17,12 17.17,7.129 C17.17,6.969 17.166,6.809 17.157,6.649 C17.879,6.129 18.504,5.478 19,4.74"></path>-->
<!--</svg>-->
<!--</a>-->
<!--</div>-->
<!--<div class="">-->
<!--<a href="https://www.linkedin.com/company/openaire-eu/" target="_blank" class="el-link uk-icon-button uk-icon">-->
<!--<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">-->
<!--<path d="M5.77,17.89 L5.77,7.17 L2.21,7.17 L2.21,17.89 L5.77,17.89 L5.77,17.89 Z M3.99,5.71 C5.23,5.71 6.01,4.89 6.01,3.86 C5.99,2.8 5.24,2 4.02,2 C2.8,2 2,2.8 2,3.85 C2,4.88 2.77,5.7 3.97,5.7 L3.99,5.7 L3.99,5.71 L3.99,5.71 Z"></path>-->
<!--<path d="M7.75,17.89 L11.31,17.89 L11.31,11.9 C11.31,11.58 11.33,11.26 11.43,11.03 C11.69,10.39 12.27,9.73 13.26,9.73 C14.55,9.73 15.06,10.71 15.06,12.15 L15.06,17.89 L18.62,17.89 L18.62,11.74 C18.62,8.45 16.86,6.92 14.52,6.92 C12.6,6.92 11.75,7.99 11.28,8.73 L11.3,8.73 L11.3,7.17 L7.75,7.17 C7.79,8.17 7.75,17.89 7.75,17.89 L7.75,17.89 L7.75,17.89 Z"></path>-->
<!--</svg>-->
<!--</a>-->
<!--</div>-->
<!--<div class="">-->
<!--<a href="http://www.facebook.com/groups/openaire/" target="_blank" class="el-link uk-icon-button uk-icon">-->
<!--<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">-->
<!--<path d="M11,10h2.6l0.4-3H11V5.3c0-0.9,0.2-1.5,1.5-1.5H14V1.1c-0.3,0-1-0.1-2.1-0.1C9.6,1,8,2.4,8,5v2H5.5v3H8v8h3V10z"></path>-->
<!--</svg>-->
<!--</a>-->
<!--</div>-->
<!--<div class="">-->
<!--<a href="https://www.youtube.com/channel/UChFYqizc-S6asNjQSoWuwjw" target="_blank" class="el-link uk-icon-button uk-icon">-->
<!--<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">-->
<!--<path d="M15,4.1c1,0.1,2.3,0,3,0.8c0.8,0.8,0.9,2.1,0.9,3.1C19,9.2,19,10.9,19,12c-0.1,1.1,0,2.4-0.5,3.4c-0.5,1.1-1.4,1.5-2.5,1.6 c-1.2,0.1-8.6,0.1-11,0c-1.1-0.1-2.4-0.1-3.2-1c-0.7-0.8-0.7-2-0.8-3C1,11.8,1,10.1,1,8.9c0-1.1,0-2.4,0.5-3.4C2,4.5,3,4.3,4.1,4.2 C5.3,4.1,12.6,4,15,4.1z M8,7.5v6l5.5-3L8,7.5z"></path>-->
<!--</svg>-->
<!--</a>-->
<!--</div>-->
<!--</div>-->
<!--<div class="uk-margin-medium-top newsletter-link uk-flex uk-flex-center">-->
<!--<div class="" style="margin-top: 7px;">Newsletter</div>-->
<!--<a class="uk-margin-small-left" href="https://www.openaire.eu/newsletter" target="_blank">-->
<!--<span class="el-image uk-icon" uk-icon="icon: rss; ratio: 1;">-->
<!--</span>-->
<!--</a>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--&lt;!&ndash;LAPTOP & PAD LANDSCAPE&ndash;&gt;-->
<!--<div class="uk-visible@m">-->
<!--<div class="uk-margin-top uk-text-left@s uk-text-center">-->
<!--<div class="uk-child-width-auto uk-grid-small uk-flex-left@s uk-flex-center uk-grid" uk-grid="">-->
<!--<div class="uk-first-column">-->
<!--<a href="http://www.twitter.com/OpenAIRE_eu" target="_blank" class="el-link uk-icon-button uk-icon">-->
<!--<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">-->
<!--<path d="M19,4.74 C18.339,5.029 17.626,5.229 16.881,5.32 C17.644,4.86 18.227,4.139 18.503,3.28 C17.79,3.7 17.001,4.009 16.159,4.17 C15.485,3.45 14.526,3 13.464,3 C11.423,3 9.771,4.66 9.771,6.7 C9.771,6.99 9.804,7.269 9.868,7.539 C6.795,7.38 4.076,5.919 2.254,3.679 C1.936,4.219 1.754,4.86 1.754,5.539 C1.754,6.82 2.405,7.95 3.397,8.61 C2.79,8.589 2.22,8.429 1.723,8.149 L1.723,8.189 C1.723,9.978 2.997,11.478 4.686,11.82 C4.376,11.899 4.049,11.939 3.713,11.939 C3.475,11.939 3.245,11.919 3.018,11.88 C3.49,13.349 4.852,14.419 6.469,14.449 C5.205,15.429 3.612,16.019 1.882,16.019 C1.583,16.019 1.29,16.009 1,15.969 C2.635,17.019 4.576,17.629 6.662,17.629 C13.454,17.629 17.17,12 17.17,7.129 C17.17,6.969 17.166,6.809 17.157,6.649 C17.879,6.129 18.504,5.478 19,4.74"></path>-->
<!--</svg>-->
<!--</a>-->
<!--</div>-->
<!--<div class="">-->
<!--<a href="https://www.linkedin.com/company/openaire-eu/" target="_blank" class="el-link uk-icon-button uk-icon">-->
<!--<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">-->
<!--<path d="M5.77,17.89 L5.77,7.17 L2.21,7.17 L2.21,17.89 L5.77,17.89 L5.77,17.89 Z M3.99,5.71 C5.23,5.71 6.01,4.89 6.01,3.86 C5.99,2.8 5.24,2 4.02,2 C2.8,2 2,2.8 2,3.85 C2,4.88 2.77,5.7 3.97,5.7 L3.99,5.7 L3.99,5.71 L3.99,5.71 Z"></path>-->
<!--<path d="M7.75,17.89 L11.31,17.89 L11.31,11.9 C11.31,11.58 11.33,11.26 11.43,11.03 C11.69,10.39 12.27,9.73 13.26,9.73 C14.55,9.73 15.06,10.71 15.06,12.15 L15.06,17.89 L18.62,17.89 L18.62,11.74 C18.62,8.45 16.86,6.92 14.52,6.92 C12.6,6.92 11.75,7.99 11.28,8.73 L11.3,8.73 L11.3,7.17 L7.75,7.17 C7.79,8.17 7.75,17.89 7.75,17.89 L7.75,17.89 L7.75,17.89 Z"></path>-->
<!--</svg>-->
<!--</a>-->
<!--</div>-->
<!--<div class="">-->
<!--<a href="http://www.facebook.com/groups/openaire/" target="_blank" class="el-link uk-icon-button uk-icon">-->
<!--<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">-->
<!--<path d="M11,10h2.6l0.4-3H11V5.3c0-0.9,0.2-1.5,1.5-1.5H14V1.1c-0.3,0-1-0.1-2.1-0.1C9.6,1,8,2.4,8,5v2H5.5v3H8v8h3V10z"></path>-->
<!--</svg>-->
<!--</a>-->
<!--</div>-->
<!--<div class="">-->
<!--<a href="https://www.youtube.com/channel/UChFYqizc-S6asNjQSoWuwjw" target="_blank" class="el-link uk-icon-button uk-icon">-->
<!--<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">-->
<!--<path d="M15,4.1c1,0.1,2.3,0,3,0.8c0.8,0.8,0.9,2.1,0.9,3.1C19,9.2,19,10.9,19,12c-0.1,1.1,0,2.4-0.5,3.4c-0.5,1.1-1.4,1.5-2.5,1.6 c-1.2,0.1-8.6,0.1-11,0c-1.1-0.1-2.4-0.1-3.2-1c-0.7-0.8-0.7-2-0.8-3C1,11.8,1,10.1,1,8.9c0-1.1,0-2.4,0.5-3.4C2,4.5,3,4.3,4.1,4.2 C5.3,4.1,12.6,4,15,4.1z M8,7.5v6l5.5-3L8,7.5z"></path>-->
<!--</svg>-->
<!--</a>-->
<!--</div>-->
<!--<div class="uk-margin-medium-left newsletter-link uk-flex uk-flex-middle">-->
<!--<div class="" style="margin-top: 7px;">Newsletter</div>-->
<!--<a class="uk-margin-small-left" href="https://www.openaire.eu/newsletter" target="_blank">-->
<!--<span class="el-image uk-icon" uk-icon="icon: rss; ratio: 1;">-->
<!--</span>-->
<!--</a>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
</div>
</div>
<div class="uk-grid uk-margin-remove" uk-grid="">
<div class="uk-width-expand@m uk-width-expand@l uk-width-expand@s">
<div class="uk-margin-top uk-flex uk-flex-center uk-visible@m">
<a class="footerLink">Disclaimer and privacy policy</a>
<a class="footerLink uk-margin-left">Cookies policy</a>
</div>
<!--Mobile-->
<div class="uk-margin-top uk-flex uk-flex-center uk-flex-column uk-hidden@m">
<a class="footerLink uk-text-center uk-margin-bottom">Disclaimer and privacy policy</a>
<a class="footerLink uk-text-center uk-margin-bottom">Cookies policy</a>
</div>
<!--<div id="footer#22" class="uk-flex uk-flex-stretch uk-text-small uk-margin-medium-top uk-margin-remove-bottom uk-text-center@m uk-text-center uk-text-lead">-->
<!--<a href="http://creativecommons.org/licenses/by/4.0/" rel="license">-->
<!--<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" width="24" height="24" class=" uk-svg uk-margin-small-right">-->
<!--<title></title>-->
<!--<g data-name="Creative Commons" id="Creative_Commons">-->
<!--<circle cx="12" cy="12" r="11.5" style="fill:none;stroke:#fff;stroke-linecap:round;stroke-linejoin:round"></circle>-->
<!--<path d="M10.87,10a3.5,3.5,0,1,0,0,4" style="fill:none;stroke:#fff;stroke-linecap:round;stroke-linejoin:round"></path>-->
<!--<path d="M18.87,10a3.5,3.5,0,1,0,0,4" style="fill:none;stroke:#fff;stroke-linecap:round;stroke-linejoin:round"></path>-->
<!--</g>-->
<!--</svg>-->
<!--<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" width="24" height="24" class=" uk-svg">-->
<!--<title></title>-->
<!--<g id="Attribution">-->
<!--<g data-name="<Group>" id="_Group_">-->
<!--<circle cx="12" cy="5" data-name="<Path>" id="_Path_" r="1.5" style="fill:none;stroke:#fff;stroke-linecap:round;stroke-linejoin:round"></circle>-->
<!--<path d="M12,8a5,5,0,0,0-3.07.71,1,1,0,0,0-.43.83V15H10v5.5h4V15h1.5V9.54a1,1,0,0,0-.43-.83A5,5,0,0,0,12,8Z" data-name="<Path>" id="_Path_2" style="fill:none;stroke:#fff;stroke-linecap:round;stroke-linejoin:round"></path>-->
<!--</g>-->
<!--<circle cx="12" cy="12" r="11.5" style="fill:none;stroke:#fff;stroke-linecap:round;stroke-linejoin:round"></circle>-->
<!--</g>-->
<!--</svg>-->
<!--</a>-->
<!--<span class="uk-margin-small-left">Unless otherwise indicated, all materials created by OpenAIRE are licenced under&nbsp;<a href="http://creativecommons.org/licenses/by/4.0/" rel="license" class="uk-margin-small-left">CC ATTRIBUTION 4.0 INTERNATIONAL LICENSE</a>.</span>-->
<!--</div>-->
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,25 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Component} from '@angular/core';
@Component({
selector: 'app-footer-intelcomp',
templateUrl: './footer.component.html',
styleUrls: ['./footer.component.css']
})
export class IntelcompFooterComponent {
}

View File

@ -0,0 +1,24 @@
<div id="page_content">
<div id="page_content_inner">
<h2 class="heading_b uk-margin-bottom uk-margin-large-top uk-text-center">Error: 403 Forbidden</h2>
<div class="uk-grid">
<!-- MIDDLE -->
<div class=" uk-width-expand@m">
<div style="font-size: 180px; color: #28beFF; line-height: 1.2;" class="uk-text-center">
<strong>403</strong>
</div>
<div class="uk-text-center">
Sorry, access to this resource on the server is forbidden.<br>
Either check the URL or <a href="/home">go home</a>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,33 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
/**
* Created by stefania on 20/04/2018.
*/
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'forbidden-page',
templateUrl: './403-forbidden-page.component.html',
})
export class ForbiddenPageComponent implements OnInit {
ngOnInit() {
let body = document.getElementsByTagName('body')[0];
body.classList.remove("landing");
body.classList.add("dashboard");
}
}

View File

@ -0,0 +1,156 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
/**
* angular2-cookie-law
*
* Copyright 2016-2017, @andreasonny83, All rights reserved.
*
* @author: @andreasonny83 <andreasonny83@gmail.com>
*/
import {
DomSanitizer,
SafeHtml,
} from '@angular/platform-browser';
import {
CookieLawService,
} from './cookie-law.service';
import { Component, EventEmitter, HostBinding, Input, OnInit, Output } from '@angular/core';
import { animate, AnimationEvent, state, style, transition, trigger } from '@angular/animations';
// import {
// closeIcon,
// } from './icons';
export type CookieLawPosition = 'top' | 'bottom';
export type CookieLawAnimation = 'topIn' | 'bottomIn' | 'topOut' | 'bottomOut';
export type CookieLawTarget = '_blank' | '_self';
@Component({
selector: 'cookie-law',
// encapsulation: ViewEncapsulation.None,
animations: [
trigger('state', [
state('bottomOut', style({ transform: 'translateY(100%)' })),
state('topOut', style({ transform: 'translateY(-100%)' })),
state('*', style({ transform: 'translateY(0)' })),
transition('void => topIn', [
style({ transform: 'translateY(-100%)' }),
animate('1000ms ease-in-out'),
]),
transition('void => bottomIn', [
style({ transform: 'translateY(100%)' }),
animate('1000ms ease-in-out'),
]),
transition('* => *', animate('1000ms ease-out')),
])
],
styleUrls: [ './cookie-law.css' ],
templateUrl: './cookie-law.html',
})
export class CookieLawComponent implements OnInit {
public cookieLawSeen: boolean;
@Input('learnMore')
get learnMore() { return this._learnMore; }
set learnMore(value: string) {
this._learnMore = (value !== null && `${value}` !== 'false') ? value : null;
}
@Input('target')
get target() { return this._target; }
set target(value: CookieLawTarget) {
this._target = (value !== null && `${value}` !== 'false' &&
(`${value}` === '_blank' || `${value}` === '_self')
) ? value : '_blank';
}
@Input('position')
get position() { return this._position; }
set position(value: CookieLawPosition) {
this._position = (value !== null && `${value}` !== 'false' &&
(`${value}` === 'top' || `${value}` === 'bottom')
) ? value : 'bottom';
}
@Output('isSeen')
private isSeenEvt: EventEmitter<boolean>;
@HostBinding('attr.seen')
public isSeen: boolean;
private animation: CookieLawAnimation;
private closeSvg: SafeHtml;
private currentStyles: {};
private _learnMore: string;
private _target: CookieLawTarget;
private _position: CookieLawPosition;
constructor(
private _service: CookieLawService,
private domSanitizer: DomSanitizer,
) {
this.isSeenEvt = new EventEmitter<boolean>();
this.animation = 'topIn';
this._position = 'bottom';
this.cookieLawSeen = this._service.seen();
}
ngOnInit(): void {
if (typeof document !== 'undefined') {
this.animation = this.position === 'bottom' ? 'bottomIn' : 'topIn';
this.closeSvg = `
<span class="clickable uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="close" ratio="1">
<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>`;
if (this.cookieLawSeen) {
this.isSeen = true;
}
this.currentStyles = {
'top': this.position === 'top' ? '0' : null,
'bottom': this.position === 'top' ? 'initial' : null,
};
}
}
afterDismissAnimation(evt: AnimationEvent) {
if (evt.toState === 'topOut' ||
evt.toState === 'bottomOut') {
this.isSeen = true;
this.isSeenEvt.emit(this.isSeen);
}
}
public dismiss(evt?: MouseEvent): void {
if (evt) {
evt.preventDefault();
}
this._service.storeCookie();
this.animation = this.position === 'top' ? 'topOut' : 'bottomOut';
}
}

View File

@ -0,0 +1,77 @@
.cookie-law-wrapper a {
color: #bbb;
-webkit-transition: color .2s;
transition: color .2s;
}
.cookie-law-wrapper a:hover {
color: #fff;
}
.cookie-law-wrapper a:hover svg {
fill: #fff;
}
.cookie-law-wrapper {
background: #333;
color: #bbb;
display: block;
/*font-family: Helvetica Neue,Helvetica,Arial,sans-serif;
font-size: 15px;
font-weight: 200;
line-height: 20px;*/
position: fixed;
bottom: 0;
left: 0;
width: 100%;
z-index: 100;
font-smooth: always;
-webkit-font-smoothing: antialiased;
text-align: center;
}
.dismiss {
display: block;
box-sizing: border-box;
padding: 10px;
position: absolute;
top: 0;
right: 10px;
text-decoration: none;
line-height: 20px;
}
.dismiss svg {
display: block;
fill: #bbb;
width: 20px;
height: 20px;
-webkit-transition: fill .2s;
transition: fill .2s;
}
.copy {
box-sizing: border-box;
padding: 10px 60px 10px 10px;
}
.copy span {
color: #fff;
/*font-weight: 400;*/
}
.copy a {
text-decoration: underline;
}
.copy a:active, .copy a:hover {
outline: 0;
}
@media (min-width: 600px) {
/* For bigger devices: */
.copy {
padding: 20px 60px 20px 20px;
/*font-size: 18px;
line-height: 24px;*/
}
.dismiss {
top: 10px;
right: 15px;
}
.dismiss svg {
width: 24px;
height: 24px;
}
}

View File

@ -0,0 +1,25 @@
<div class="cookie-law-wrapper"
[ngStyle]="currentStyles"
*ngIf="!cookieLawSeen"
[@state]="animation"
(@state.done)="afterDismissAnimation($event)">
<div class="copy">
<span #ref><ng-content></ng-content></span>
<span *ngIf="ref.childNodes.length == 0">
By continuing to browse the site, you're agreeing to our use of cookies.
<span *ngIf="learnMore">
Learn more in our <a [href]="learnMore" [target]="target">privacy policy</a>.
</span>
</span>
<a href="#" role="button" class="dismiss" (click)="dismiss($event)">
<span class="clickable uk-icon">
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" icon="close" ratio="1">
<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>
</a>
</div>
</div>

View File

@ -0,0 +1,40 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
/**
* angular2-cookie-law
*
* Copyright 2016-2017, @andreasonny83, All rights reserved.
*
* @author: @andreasonny83 <andreasonny83@gmail.com>
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CookieLawComponent } from './cookie-law.component';
import { CookieLawService } from './cookie-law.service';
@NgModule({
imports: [ CommonModule ],
declarations: [ CookieLawComponent ],
providers: [ CookieLawService ],
exports: [ CookieLawComponent ]
})
export class CookieLawModule { }
export {
CookieLawComponent,
CookieLawService
};

View File

@ -0,0 +1,77 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
/**
* angular2-cookie-law
*
* Copyright 2016-2017, @andreasonny83, All rights reserved.
*
* @author: @andreasonny83 <andreasonny83@gmail.com>
*/
import { Injectable } from '@angular/core';
@Injectable()
export class CookieLawService {
seen(): boolean {
return this.cookieExists('cookieLawSeen');
}
storeCookie(): void {
return this.setCookie('cookieLawSeen');
}
/**
* try to read a saved cookie
*
* @param {string} name [the cookie name]
*
* @return {string} [the cookie's value]
*/
private cookieExists(name: string): boolean {
if (typeof document !== 'undefined') {
let ca: Array<string> = document.cookie.split(';');
let caLen: number = ca.length;
let cookieName = name + '=';
let c: string;
for (let i: number = 0; i < caLen; i += 1) {
c = ca[i].replace(/^\s\+/g, '');
if (c.indexOf(cookieName) !== -1) {
return true;
}
}
}
return false;
}
/**
* store a new cookie in the browser
*
* @param {string} name [the name for the cookie]
*/
private setCookie(name: string): void {
if (typeof document !== 'undefined') {
let d:Date = new Date();
d.setTime(d.getTime() + 3*30 * 24 * 60 * 60 * 1000); // in 3 months
let expires:string = `expires=${d.toUTCString()}`;
document.cookie = encodeURIComponent(name) + '=true; path=/; expires='+expires+';';
}
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
/**
* angular2-cookie-law
*
* Copyright 2016-2017, @andreasonny83, All rights reserved.
*
* @author: @andreasonny83 <andreasonny83@gmail.com>
*/
export const closeIcon: string = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M377.047 184.198q0 8.26-6.037 14.297L313.505 256l57.505 57.505q6.037 6.037 6.037 14.297 0 8.578-6.037 14.615l-28.593 28.593q-6.037 6.037-14.615 6.037-8.26 0-14.297-6.037L256 313.505l-57.505 57.505q-6.037 6.037-14.297 6.037-8.578 0-14.615-6.037l-28.593-28.593q-6.037-6.037-6.037-14.615 0-8.26 6.037-14.297L198.495 256l-57.505-57.505q-6.037-6.037-6.037-14.297 0-8.578 6.037-14.615l28.593-28.593q6.037-6.037 14.615-6.037 8.26 0 14.297 6.037L256 198.495l57.505-57.505q6.037-6.037 14.297-6.037 8.578 0 14.615 6.037l28.593 28.593q6.037 6.037 6.037 14.615zM500 256q0-66.401-32.724-122.477-32.724-56.075-88.799-88.799Q322.401 12 256 12q-66.401 0-122.477 32.724-56.075 32.724-88.799 88.799Q12 189.599 12 256q0 66.401 32.724 122.477 32.724 56.075 88.799 88.799Q189.599 500 256 500q66.401 0 122.477-32.724 56.075-32.724 88.799-88.799Q500 322.401 500 256z"></path>
</svg>
`;

View File

@ -0,0 +1,88 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
/**
* Created by stefania on 4/6/17.
*/
import {AfterContentInit, AfterViewInit, Component, ElementRef, Input, OnChanges, ViewChild} from "@angular/core";
@Component({
selector: "read-more",
template: `
<div [class.collapsed]="isCollapsed" [style.height]="isCollapsed ? maxHeight+'px' : 'auto'" #readMoreDiv>
<ng-content></ng-content>
</div>
<a *ngIf="isCollapsable" (click)="isCollapsed =! isCollapsed">View {{isCollapsed ? 'more' : 'less'}}...</a>
`,
styles: [`
div.collapsed {
overflow: hidden;
}
`]
})
export class ReadMoreComponent implements AfterContentInit {
//the text that need to be put in the container
//@Input() text: string;
//maximum height of the container
@Input("maxHeight") maxHeight: number = 100;
@ViewChild("readMoreDiv", { static: true })
readMoreDiv: ElementRef;
//set these to false to get the height of the expended container
public isCollapsed: boolean = false;
public isCollapsable: boolean = false;
constructor(public elementRef: ElementRef) {
}
ngAfterContentInit() {
setTimeout(_ => {
let currentHeight = this.readMoreDiv.nativeElement.offsetHeight;
//collapsable only if the contents make container exceed the max height
if (currentHeight > this.maxHeight) {
this.isCollapsed = true;
this.isCollapsable = true;
} else {
}
}, 200);
}
}
@Component({
selector: "read-more-text",
template: `
<div [innerHTML]="text" [class.collapsed]="isCollapsed" [style.height]="isCollapsed ? maxHeight+'px' : 'auto'" #readMoreDiv>
<!--{{text}}-->
</div>
<a *ngIf="isCollapsable" (click)="isCollapsed =! isCollapsed">View {{isCollapsed ? 'more' : 'less'}}...</a>
`,
styles: [`
div.collapsed {
overflow: hidden;
}
`]
})
export class ReadMoreTextComponent extends ReadMoreComponent implements OnChanges, AfterViewInit {
@Input() text: string = "";
ngAfterViewInit(): void {
this.ngAfterContentInit();
}
ngOnChanges(): void {
this.ngAfterContentInit();
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
/**
* Created by stefania on 4/6/17.
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { ForbiddenPageComponent } from './403-forbidden-page.component';
import { ReadMoreComponent, ReadMoreTextComponent } from './read-more.component';
import { SideMenuDashboardComponent } from "../sidemenudashboard/side-menu-dashboard.component";
import { TopMenuLandingComponent } from "../top-menu/topmenulanding/top-menu-landing.component";
import { DashboardNavigationMobileComponent } from "../dashboard-navigation-mobile/dashboard-navigation-mobile.component";
@NgModule({
imports: [
CommonModule,
RouterModule,
// TabsModule.forRoot(),
// ModalModule.forRoot(),
FormsModule,
ReactiveFormsModule,
HttpClientModule,
],
declarations: [
TopMenuLandingComponent,
SideMenuDashboardComponent,
DashboardNavigationMobileComponent,
// FooterComponent,
ForbiddenPageComponent,
ReadMoreComponent,
ReadMoreTextComponent,
],
exports: [
TopMenuLandingComponent,
SideMenuDashboardComponent,
DashboardNavigationMobileComponent,
// SideMenuComponent,
// FooterComponent,
ForbiddenPageComponent,
ReadMoreComponent,
ReadMoreTextComponent,
],
providers: [
// HelpContentService
],
})
export class ReusableComponentsModule {
}

View File

@ -0,0 +1,33 @@
#sidebar_main #sidebar_toggle:hover {
background-color: var(--intelcomp-light-color) !important;
color: var(--white);
}
#sidebar_main {
background-color: var(--intelcomp-dark-color);
color: var(--white);
/*max-height: calc(100svh - var(--header-height));*/
/*overflow-y: auto;*/
/*overflow-x: hidden;*/
}
#sidebar_main .menu_section .material-icons {
color: var(--white) !important;
}
.menu_section .current_section .material-icons {
background-color: var(--intelcomp-light-color) !important;
/*color: var(--white);*/
}
#sidebar_main .menu_section > ul > li > a {
color: var(--white) !important;
}
#sidebar_main .menu_section > ul > li.current_section a {
color: var(--white) !important;
}
#sidebar_main .menu_section h6 {
color: var(--intelcomp-light-color);
}

View File

@ -0,0 +1,107 @@
<aside id="sidebar_main" >
<div id="sidebar_toggle" class="" (click)="toggleSidebar()"></div>
<div class="menu_section uk-margin-medium-top">
<ul>
<li [routerLinkActive]="['current_section']">
<a [routerLink]="['/dashboard']" class="uk-flex uk-flex-middle">
<span class="material-icons uk-margin-right">dashboard</span>
<span class="menu_title">Dashboard</span>
</a>
</li>
</ul>
</div>
<div *ngIf="userInfo?.roles && (hasRole('OPERATOR_DATASET-OWNER') || hasRole('OPERATOR_DATASET-INGESTOR'))"
class="menu_section border_top">
<div class="header uk-text-light uk-text-uppercase uk-margin-remove uk-text-primary">Resources</div>
<ul>
<li *ngIf="hasRole('OPERATOR_DATASET-OWNER')" [routerLinkActive]="['current_section']" class="">
<a [routerLink]="['requests', 'create']" class="uk-flex uk-flex-middle">
<span class="material-icons uk-margin-right">input</span>
<span class="menu_title">Request Resource</span>
</a>
</li>
<li [routerLinkActive]="['current_section']" class="">
<a [routerLink]="['requests', 'all']" class="uk-flex uk-flex-middle">
<span class="material-icons uk-margin-right">file_download</span>
<span class="menu_title">Resource Requests</span>
</a>
</li>
<li *ngIf="hasRole('OPERATOR_DATASET-INGESTOR')" [routerLinkActive]="['current_section']" class="">
<a [routerLink]="['form', 'dataset_type']" class="uk-flex uk-flex-middle">
<span class="material-icons uk-margin-right">description</span>
<span class="menu_title">Register Resource</span>
</a>
</li>
</ul>
</div>
<div *ngIf="userInfo?.roles && hasRole('OPERATOR_DATA-PROCESSOR')" class="menu_section border_top">
<div class="header uk-text-light uk-text-uppercase uk-margin-remove uk-text-primary">Data</div>
<ul>
<li [routerLinkActive]="['current_section']" class="">
<a [routerLink]="['request-data']" class="uk-flex uk-flex-middle">
<span class="material-icons uk-margin-right">download</span>
<span class="menu_title">Request Data</span>
</a>
</li>
<li [routerLinkActive]="['current_section']" class="">
<a [routerLink]="['browseJobs']" class="uk-flex uk-flex-middle">
<span class="material-icons uk-margin-right">storage</span>
<span class="menu_title">My Data Requests</span>
</a>
</li>
</ul>
</div>
<div *ngIf="userInfo?.roles && hasRole('OPERATOR_DEVELOPER')" class="menu_section border_top">
<div class="header uk-text-light uk-text-uppercase uk-margin-remove uk-text-primary">Tools / Models</div>
<ul>
<li [routerLinkActive]="['current_section']" class="">
<a [routerLink]="['/form/tool']" class="uk-flex uk-flex-middle">
<span class="material-icons uk-margin-right">description</span>
<span class="menu_title">Register tool</span>
</a>
</li>
<li [routerLinkActive]="['current_section']" class="">
<a [routerLink]="['/form/ai_model']" class="uk-flex uk-flex-middle">
<span class="material-icons uk-margin-right">description</span>
<span class="menu_title">Register model</span>
</a>
</li>
</ul>
</div>
<div *ngIf="userInfo?.roles && (hasRole('OPERATOR-WORKFLOW_PROCESSOR') && hasRole('EASTER'))" class="menu_section border_top">
<div class="header uk-text-light uk-text-uppercase uk-margin-remove uk-text-primary">Datasets</div>
<ul>
<li [routerLinkActive]="['current_section']" class="">
<a [routerLink]="['/datasets/upload']" class="uk-flex uk-flex-middle">
<span class="material-icons uk-margin-right">upload</span>
<span class="menu_title">Upload dataset</span>
</a>
</li>
<li [routerLinkActive]="['current_section']" class="">
<a [routerLink]="['/datasets/my']" class="uk-flex uk-flex-middle">
<span class="material-icons uk-margin-right">file_copy</span>
<span class="menu_title">My datasets</span>
</a>
</li>
</ul>
</div>
<div *ngIf="userInfo?.roles && hasRole('OPERATOR-WORKFLOW_PROCESSOR')" class="menu_section border_top">
<div class="header uk-text-light uk-text-uppercase uk-margin-remove uk-text-primary">Analyses</div>
<ul>
<li [routerLinkActive]="['current_section']" class="">
<a [routerLink]="['/workflowSearch']" class="uk-flex uk-flex-middle">
<span class="material-icons uk-margin-right">description</span>
<span class="menu_title">History</span>
</a>
</li>
</ul>
</div>
</aside><!-- main sidebar end -->

View File

@ -0,0 +1,83 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Component, Input, OnDestroy, OnInit, ViewChild} from "@angular/core";
import {UserService} from "../../services/user.service";
import {UserInfo} from "../../domain/userInfo";
import {Subscriber} from "rxjs";
@Component({
selector: 'app-side-menu-dashboard',
templateUrl: 'side-menu-dashboard.component.html',
styleUrls: ['./side-menu-dashboard.component.css']
})
export class SideMenuDashboardComponent implements OnInit, OnDestroy {
subscriptions = [];
toggle: number[] = [];
userInfo: UserInfo;
// roles = ['OPERATOR_DATA-PROCESSOR','OPERATOR_DATASET-INGESTOR','OPERATOR_DATASET-OWNER','OPERATOR_DEVELOPER']
constructor(private userService: UserService) {
}
ngOnInit() {
this.subscriptions.push(
this.userService.getUserInfo().subscribe(
res => {
this.userInfo = res;
this.userService.roleToSessionStorage(res);
// console.log(this.userInfo);
}, error => {
console.log(error);
this.userService.clearUserInfo()
}
)
);
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
}
});
}
hasRole(role: string) {
// console.log(role);
// console.log(this.userInfo.roles.indexOf(role) > -1);
return this.userInfo.roles.indexOf(role) > -1;
// return this.roles.indexOf(role) > -1;
}
toggleSidebar() {
const el: HTMLElement = document.getElementById('sidebar_toggle');
if(!el.classList.contains('closed')) {
el.classList.add('closed');
const el1: HTMLElement = document.getElementById('sidebar_main_content');
el1.classList.remove('sidebar_main_active');
el1.classList.add('sidebar_main_inactive');
} else {
el.classList.remove('closed');
const el1: HTMLElement = document.getElementById('sidebar_main_content');
el1.classList.add('sidebar_main_active');
el1.classList.remove('sidebar_main_inactive');
}
}
}

View File

@ -0,0 +1,167 @@
/*.fixed-navbar {*/
/*position: fixed;*/
/*z-index: 1000;*/
/*height: 80px;*/
/*display: flex;*/
/*background: #ffffff 0% 0% no-repeat padding-box;*/
/*background-color: rgb(255, 255, 255);*/
/*box-shadow: 0 0 6px #00000029;*/
/*opacity: 1;*/
/*top: 0;*/
/*left: 0;*/
/*right: 0;*/
/*}*/
#header_main {
left: 0;
position: fixed;
right: 0;
top: 0;
z-index: 1000;
/*height: 100px;*/
}
.uk-navbar-container:not(.uk-navbar-transparent) {
box-shadow: 0 0 6px #00000029;
background: #fff;
}
/*.uk-navbar-container {*/
/*height: 90px;*/
/*}*/
.user_actions circle, .user_actions svg {
/*stroke: #707070;*/
stroke: #151f2e;
fill: #151f2e;
}
.user_actions text {
/*stroke: #707070;*/
stroke: white;
fill: white;
}
.projectLogo {
background-image: var(--logo);
background-repeat: no-repeat;
background-size: contain;
width: 200px;
height: var(--logo-height);
padding: 10px;
}
.logo img {
width: 200px;
padding: 10px;
}
a.logo span {
/*color: #004494;*/
color: var(--primary-color);
/*font-weight: bold;*/
font-size: 18px;
/*border-left: 1px solid #004494;*/
border-left: 1px solid var(--primary-color);
padding-left: 20px;
margin-left: 15px;
}
.hamburger {
display: inline-block;
cursor: pointer;
padding: .6rem;
margin-left: .8rem;
margin-right: .8rem;
}
.hamburger:hover {
background-color: #ececec !important;
border-radius: 50%;
}
.icon-bar1, .icon-bar2, .icon-bar3 {
width: 18px;
height: 2px;
background-color: #333;
margin: 3px 0;
transition: .4s;
}
.change .icon-bar1 {
transform: rotate(-45deg) translate(-3px,3px);
}
.change .icon-bar2 {
opacity: 0;
}
.change .icon-bar3 {
transform: rotate(45deg) translate(-4px,-4px);
}
a.uk-icon span {
color: #1A1A1A;
}
.uk-dropdown .uk-nav.uk-dropdown-nav > li a, .uk-dropdown .uk-nav.uk-dropdown-nav > li.user-info {
padding: 5px 20px;
color: #1A1A1A;
}
.uk-dropdown .uk-nav.uk-dropdown-nav > li a:hover {
background-color: #ececec;
}
.uk-navbar-dropdown {
width: 280px;
padding: 25px 0px;
}
.uk-navbar-dropdown-nav > li {
padding: 0px 25px;
}
.uk-nav > li > a {
/*padding: 5px 15px;*/
padding: 5px 30px;
}
.uk-navbar-dropdown-nav > li > a, .uk-navbar-dropdown-nav > li > a:hover {
color: #212121;
}
.uk-navbar-dropdown-nav > li:hover, .uk-navbar-dropdown-nav > li.uk-active {
color: #212121;
background: var(--primary-color-background) 0% 0% no-repeat padding-box;
opacity: 1;
}
.uk-navbar-nav>li.uk-active>a {
color: var(--intelcomp-light-color);
}
.uk-navbar-nav>li.uk-active>a:before {
content: "";
display: block;
position: absolute;
z-index: -1;
top: 0;
height: 2px;
transition: .35s ease-in-out;
transition-property: all;
left: 50%;
right: 50%;
opacity: 0;
background: var(--intelcomp-light-color);
}
.uk-navbar-nav>li.uk-active>a:before {
left: 0px;
right: 0px;
opacity: 1;
}

View File

@ -0,0 +1,159 @@
<!--NO MOBILE-->
<div id="header_main" class="main-menu tm-header uk-visible@m tm-header-transparent">
<div >
<nav class="uk-navbar-container uk-container uk-container-expand" uk-navbar>
<div class="uk-navbar-left">
<a [routerLink]="['home']" class="uk-logo uk-navbar-item">
<img src="{{logoURL}}" alt="Opix Platform" class="" width="150px" height="80px">
</a>
</div>
<div class="uk-navbar-center">
<ul class="uk-navbar-nav">
<li class="uk-parent" [routerLinkActive]="['uk-active']">
<a class="" [routerLink]="['/home']" aria-expanded="false">Home</a>
</li>
<li *ngIf="(userInfo?.roles && (hasRole('OPERATOR_DATASET-OWNER') || hasRole('OPERATOR_DATASET-INGESTOR')
|| hasRole('OPERATOR_DATA-PROCESSOR') || hasRole('OPERATOR_DEVELOPER'))) || projectName !== 'Opix'"
class="uk-parent" [routerLinkActive]="['uk-active']">
<a href="#" class="" aria-expanded="false">
Browse catalogue
</a>
<div class="uk-navbar-dropdown uk-navbar-dropdown-bottom-left" id="browse" uk-toggle>
<div class="uk-navbar-dropdown-grid uk-child-width-1-1 uk-grid uk-grid-stack" uk-grid="">
<div class="uk-first-column">
<ul class="uk-nav uk-navbar-dropdown-nav">
<li [routerLinkActive]="'uk-active'" [routerLinkActiveOptions]="{exact: true}"><a routerLink="/search" routerLinkActive="uk-active" href="/search">Resources</a></li>
<li [routerLinkActive]="'uk-active'"><a routerLink="/search/tool" routerLinkActive="uk-active" href="/search/tool">Tools & Workflows</a></li>
</ul>
</div>
</div>
</div>
</li>
<li class="uk-parent" *ngIf="userInfo && hasRoles()" [routerLinkActive]="['uk-active']">
<a class="" [routerLink]="['/dashboard']" aria-expanded="false">My dashboard</a>
</li>
</ul>
</div>
<div class="uk-navbar-right">
<div id="navigation">
<ul *ngIf="isLoggedIn() && userInfo; else elseBlock" class="uk-navbar-nav user_actions">
<li>
<div>
<a class="uk-icon ng-star-inserted" aria-expanded="false">
<svg height="60" width="60">
<circle cx="30" cy="30" r="20" stroke-width="1"></circle>
<text dy=".4em" font-size="16" text-anchor="middle" x="50%" y="50%" class="ng-star-inserted"> {{parseUsername()}} </text>
</svg>
</a>
<div class="uk-padding-remove-horizontal ng-star-inserted uk-dropdown" uk-dropdown="mode: click; offset: -2; delay-hide: 0; flip: false; pos: bottom-right">
<ul class="uk-nav uk-dropdown-nav">
<li>
<a id="logout" (click)="logout()">Log out</a>
</li>
</ul>
</div>
</div>
</li>
</ul>
<ng-template #elseBlock>
<ul class="uk-navbar-nav user_actions">
<li>
<div>
<a class="uk-button uk-button-link" (click)="logInButton()">Login</a>
</div>
</li>
</ul>
</ng-template>
</div>
</div>
</nav>
</div>
</div>
<!--MOBILE-->
<div class="uk-hidden@m">
<nav class="uk-navbar-container uk-navbar" uk-navbar="delay-hide: 400">
<div class="uk-navbar-left">
<a href="#tm-mobile" class="uk-navbar-toggle" uk-toggle>
<div class="uk-navbar-toggle-icon uk-icon">
<span class="material-icons">menu</span>
</div>
</a>
</div>
<div class="uk-navbar-center">
<a [routerLink]="['home']" class="uk-navbar-item uk-logo"><img alt="Opix Platform" src="{{logoURL}}" style="width: 140px"></a>
</div>
<div class="uk-navbar-right login">
<div *ngIf="isLoggedIn() && userInfo; else elseMobileBlock">
<a class="uk-icon ng-star-inserted user-info" aria-expanded="false">
<svg height="60" width="60">
<circle cx="30" cy="30" r="20" stroke-width="1"></circle>
<text dy=".4em" font-size="16" text-anchor="middle" x="50%" y="50%" class="ng-star-inserted"> {{parseUsername()}} </text>
</svg>
</a>
<div class="uk-padding-remove-horizontal ng-star-inserted uk-dropdown" uk-dropdown="mode: click; offset: -2; delay-hide: 0; flip: false; pos: bottom-right">
<ul class="uk-nav uk-dropdown-nav">
<li>
<a id="logout-mobile" (click)="logout()">Log out</a>
</li>
</ul>
</div>
</div>
<ng-template #elseMobileBlock>
<a class="navbar-user-icon" (click)="logInButton()">
<div name="login" ratio="1.5"><span class="uk-icon uk-flex ng-star-inserted" style=""><svg width="30" height="30" viewBox="0 0 700 700" xmlns="http://www.w3.org/2000/svg"><g><path d="m151.67 536.67c0-109.47 88.863-198.34 198.33-198.34s198.33 88.867 198.33 198.34c0 6.4375 5.2266 11.664 11.668 11.664s11.668-5.2266 11.668-11.664c0-122.34-99.332-221.67-221.67-221.67s-221.67 99.328-221.67 221.67c0 6.4375 5.2266 11.664 11.668 11.664s11.668-5.2266 11.668-11.664z" fill-rule="evenodd"></path><path d="m349.8 11.668c-77.164 0-139.8 62.637-139.8 139.8s62.637 139.8 139.8 139.8c77.164 0 139.8-62.637 139.8-139.8s-62.637-139.8-139.8-139.8zm0 23.332c64.285 0 116.47 52.184 116.47 116.47 0 64.281-52.184 116.47-116.47 116.47-64.281 0-116.47-52.188-116.47-116.47 0-64.285 52.188-116.47 116.47-116.47z" fill-rule="evenodd"></path></g></svg></span></div>
</a>
</ng-template>
</div>
</nav>
<div #canvas id="tm-mobile" [attr.uk-offcanvas]="'mode: none; overlay: true'"
class="uk-offcanvas">
<div class="uk-offcanvas-bar-light uk-padding-remove">
<nav class="uk-navbar uk-background-default" uk-sticky>
<div class="uk-navbar-left">
<button class="uk-navbar-toggle uk-icon uk-close" (click)="closeCanvas(canvas)">
<div name="close" ratio="1.5" visuallyhidden="close menu" style="margin-left: -0.5em;">
<span class="uk-display-inline-block ng-star-inserted">
<span class="material-icons" style="font-size: 30px;">close</span>
</span>
</div>
</button>
</div>
<div class="uk-navbar-center">
<a class="uk-logo uk-navbar-item uk-flex uk-flex-middle ng-star-inserted">
<img src="{{logoURL}}" alt="Opix Platform" width="140px">
</a>
</div>
</nav>
<ul class="uk-nav uk-nav-primary uk-list uk-list-large uk-margin-large-top uk-nav-parent-icon" uk-nav>
<li [routerLinkActive]="['uk-active']">
<a [routerLink]="['/home']" (click)="closeCanvas(canvas)">Home</a>
</li>
<!-- <li [routerLinkActive]="['uk-active']">-->
<!-- <a href="">Test 2</a>-->
<!-- </li>-->
<!-- <li>-->
<!-- <a href="">Test 3</a>-->
<!-- </li>-->
<li *ngIf="hasRoles()" [routerLinkActive]="['uk-active']">
<a [routerLink]="['/dashboard']">My dashboard</a>
</li>
</ul>
</div>
</div>
</div>

View File

@ -0,0 +1,88 @@
/*
* Copyright 2021-2024 OpenAIRE AMKE
*
* 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
*
* https://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.
*/
import {Component, OnInit} from "@angular/core";
import {AuthenticationService} from "../../../services/authentication.service";
import {environment} from "../../../../../environments/environment";
import {UserService} from "../../../services/user.service";
import {UserInfo} from "../../../domain/userInfo";
declare var UIkit;
@Component({
selector: 'app-top-menu-landing',
templateUrl: 'top-menu-landing.component.html',
styleUrls: ['../top-menu.component.css'],
})
export class TopMenuLandingComponent implements OnInit {
subscriptions = [];
userInfo: UserInfo = null;
projectName = environment.projectName;
logoURL = environment.logoURL ? environment.logoURL : 'https://www.opix.ai/images/Logos/opix%20logo%202.svg';
constructor(private authentication: AuthenticationService, private userService: UserService) {
}
ngOnInit() {
this.subscriptions.push(
this.userService.getUserInfo().subscribe(
res => {
this.userInfo = res;
this.userService.roleToSessionStorage(res);
// console.log(this.userInfo);
}, error => {
console.log(error);
this.userService.clearUserInfo();
}
)
);
}
closeCanvas(element) {
UIkit.offcanvas(element).hide();
}
parseUsername() {
let firstLetters = "";
let matches = this.userInfo.fullname?.match(/\b(\w)/g);
if(matches)
firstLetters += matches.join('');
return firstLetters;
}
hasRoles() {
return this.authentication.userRoles.length > 0
}
hasRole(role: string) {
return this.userInfo.roles.indexOf(role) > -1;
}
logInButton() {
this.authentication.login();
}
logout() {
this.authentication.logout();
}
isLoggedIn() {
return this.authentication.authenticated;
}
}

View File

View File

@ -0,0 +1,997 @@
@import url("https://use.typekit.net/dwa4ieu.css");
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap');
@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&display=swap');
/*:root {*/
/*--primary-color: #004494;*/
/*--link-color: #2D72D6;*/
/*--link-hover-color: #3665ab;*/
/*--breadcrumb-active-color: #26C0E2;*/
/*--button-primary-hover-background-color: #1E95B0;*/
/*--button-secondary-color: #fff;*/
/*--button-secondary-background-color: #26C0E2;*/
/*--button-secondary-hover-background-color: #1E95B0;*/
/*}*/
:root {
--primary-color-background: #ffcce2;
--intelcomp-light-color: #ff006e;
--intelcomp-dark-color: #151F2E;
--sidebar-width: 320px;
--sidebar-width-invert: -320px;
--toggle-sidebar-closed: 338px;
--dashboard-transition-delay: 0.25s;
--sidebar-font-size: 16px;
//--sidebar-width: 280px;
//--header-height: 80px;
--white: #fff;
--main-font-family: 'Aileron';
--secondary-font-family: 'Bitter';
--black: #1A1A1A;
--grey: #6E6E6E;
--catalogue-light-purple: #AD20E7;
--catalogue-dark-purple: #1D193C;
--light-grey: #F9F9F9;
--medium-grey: #F5F5F5;
--dark-grey: #2B2B2B;
--eosc-blue: #3A75AB;
--openaire-light-blue: #3086ED;
--default-element-bg: #DEDEDE;
--grey-900: #2C2C2C;
--grey-700: #6E6E6E;
--primary-color: #ff006e;
/*--primary-color: #AD20E7;*/
--link-color: #2D72D6;
--link-hover-color: #3665ab;
--breadcrumb-active-color: #4687E6;
--button-primary-hover-background-color: #9FCC52;
--button-secondary-color: #fff;
--button-secondary-background-color: #3086ED;
--button-secondary-hover-background-color: #0053ba;
--logo: url('../../assets/images/intelcomp-logo.svg');
--logo-height: 40px;
--home-hero-image: url('https://intelcomp.eu/sites/default/files/2022-09/img-background-2.png');
--header-height: 60px;
}
body {
font-family: var(--main-font-family), sans-serif !important;
color: var(--black) !important;
background-color: var(--medium-grey) !important;
font-size: 16px;
opacity: 1;
}
/*.uk-container-xlarge {*/
/*max-width: 1500px;*/
/*}*/
.uk-section-default {
background-color: var(--medium-grey) !important;
}
.uk-section-secondary {
background-color: var(--intelcomp-dark-color);
color: var(--light-grey);
/*background-color: #fafafa;*/
/*color: #424242 !important;*/
}
.uk-section-primary {
/*background-color: #222080;*/
background-color: #fff;
background-image: none;
}
.uk-padding-xlarge {
padding: 100px;
}
.uk-background-default {
background-color: #fff;
}
.uk-background-secondary {
background-color: var(--intelcomp-dark-color);
}
.uk-text-normal {
font-weight: 400 !important;
}
.uk-display-none {
display: none;
}
.sidebar_main_active #page_content {
//margin-left: 280px;
margin-left: var(--sidebar-width);
}
.header-margin {
margin-top: var(--header-height);
}
.home-hero {
min-height: 900px;
background-image: var(--home-hero-image);
background-repeat: no-repeat;
background-size: cover;
}
/* ========================================================================
Label - custom
========================================================================== */
.uk-label-secondary {
background: var(--grey);
}
/* ========================================================================
Link - overrides
========================================================================== */
//a, .uk-link {
// color: var(--intelcomp-dark-color);
//}
/* ========================================================================
Sidebar - overrides
========================================================================== */
.sidebar_main_swipe #sidebar_main .menu_section .header {
padding: 10px 20px;
}
.sidebar_main_swipe #sidebar_main .menu_section > ul > li > a {
padding: 5px 20px;
}
#sidebar_main .menu_section {
padding-bottom: 15px;
padding-top: 15px;
}
#sidebar_main .menu_section.border_top {
border-top: 1px solid #6E6E6E;
}
/* ========================================================================
Modal - custom
========================================================================== */
.uk-modal.modal-secondary .uk-modal-header {
background-color: var(--intelcomp-dark-color);
}
.uk-modal.modal-secondary .uk-modal-header h4.uk-modal-title {
color: var(--white);
}
.uk-modal.modal-secondary .uk-modal-close-full {
background: transparent;
}
.uk-modal.modal-secondary .uk-close {
color: var(--white);
}
/* ========================================================================
Dropdown - custom
========================================================================== */
.filters-dropdown {
max-width: 400px !important;
overflow-wrap: break-word;
}
/* ========================================================================
Table - custom
========================================================================== */
//.table-simple.uk-table thead tr {
// background-color: var(--primary-color-background);
// border-radius: 6px;
//}
//
//.table-simple.uk-table th {
// text-transform: none;
//}
.card-table.uk-table thead tr {
background-color: var(--primary-color-background);
}
.card-table.uk-table th {
text-transform: none;
}
.card-table.uk-table th.extra-left-padding, .card-table.uk-table td.extra-left-padding {
padding-left: 30px;
}
.card-table.uk-table th.extra-right-padding, .card-table.uk-table td.extra-right-padding {
padding-right: 30px;
}
.card-table td {
font-size: 14px;
}
/* ========================================================================
Margins
========================================================================== */
.uk-margin-xlarge-top {
margin-top: 100px !important;
}
.uk-margin-xlarge-bottom {
margin-bottom: 100px !important;
}
/* ========================================================================
Color and Typography
========================================================================== */
h1, h2, h3, h4, h5, h6 {
color: var(--grey-900);
/*text-align: left;*/
letter-spacing: 0px;
opacity: 1;
}
h1 {
font: normal normal 600 66px/83px var(--main-font-family) !important;
}
h2 {
font: normal normal 600 52px/65px var(--main-font-family) !important;
}
h3 {
font: normal normal 600 41px/51px var(--main-font-family) !important;
}
h4 {
font: normal normal 600 32px/40px var(--main-font-family) !important;
}
h5 {
font: normal normal 600 26px/33px var(--main-font-family) !important;
}
h6 {
font: normal normal 600 20px/27px var(--main-font-family) !important;
}
.h1-subHeader {
color: var(--intelcomp-light-color);
/*text-align: left;*/
font: normal normal normal 20px/27px var(--main-font-family);
letter-spacing: 0px;
opacity: 1;
margin-bottom: 0.5em;
}
.h2-subHeader-blue {
color: var(--eosc-blue);
/*text-align: left;*/
font: normal normal 600 20px/27px var(--main-font-family);
letter-spacing: 0px;
opacity: 1;
margin-bottom: 0.5em;
}
.h5-subheader {
color: var(--catalogue-light-purple);
/*text-align: left;*/
font: normal normal normal 16px/24px var(--main-font-family);
letter-spacing: 0px;
opacity: 1;
margin-bottom: 0.5em;
}
@media only screen and (max-width: 960px) {
h1 {
font: normal normal 600 41px var(--main-font-family) !important;
}
h2 {
font: normal normal 600 36px var(--main-font-family) !important;
}
h5 {
font: normal normal 600 23px var(--main-font-family) !important;
}
.h1-subHeader {
font: normal normal normal 18px var(--main-font-family);
}
.h2-subHeader-blue {
font: normal normal 600 18px var(--main-font-family);
}
}
p.x-large-text {
/*color: var(--black);*/
font: normal normal normal 27px/34px var(--main-font-family);
letter-spacing: 0px;
opacity: 1;
}
p.big-text {
/*color: var(--black);*/
/*text-align: left;*/
font: normal normal normal 22px/29px var(--main-font-family);
letter-spacing: 0px;
opacity: 1;
}
p.big-text-header {
/*color: var(--black);*/
/*text-align: left;*/
font: normal normal normal 27px/41px var(--main-font-family);
letter-spacing: 0px;
opacity: 1;
}
p.regular-text {
/*color: var(--black);*/
/*text-align: left;*/
font: normal normal normal 16px/24px var(--main-font-family);
letter-spacing: 0px;
opacity: 1;
}
dt {
color: var(--black);
/*text-align: left;*/
font: normal normal bold 16px/24px var(--main-font-family);
letter-spacing: 0;
opacity: 1;
}
dd {
color: var(--black);
/*text-align: left;*/
font: normal normal normal 14px/22px Aileron;
letter-spacing: 0.14px;
opacity: 1;
}
.uk-text-primary {
color: var(--primary-color) !important;
}
.line-clamp {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* ========================================================================
Divider
========================================================================== */
hr {
border: 1px solid var(--default-element-bg);
}
.browse-dropdown-menu hr {
border: 2px solid var(--default-element-bg);
}
/* ========================================================================
Links
========================================================================== */
.eosc-link.uk-link, a.eosc-link {
color: var(--eosc-blue);
}
a {
color: var(--intelcomp-light-color);
text-decoration: none;
}
a:hover {
color: var(--black);
text-decoration: none;
}
a.footerLink:hover {
color: #fff;
}
/* ========================================================================
Buttons
========================================================================== */
.uk-button {
/*font: normal normal bold 12px/15px var(--main-font-family);*/
/*letter-spacing: 0px;*/
font-size: 14px;
}
.uk-card-media {
border-radius: 6px;
}
.uk-button-text {
text-transform: uppercase;
color: var(--catalogue-light-purple);
font: normal normal normal 16px/92px var(--main-font-family);
letter-spacing: -0.4px;
}
.uk-button-text::before {
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2220%22%20height%3D%2211%22%20viewBox%3D%220%200%2020%2011%22%3E%0A%20%20%20%20%3Cpolyline%20fill%3D%22none%22%20stroke%3D%22%23AD20E7%22%20stroke-width%3D%221.2%22%20points%3D%2213%201%2018%205.5%2013%2010%20%22%2F%3E%0A%20%20%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23AD20E7%22%20stroke-width%3D%221.2%22%20x1%3D%220%22%20y1%3D%225.5%22%20x2%3D%2218.4%22%20y2%3D%225.5%22%2F%3E%0A%3C%2Fsvg%3E%0A");
}
.uk-button-text:hover {
color: var(--openaire-light-blue);
}
.uk-button-text:focus::before, .uk-button-text:hover::before {
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2220%22%20height%3D%2211%22%20viewBox%3D%220%200%2020%2011%22%3E%0A%20%20%20%20%3Cpolyline%20fill%3D%22none%22%20stroke%3D%22%233086ED%22%20stroke-width%3D%221.2%22%20points%3D%2213%201%2018%205.5%2013%2010%20%22%2F%3E%0A%20%20%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%233086ED%22%20stroke-width%3D%221.2%22%20x1%3D%220%22%20y1%3D%225.5%22%20x2%3D%2218.4%22%20y2%3D%225.5%22%2F%3E%0A%3C%2Fsvg%3E%0A");
}
.uk-button-primary {
background-color: var(--intelcomp-light-color);
/*font: normal normal bold 12px/15px var(--main-font-family);*/
border-radius: 60px;
opacity: 1;
text-transform: uppercase;
border: none;
}
.uk-button-primary:hover {
background-color: var(--intelcomp-dark-color);
}
.uk-card-primary.uk-card-body .uk-button-primary, .uk-card-primary > :not([class*="uk-card-media"]) .uk-button-primary {
color: var(--catalogue-light-purple);
}
.uk-card-primary.uk-card-body .uk-button-primary:hover, .uk-card-primary > :not([class*="uk-card-media"]) .uk-button-primary:hover {
background-color: #fff;
color: var(--grey);
}
.uk-button-default {
text-transform: uppercase;
color: var(--catalogue-light-purple);
}
.uk-button-default:hover {
text-transform: uppercase;
color: var(--grey);
}
.uk-button-secondary {
text-transform: uppercase;
border: 1px solid var(--catalogue-light-purple);
color: var(--catalogue-light-purple);
}
.uk-button-secondary:hover {
background: transparent linear-gradient(254deg, var(--openaire-light-blue) 0%, var(--catalogue-light-purple) 100%) 0 0 no-repeat padding-box;
}
a.uk-button {
line-height: 50px;
}
a.uk-icon-button {
text-decoration: none;
}
.uk-button-blue {
background: var(--openaire-light-blue) 0 0 no-repeat padding-box;
font: normal normal bold 12px/15px var(--main-font-family);
border-radius: 60px;
opacity: 1;
text-transform: uppercase;
padding: 12px 30px;
color: #fff;
}
/* ========================================================================
Menus
========================================================================== */
.uk-navbar-dropbar {
background-color: #fff;
color: var(--dark-grey);
}
.navbar .nav > li > .dropdown-menu, .uk-navbar-dropdown {
padding: 20px 0;
color: var(--dark-grey);
font: normal normal normal 16px/24px Aileron;
letter-spacing: 0px;
}
.default-menu-item {
font: normal normal normal 14px/22px var(--main-font-family) !important;
text-transform: capitalize !important;
color: var(--black) !important;
text-align: left !important;
letter-spacing: 0.14px !important;
opacity: 1 !important;
}
.browse-dropdown-menu .services a {
color: var(--black) !important;
text-decoration: none;
}
.help-section a {
color: var(--catalogue-light-purple) !important;
text-decoration: none;
}
.help-section a:hover {
color: var(--openaire-light-blue) !important;
}
/*.service-menu {*/
/*margin-top: -10px;*/
/*}*/
.service-menu .uk-navbar-container {
background-color: var(--catalogue-dark-purple);
color: #fff;
}
.service-menu > .uk-active {
background-color: #fff;
color: #fff;
}
.service-menu-item {
font: normal normal normal 14px/22px var(--main-font-family) !important;
text-transform: capitalize !important;
color: #fff !important;
text-align: left !important;
letter-spacing: 0.14px !important;
opacity: 1 !important;
}
.service-menu > .uk-active .service-menu-item {
color: var(--black) !important;
}
.uk-active > .service-menu-item {
font: normal normal 600 14px/22px var(--main-font-family) !important;
color: var(--catalogue-light-purple) !important;
text-decoration-line: underline !important;
text-underline-offset: 5px;
text-decoration-thickness: 1.5px;
}
a.service-menu-item:hover {
color: #fff !important;
}
.service-menu > .uk-active .uk-active > .service-menu-item {
color: var(--catalogue-light-purple) !important;
}
.service-menu > :not(.uk-active) .uk-navbar-left {
display: none;
}
.uk-navbar-nav > li.uk-active > a::before, .uk-navbar-nav > li:hover > a::before {
background-color: transparent;
}
.uk-navbar-nav > li > a::before {
background-image: none;
}
@media only screen and (max-width: 960px) {
.uk-navbar-container:not(.uk-navbar-transparent) {
background: #fff;
opacity: 1;
}
.uk-navbar-toggle, .uk-navbar-toggle:focus {
color: var(--grey-900);
}
.help-section {
font-size: 20px;
}
.service-tabs.uk-tab {
flex-wrap: nowrap;
overflow-x: auto;
background: var(--catalogue-dark-purple);
padding-bottom: 15px;
padding-top: 10px;
padding-left: 20px;
margin-bottom: 0px;
}
.service-tabs.uk-tab > .uk-active > a {
border: none;
}
.service-tabs.uk-tab > .uk-active > a {
color: var(--catalogue-light-purple) !important;
}
.service-tabs.uk-tab > * > a {
color: #fff !important;
}
.service-tabs.uk-tab > li:not(.uk-active) > a {
text-decoration: none;
}
#tm-mobile {
overflow-y: hidden;
overscroll-behavior: contain;
//height: 90vh;
}
.tm-mobile-background {
z-index: 3;
display: none;
padding-top: 100px;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0,0.4);
}
}
/* ========================================================================
Cards
========================================================================== */
.uk-card .el-meta {
font-weight: normal !important;
}
.uk-card-default {
background: var(--light-grey) 0 0 no-repeat padding-box;
/*box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);*/
border-radius: 6px;
opacity: 1;
color: var(--black);
font: normal normal normal 16px/22px var(--main-font-family);
letter-spacing: 0.14px;
}
.uk-card-default .uk-card-title {
color: var(--black);
}
.uk-card-primary {
background: transparent linear-gradient(213deg, var(--openaire-light-blue) 0%, var(--catalogue-light-purple) 100%) 0% 0% no-repeat padding-box;
}
.uk-card-default.uk-card-hover:hover {
background: var(--light-grey) 0 0 no-repeat padding-box;
}
/*.card-icon-no-button {*/
/**/
/*}*/
/*.insight-info-card {*/
/*background: var(--light-grey) 0 0 no-repeat padding-box;*/
/*border-radius: 6px;*/
/*opacity: 1;*/
/*}*/
/* ========================================================================
Pricing
========================================================================== */
/* ========================================================================
Sliders
========================================================================== */
.uk-slideshow-items > .uk-active {
display: flex;
}
.uk-dotnav > * > * {
width: 16px;
height: 16px;
background-color: var(--intelcomp-dark-color) !important;
opacity: 0.4;
border: none !important;
}
.uk-dotnav > .uk-active > * {
background-color: var(--intelcomp-dark-color) !important;
opacity: 1;
width: 30px;
border-radius: 45%;
}
.slider-image {
}
.slider-text {
position: relative;
/*left: -70px;*/
}
.slider-bold-background-header {
text-align: left;
font: normal normal bold 229px/286px Bitter;
letter-spacing: 0px;
color: #211F7E;
opacity: 0.03;
position: absolute;
top: -80px;
left: -80px;
white-space: nowrap;
overflow: clip;
z-index: -10;
}
.slider-header {
color: var(--black);
/*text-align: left;*/
font: normal normal normal 45px/56px var(--secondary-font-family);
letter-spacing: 0px;
opacity: 1;
}
.slider-description {
color: var(--grey);
/*text-align: left;*/
font: normal normal normal 16px/24px var(--main-font-family);
letter-spacing: 0px;
opacity: 1;
}
/* ========================================================================
Component: Footer
========================================================================== */
.footerSection {
text-align: left;
font: normal normal 300 12px/20px var(--main-font-family);
letter-spacing: 0px;
opacity: 1;
}
.footerLink {
font: normal normal normal 16px/21px var(--main-font-family);
text-decoration: none;
}
.newsletter-link {
font: normal normal 600 19px/26px Open Sans;
}
/* ========================================================================
Forms
========================================================================== */
.uk-tab-left > * > a {
text-decoration: none;
}
.uk-input:not([class*="menuSearch"]) {
background-color: #fff;
//border: 1px solid var(--default-element-bg);
border-radius: 4px;
box-shadow: none;
}
.ng-select {
//background-color: #fff;
//border: 1px solid var(--default-element-bg);
height: 40px !important;
}
.ng-select .ng-select-container {
height: 40px !important;
}
/* ========================================================================
Pagination
========================================================================== */
.uk-pagination > * > * {
box-shadow: none;
}
.uk-pagination > li.uk-active > a:hover {
color: #fff;
}
/* ========================================================================
Search
========================================================================== */
.refineOption > input {
margin-right: 5px !important;
}
input[type="checkbox"] {
background: #FFFFFF 0% 0% no-repeat padding-box;
box-shadow: inset 0px 1px 3px #00000026 !important;
border: 0.5px solid #D4D4D5;
border-radius: 4px !important;
}
.menuSearch {
/*box-shadow: inset -10px -10px 13px #FFFFFFE6;*/
border-radius: 54px;
//width: 400px;
background: #fff;
padding: 20px 30px;
}
.menuSearchFields {
height: 48px !important;
background: #f7f7f7;
width: 200px;
}
a.serviceDetails {
text-decoration: none;
}
/*.serviceDetails .portfolioSection {*/
/*width: 35px;*/
/*background: #ececec 0% 0% no-repeat padding-box;*/
/*}*/
/*.serviceDetails .portfolioSection span {*/
/*transform: rotate(-90deg);*/
/*position: absolute;*/
/*bottom: 0;*/
/*left: 0;*/
/*margin-left: -30px;*/
/*@include transform(rotate(270deg));*/
/*@include transform-origin(0 0);*/
/*}*/
.service-details-card-content {
display: block;
position: relative;
margin: 40px 0;
}
.service-details-card-content .portfolioSection {
/*font: bold 12px Sans-Serif;*/
/*letter-spacing: 2px;*/
/*text-transform: uppercase;*/
background: #ececec;
/*color: #fff;*/
color: var(--grey-700);
padding: 5px 10px;
margin: 0 0 10px 0;
line-height: 24px;
}
.serviceDetails .service-details-card-content {
border-left: 34px solid #ececec;
border-radius: 6px;
/*padding-left: 10px;*/
}
.serviceDetails .service-details-card-content .portfolioSection {
/* Abs positioning makes it not take up vert space */
position: absolute;
bottom: 0;
left: -34px;
/* Border is the new background */
background: none;
/* Rotate from top left corner (not default) */
transform-origin: 0 0;
transform: rotate(-90deg);
}
.serviceDetails .field-label {
color: var(--grey);
}
.serviceDetails .field-value {
font-weight: 600;
}
.serviceDetails .service-image {
border-radius: 6px;
position: initial !important;
}
.serviceDetails .serviceDescription,
.serviceDetails .service-users,
.serviceDetails .service-pricing,
.service-details-card-content .portfolioSection {
font-size: 16px;
}
@media only screen and (max-width: 960px) {
.serviceDetails .service-details-card-content {
border-left: none;
//border-bottom: 34px solid #ececec;
}
.serviceDetails .service-details-card-content .portfolioSection {
/*background-color: #ececec;*/
transform: none;
left: 21px;
bottom: -45px;
}
}
#offcanvas-filters .uk-offcanvas-bar {
width: 100%;
background-color: #F9F9F9;
}
#offcanvas-filters .uk-offcanvas-bar .header {
background-color: #fff;
border-bottom: 1px solid #ececec;
}
#offcanvas-filters .uk-offcanvas-close {
position: initial;
}
.material-icons {
/*width: 24px;*/
/*height: 24px;*/
/*vertical-align: middle;*/
//color: #6b6b6b;
color: #ddd;
}
.material-icons.icons-secondary {
color: var(--intelcomp-dark-color);
}
.material-icons.md-10 { font-size: 10px; }
.material-icons.md-18 { font-size: 18px; }
.material-icons.md-24 { font-size: 24px; }
.material-icons.md-36 { font-size: 36px; }
.material-icons.md-48 { font-size: 48px; }

View File

@ -0,0 +1,8 @@
@mixin hook-navbar() {
// new rule
.uk-navbar-nav > li > a {
text-transform: none;
color: var(--black);
}
}

View File

@ -0,0 +1,270 @@
/* ========================================================================
Component: Nav
========================================================================== */
/*
* Reset
*/
.uk-nav,
.uk-nav ul {
margin: 0;
padding: 0;
list-style: none;
}
/*
* 1. Center content vertically, e.g. an icon
* 2. Imitate white space gap when using flexbox
* 3. Reset link
* 4. Space is allocated solely based on content dimensions: 0 0 auto
*/
.uk-nav li > a {
/* 1 */
display: flex;
align-items: center;
/* 2 */
-moz-column-gap: 0.25em;
column-gap: 0.25em;
/* 3*/
text-decoration: none;
}
/* 4 */
.uk-nav li > a > * {
flex: none;
}
/*
* Items
* Must target `a` elements to exclude other elements (e.g. lists)
*/
.uk-nav > li > a {
padding: 5px 30px;
}
/* Sublists
========================================================================== */
/*
* Level 2
* `ul` needed for higher specificity to override padding
*/
ul.uk-nav-sub {
padding: 5px 0 5px 45px;
}
/*
* Level 3 and deeper
*/
.uk-nav-sub ul {
padding-left: 15px;
}
/*
* Items
*/
.uk-nav-sub a {
padding: 2px 0;
}
/* Parent icon modifier
========================================================================== */
.uk-nav-parent-icon > .uk-parent > a::after {
content: "";
width: 24px;
height: 24px;
margin-left: auto;
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2214%22%20height%3D%2214%22%20viewBox%3D%220%200%2014%2014%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%3Cpolyline%20fill%3D%22none%22%20stroke%3D%22%232C2C2C%22%20stroke-width%3D%221.1%22%20points%3D%2210%201%204%207%2010%2013%22%20%2F%3E%0A%3C%2Fsvg%3E");
background-repeat: no-repeat;
background-position: 50% 50%;
background-image: none !important;
font-family: "Material Icons";
font-weight: 400 !important;
font-size: 1.5em;
width: auto;
height: auto;
content: "\e5c5";
}
.uk-nav-parent-icon > .uk-parent.uk-open > a::after {
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2214%22%20height%3D%2214%22%20viewBox%3D%220%200%2014%2014%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%3Cpolyline%20fill%3D%22none%22%20stroke%3D%22%232C2C2C%22%20stroke-width%3D%221.1%22%20points%3D%221%204%207%2010%2013%204%22%20%2F%3E%0A%3C%2Fsvg%3E");
}
/* Inverse */
.sidebar_main_swipe {
/* No sidebar */
/* Mini Sidebar*/
}
.sidebar_main_swipe #sidebar_main #sidebar_content {
width: var(--sidebar-width);
position: fixed;
top: 0;
bottom: 0;
left: 0;
/*padding-top: 65px;*/
/*padding-top: var(--header-height);*/
z-index: 60;
background: #FFFFFF;
/*border-right: 1px solid #EAEAEA;*/
transition: 0.5s;
transition-property: width;
/*overflow-y: auto;*/
}
.sidebar_main_swipe #sidebar_main .menu_section {
margin-left: 10px;
position: relative;
font-size: 14px;
}
.sidebar_main_swipe #sidebar_main .menu_section > ul > li > a {
position: relative;
padding: 10px 20px;
line-height: 30px;
}
.sidebar_main_swipe #sidebar_main .menu_section > ul > li > a:not(.uk-flex) {
display: block;
}
.sidebar_main_swipe #sidebar_main .menu_section > ul > li > a .menu-icon {
display: block;
padding: 6px;
border-radius: 6px;
background-color: transparent;
}
.sidebar_main_swipe #sidebar_main .menu_section > ul > li.uk-parent > a {
padding: 10px 40px 10px 20px;
}
.sidebar_main_swipe #sidebar_main .menu_section > ul > li.uk-parent > a:not(.uk-flex)::after {
position: absolute;
right: 10px;
top: 50%;
transform: translate(-50%, -50%);
line-height: 20px;
}
.sidebar_main_swipe #sidebar_main .menu_section > ul > li.uk-parent .uk-nav-sub {
margin-right: 10px;
padding-left: 57px;
position: relative;
}
.sidebar_main_swipe #sidebar_main .menu_section > ul > li.uk-parent .uk-nav-sub a {
border-radius: 4px;
padding: 7px 15px;
justify-content: left;
}
.sidebar_main_swipe #sidebar_main .menu_section > ul > li.uk-parent .uk-nav-sub > li.uk-active > a {
background-color: #F3F3F3;
color: var(--eosc-observatory-primary-color) !important;
justify-content: left;
}
.sidebar_main_swipe #sidebar_main .menu_section > ul > li.uk-parent .uk-nav-sub:before {
content: "";
left: 32px;
position: absolute;
height: 95%;
/*border-left: 2px solid rgba(33, 31, 126, 0.3);*/
border-left: 2px solid var(--eosc-observatory-secondary-color);
opacity: 0.3;
}
.sidebar_main_swipe #sidebar_main .menu_section > ul > li.uk-active > a .menu-icon {
background-color: #211F7E;
background-image: linear-gradient(51deg, #4687E6 0%, #1F2379 100%);
color: #FFFFFF;
}
.sidebar_main_swipe #page_content,
.sidebar_main_swipe openaire-user > user > div,
.sidebar_main_swipe openaire-error > div,
.sidebar_main_swipe #page_content .message,
.sidebar_main_swipe bottom > div {
/*padding-left: 280px;*/
transition: 0.5s;
}
.sidebar_main_swipe #page_content {
/* for firefox */
}
.sidebar_main_swipe #page_content.uk-blur-background,
.sidebar_main_swipe #page_content .uk-blur-background {
background: rgba(249, 249, 249, 0.99);
}
@supports ((-webkit-backdrop-filter: none) or (backdrop-filter: none)) {
.sidebar_main_swipe #page_content.uk-blur-background,
.sidebar_main_swipe #page_content .uk-blur-background {
-webkit-backdrop-filter: saturate(180%) blur(20px);
backdrop-filter: saturate(180%) blur(20px);
background: rgba(249, 249, 249, 0.8);
}
}
@-moz-document url-prefix() {
.sidebar_main_swipe #page_content.uk-blur-background,
.sidebar_main_swipe #page_content .uk-blur-background {
background: rgba(249, 249, 249, 0.99);
}
}
.sidebar_main_swipe #page_content .message {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
position: absolute;
padding-left: calc(var(--sidebar-width) - 100px);
padding-right: 20px;
text-align: center;
}
.sidebar_main_swipe #page_content #page_content_header.uk-sticky,
.sidebar_main_swipe #page_content #page_content_actions.uk-sticky {
z-index: 979;
}
.sidebar_main_swipe #page_content #page_content_header.uk-sticky.uk-active,
.sidebar_main_swipe #page_content #page_content_actions.uk-sticky.uk-active {
border-bottom: 1px solid #EAEAEA;
}
.sidebar_main_swipe #page_content #page_content_header.uk-sticky.uk-active .uk-tab,
.sidebar_main_swipe #page_content #page_content_actions.uk-sticky.uk-active .uk-tab {
margin-bottom: 0;
}
.sidebar_main_swipe #page_content #page_content_header.uk-sticky.uk-active *:last-child.uk-tab:before,
.sidebar_main_swipe #page_content #page_content_actions.uk-sticky.uk-active *:last-child.uk-tab:before {
content: none;
}
.sidebar_main_swipe #page_content #page_content_header {
overflow-x: hidden;
}
.sidebar_main_swipe #page_content #page_content_header .info {
height: 45px;
overflow: hidden;
}
.sidebar_main_swipe #page_content #page_content_header .info img {
max-height: 45px;
max-width: 180px;
}
.sidebar_main_swipe #page_content,
.sidebar_main_swipe openaire-user > user > div,
.sidebar_main_swipe openaire-error > div {
min-height: calc(100vh - 65px);
min-height: calc(100vh - var(--header-height));
/*background-color: #F9F9F9;*/
position: relative;
z-index: 70;
}
.sidebar_main_swipe:not(.sidebar_main_active):not(.sidebar_mini) #page_content,
.sidebar_main_swipe:not(.sidebar_main_active):not(.sidebar_mini) openaire-user > user > div,
.sidebar_main_swipe:not(.sidebar_main_active):not(.sidebar_mini) openaire-error > div,
.sidebar_main_swipe:not(.sidebar_main_active):not(.sidebar_mini) #page_content .message,
.sidebar_main_swipe:not(.sidebar_main_active):not(.sidebar_mini) bottom > div {
padding-left: 0;
}
.sidebar_main_swipe:not(.sidebar_main_active):not(.sidebar_mini) #sidebar_main #sidebar_content {
display: none;
width: 0;
}
.sidebar_main_swipe.sidebar_mini #sidebar_main #sidebar_content {
width: 125px;
}
.sidebar_main_swipe.sidebar_mini #page_content,
.sidebar_main_swipe.sidebar_mini openaire-user > user > div,
.sidebar_main_swipe.sidebar_mini openaire-error > div,
.sidebar_main_swipe.sidebar_mini #page_content .message,
.sidebar_main_swipe.sidebar_mini bottom > div {
padding-left: 125px;
}
@media (max-width: 480px) {
.sidebar_main_swipe #sidebar_main #sidebar_content {
width: 100px !important;
}
.sidebar_main_swipe #page_content,
.sidebar_main_swipe openaire-user > user > div,
.sidebar_main_swipe openaire-error > div,
.sidebar_main_swipe #page_content .message,
.sidebar_main_swipe bottom > div {
padding-left: 100px !important;
}
.sidebar_main_swipe #page_content .message {
padding-right: 0;
}
}

View File

@ -0,0 +1,148 @@
.uk-navbar-toggle {
color: #2c2c2c !important;
padding: 0 25px !important;
}
.user-info {
padding: 0 15px !important;
}
a.navbar-user-icon {
padding: 0 25px !important;
color: #2c2c2c !important;
}
a.user-info text {
color: #fff !important;
}
/**************** OFF-Canvas menu ****************/
.uk-navbar-toggle .material-icons {
color: #2c2c2c !important;
}
.uk-offcanvas-close {
left: 5px;
}
.uk-open > .uk-offcanvas-bar {
left: 0;
}
.uk-offcanvas-bar {
width: 100vw;
}
.custom-offcanvas-close {
position: relative;
right: 0;
top: 0;
}
/*.uk-offcanvas-bar-light {*/
/* text-transform: uppercase;*/
/*}*/
.uk-offcanvas-bar-light {
position: absolute;
top: 0;
bottom: 0;
left: 0;
/*left: -270px;*/
box-sizing: border-box;
width: 100vw;
/*padding: 20px 20px;*/
background: #fff;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.uk-nav-sub a {
padding: 2px 15px;
}
.uk-offcanvas-bar-light .uk-nav-default > li > a, .uk-offcanvas-bar-light .uk-nav-default .uk-nav-sub a {
color: #333;
}
.uk-nav-default .uk-nav-sub a:hover {
color: var(--intelcomp-light-color);
}
.uk-offcanvas-bar-light .uk-nav-default > li.uk-active > a, .uk-offcanvas-bar-light .uk-nav-default > li > a:hover,
.uk-offcanvas-bar-light .uk-nav-default > li > a.uk-active, .uk-offcanvas-bar-light .uk-nav-default > li > a:focus,
.uk-offcanvas-bar-light .uk-nav-default > li > a:active {
color: var(--intelcomp-light-color);
}
.uk-offcanvas-bar-animation {
transition: left 0.3s ease-out;
}
@media (min-width: 960px) {
.uk-offcanvas-bar-light {
left: -350px;
width: 350px;
width: 100vw;
padding: 40px 40px;
}
}
.uk-offcanvas-flip .uk-offcanvas-bar-light {
left: auto;
right: -270px;
}
.uk-offcanvas-flip .uk-offcanvas-bar-animation {
transition-property: right;
}
.uk-offcanvas-flip .uk-open > .uk-offcanvas-bar-light {
left: auto;
right: 0;
}
@media (min-width: 960px) {
.uk-offcanvas-flip .uk-offcanvas-bar-light {
right: -350px;
}
}
.uk-offcanvas-flip .uk-offcanvas-reveal .uk-offcanvas-bar-light {
left: auto;
right: 0;
}
.uk-offcanvas-reveal .uk-offcanvas-bar-light {
left: 0;
}
.uk-open > .uk-offcanvas-bar-light {
left: 0;
}
.uk-close::after {
opacity: 0 !important;
color: #fff;
content: '';
font-family: "Material Icons";
}
.uk-nav > li > a {
padding: 5px 30px;
}
.uk-nav-primary > li > a {
font-size: 20px;
line-height: 24px;
font-weight: 600;
color: var(--black) !important;
}
.uk-nav-primary > li.uk-active > a {
color: var(--intelcomp-light-color) !important;
}
/*************************************/

View File

@ -0,0 +1,206 @@
/* ========================================================================
Sidebar main
========================================================================== */
#sidebar_main {
/*overflow: auto;*/
position: fixed;
top: var(--header-height) !important;
box-shadow: 0 0 16px 2px #00000029;
background: #fff;
/*width: 280px;*/
width: var(--sidebar-width);
transform: translate3d(var(--sidebar-width-invert),0,0);
-webkit-transform: translate3d(var(--sidebar-width-invert),0,0);
-webkit-transition: all 280ms cubic-bezier(.4,0,.2,1);
transition: all 280ms cubic-bezier(.4,0,.2,1);
height: 100%;
z-index: 800;
}
.sidebar_main_active #sidebar_main {
-webkit-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);
}
/* ========================================================================
Menu section
========================================================================== */
#sidebar_main .menu_section {
overflow: visible;
margin-bottom: 15px;
padding-bottom: 20px;
flex: 0;
padding-top: 35px;
}
.sidebar_main_active #sidebar_main .menu_section {
overflow: auto;
flex: 1;
margin-bottom: 15px;
}
.dashboard #sidebar_main .menu_section .sidebar_heading {
font-weight: 500;
font-size: 14px;
letter-spacing: 0px;
color: #4D4D4D;
text-transform: uppercase;
opacity: 1;
padding: 8px 25px;
/*margin-top: 20px;*/
}
#sidebar_main .menu_section.sidebar-footer {
border-bottom: none;
margin-bottom: 100px;
width: 100%;
position: absolute !important;
bottom: 0;
}
#sidebar_main .menu_section.border_top {
border-top: 1px solid #DEDEDE;
}
#sidebar_main .menu_section ul {
margin: 0;
padding: 0;
list-style: none;
}
#sidebar_main .menu_section ul > li {
padding: 0;
margin: 0;
list-style: none;
}
#sidebar_main .menu_section > ul > li > a {
font-size: 16px;
}
#sidebar_main .menu_section > ul > li > a:hover {
/*background-color: #ececec;*/
border-radius: 6px;
}
#sidebar_main .menu_section > ul > li.current_section {
background-color: transparent;
}
#sidebar_main .menu_section > ul > li.current_section a {
/*background-color: rgba(255, 205, 0, 0.5);*/
/*background-color: #ececec;*/
border-radius: 6px;
}
#sidebar_main .menu_section > ul > li.current_section > a:hover {
/*background-color: #ececec;*/
/*background-color: rgba(255, 205, 0, 0.5);*/
}
#sidebar_main .menu_section > ul > li.current_section a {
color: #1A1A1A !important;
font-weight: bold !important;
}
#sidebar_main .menu_section .material-icons {
padding: 3px;
background-color: transparent;
border-radius: 6px;
color: var(--grey-700);
}
#sidebar_main .menu_section .current_section .material-icons {
padding: 3px;
/*background: transparent linear-gradient(254deg, var(--openaire-light-blue) 0%, var(--catalogue-light-purple) 100%) 0 0 no-repeat padding-box;*/
background-color: var(--eosc-observatory-secondary-color);
border-radius: 6px;
color: var(--white);
}
/*.material-icons-small {*/
/*width: 12px !important;*/
/*height: 12px !important;*/
/*!*vertical-align: middle;*!*/
/*color: #6b6b6b;*/
/*}*/
#sidebar_main .menu_section > ul > li > a {
font-weight: 400;
font-size: var(--sidebar-font-size);
color: #212121;
padding: 8px 25px;
display: block;
overflow: hidden;
position: relative;
}
/* ========================================================================
Sidebar toggle
========================================================================== */
#sidebar_main #sidebar_toggle {
position: fixed;
z-index: 9800;
top: 50%;
left: 280px;
left: var(--sidebar-width);
width: 35px;
height: 35px;
transition: left 0.25s linear;
transition: left var(--dashboard-transition-delay) linear;
-webkit-transition: left 0.25s linear;
-webkit-transition: left var(--dashboard-transition-delay) linear;
-moz-transition: left 0.25s linear;
-moz-transition: left var(--dashboard-transition-delay) linear;
-o-transition: left 0.25s linear;
-o-transition: left var(--dashboard-transition-delay) linear;
transform: translate(-50%, -50%);
box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.1);
border-radius: 500px;
border: 1px solid #EAEAEA;
background: #FFFFFF;
color: #2C2C2C;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
#sidebar_main #sidebar_toggle.closed {
left: var(--toggle-sidebar-closed);
}
#sidebar_main #sidebar_toggle::before {
content: '\e5cb';
font-family: 'Material Icons';
font-size: 25px;
transition: transform 0.25s linear;
transition: transform var(--dashboard-transition-delay) linear;
-webkit-transition: transform 0.25s linear;
-webkit-transition: transform var(--dashboard-transition-delay) linear;
-moz-transition: transform 0.25s linear;
-moz-transition: transform var(--dashboard-transition-delay) linear;
-o-transition: transform 0.25s linear;
-o-transition: transform var(--dashboard-transition-delay) linear;
}
#sidebar_main #sidebar_toggle.closed::before {
transform: rotate(180deg);
}
#sidebar_main #sidebar_toggle:hover {
background-color: var(--eosc-observatory-secondary-color) !important;
color: var(--white);
/*border-color: @dashboard-sidebar-toggle-border-hover;*/
}
/* ========================================================================
Page content
========================================================================== */
.sidebar_main_active #page_content {
margin-left: var(--sidebar-width);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@ -0,0 +1 @@
<svg id="Capa_1" data-name="Capa 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 763.3 145.02"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:#ff006e;}</style></defs><title>intelcomp-blanco</title><path class="cls-1" d="M173.36,104.07H154.85V45.12h18.51Z"/><path class="cls-1" d="M187.76,45.12h18.5v9.59c4.57-6.85,11-10.51,18.63-10.51,11.42,0,19.54,8.34,19.54,20.11v39.76H225.92V69.68c0-6.63-3.89-11-9.83-11a11.93,11.93,0,0,0-9.83,4.91v40.45h-18.5Z"/><path class="cls-1" d="M264.42,59.4H253V45.12h11.43V28.78L282.93,25V45.12H298.7V59.4H282.93V82.25c0,5.25,2.06,7.08,7.77,7.08a24.79,24.79,0,0,0,7.54-1.26v15a51.42,51.42,0,0,1-12.68,1.83c-13.94,0-21.14-6.4-21.14-19Z"/><path class="cls-1" d="M337.43,105.21c-17.37,0-31.08-13.36-31.08-30.5,0-17.37,12.8-30.62,29.71-30.62s29,12.91,29,31.3v4H324.52c1.71,6.63,7.08,11.08,13.82,11.08,4.91,0,9-1.71,11.66-4.91l12.22,10.17C354.57,102.47,347.37,105.21,337.43,105.21ZM324.52,68.88h23.42c-1.49-6.4-6.06-10.4-12-10.4S326,62.37,324.52,68.88Z"/><path class="cls-1" d="M395.13,104.07H376.62V22.38l18.51-2.86Z"/><path class="cls-1" d="M450.42,83.39l11,10.85a31,31,0,0,1-24,11,30,30,0,0,1-30.51-30.5A30,30,0,0,1,437.4,44.2,31.9,31.9,0,0,1,462,55.06L450.65,66.37c-3.77-4.46-7.54-6.4-12.57-6.4-7.31,0-12.79,6.28-12.79,14.74s5.6,14.51,13.25,14.51A14.24,14.24,0,0,0,450.42,83.39Z"/><path class="cls-1" d="M497.5,44.2c17.59,0,30.84,13.14,30.84,30.51s-13.36,30.5-30.84,30.5S466.76,92,466.76,74.71,480,44.2,497.5,44.2Zm12.79,30.51c0-8.8-5.37-15.08-12.79-15.08s-12.69,6.28-12.69,15.08,5.26,14.85,12.69,14.85S510.29,83.39,510.29,74.71Z"/><path class="cls-1" d="M540.11,45.12h18.51v9.36C563,47.74,568.9,44.2,576.1,44.2a17.47,17.47,0,0,1,16.57,11c4.57-7.08,11.2-11,19.31-11,10.85,0,18.51,8.57,18.51,20.68v39.19H612V68.54c0-5.94-3.55-9.83-8.8-9.83-3.43,0-6.17,1.37-8.57,4.57v40.79H576.1V68.54c0-5.94-3.54-9.83-8.8-9.83-3.42,0-6.28,1.49-8.68,4.57v40.79H540.11Z"/><path class="cls-1" d="M644.42,45.12h18.29v8.22a21.76,21.76,0,0,1,17.48-8.57c14.51,0,26,13.37,26,29.94s-12.11,29.7-27.42,29.7a20.59,20.59,0,0,1-15.89-6.85v31.08H644.42Zm18.51,19.76V84.53A15.19,15.19,0,0,0,674,89.22c8.11,0,14.05-6.17,14.05-14.63S682,60.08,674,60.08A14.29,14.29,0,0,0,662.93,64.88Z"/><rect class="cls-2" x="57.07" y="16.39" width="19.82" height="19.84"/><rect class="cls-2" x="91.98" y="16.39" width="47.63" height="19.82"/><polygon class="cls-2" points="139.61 84.21 139.61 104.03 57.07 104.03 57.07 51.2 76.88 51.2 76.88 84.21 139.61 84.21"/><rect class="cls-2" x="76.83" y="51.2" width="0.05" height="19.99"/><path class="cls-1" d="M154.23,26.26a9.88,9.88,0,0,1,19.75,0,9.88,9.88,0,0,1-19.75,0Z"/></svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1 @@
<svg id="Capa_1" data-name="Capa 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 763.3 145.02"><defs><style>.cls-1{fill:#ff006e;}</style></defs><title>intelcomp</title><path d="M149.27,107.72H128.62V42h20.65Z"/><path d="M165.33,42H186v10.7c5.1-7.64,12.24-11.72,20.78-11.72,12.75,0,21.8,9.3,21.8,22.43v44.36H207.91V69.35c0-7.39-4.34-12.23-11-12.23a13.28,13.28,0,0,0-11,5.48v45.12H165.33Z"/><path d="M250.86,57.88H238.12V42h12.74V23.72l20.65-4.21V42H289.1V57.88H271.51V83.37c0,5.87,2.3,7.91,8.67,7.91a27.64,27.64,0,0,0,8.41-1.41v16.7a57.28,57.28,0,0,1-14.15,2c-15.55,0-23.58-7.14-23.58-21.16Z"/><path d="M332.31,109c-19.37,0-34.67-14.91-34.67-34,0-19.37,14.28-34.16,33.14-34.16s32.38,14.4,32.38,34.93v4.46H317.91c1.91,7.39,7.9,12.36,15.42,12.36,5.48,0,10.07-1.91,13-5.48L360,98.42C351.43,105.94,343.4,109,332.31,109Zm-14.4-40.53H344c-1.66-7.14-6.76-11.6-13.38-11.6S319.57,61.19,317.91,68.46Z"/><path d="M396.68,107.72H376V16.58l20.65-3.19Z"/><path d="M458.38,84.65l12.23,12.11A34.56,34.56,0,0,1,443.85,109c-19.25,0-34-14.78-34-34s14.79-34,34-34c10.83,0,20.77,4.33,27.4,12.11L458.63,65.66c-4.2-5-8.41-7.14-14-7.14-8.16,0-14.28,7-14.28,16.44s6.25,16.19,14.79,16.19A15.93,15.93,0,0,0,458.38,84.65Z"/><path d="M510.89,40.93c19.63,0,34.42,14.66,34.42,34s-14.91,34-34.42,34S476.6,94.21,476.6,75,491.39,40.93,510.89,40.93Zm14.28,34c0-9.81-6-16.82-14.28-16.82s-14.15,7-14.15,16.82,5.87,16.57,14.15,16.57S525.17,84.65,525.17,75Z"/><path d="M558.44,42h20.65V52.4c4.84-7.52,11.47-11.47,19.5-11.47a19.47,19.47,0,0,1,18.48,12.23c5.1-7.9,12.49-12.23,21.54-12.23,12.11,0,20.65,9.56,20.65,23.07v43.72H638.61V68.08c0-6.63-4-11-9.81-11-3.83,0-6.88,1.53-9.56,5.09v45.51H598.59V68.08c0-6.63-4-11-9.82-11-3.82,0-7,1.65-9.68,5.09v45.51H558.44Z"/><path d="M674.81,42h20.4v9.17a24.28,24.28,0,0,1,19.5-9.56c16.19,0,29.06,14.92,29.06,33.4s-13.51,33.14-30.59,33.14a22.91,22.91,0,0,1-17.72-7.65v34.68H674.81Zm20.65,22V85.92a16.92,16.92,0,0,0,12.37,5.23c9,0,15.68-6.88,15.68-16.32s-6.76-16.18-15.68-16.18A16,16,0,0,0,695.46,64Z"/><rect class="cls-1" x="19.53" y="9.9" width="22.11" height="22.13"/><rect class="cls-1" x="58.48" y="9.9" width="53.14" height="22.11"/><polygon class="cls-1" points="111.62 85.56 111.62 107.67 19.53 107.67 19.53 48.73 41.64 48.73 41.64 85.56 111.62 85.56"/><rect class="cls-1" x="41.58" y="48.73" width="0.06" height="22.3"/><path d="M127.93,20.91a11,11,0,0,1,22,0,11,11,0,0,1-22,0Z"/></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

View File

@ -0,0 +1,223 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>
This is a custom SVG font generated by IcoMoon.
<iconset grid="16"></iconset>
</metadata>
<defs>
<font id="IcoMoon" horiz-adv-x="512" >
<font-face units-per-em="512" ascent="480" descent="-32" />
<missing-glyph horiz-adv-x="512" />
<glyph class="hidden" unicode="&#xf000;" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" />
<glyph unicode="&#xe200;" d="M 133.002,341.661c 16.416,16.422, 43.001,16.422, 59.402,0.016l 3.913-3.934l 50.552,50.578l-3.937,3.94 c-28.812,28.85-69.257,38.939-106.21,30.261C 131.425,455.113, 103.178,479.984, 69.135,480C 31.31,480, 0.658,449.279, 0.65,411.421 c0-32.668, 22.795-60, 53.331-66.915c-11.569-38.725-2.121-82.417, 28.423-112.992l 113.913-113.95l 50.498,50.607L 132.91,282.114 C 116.569,298.475, 116.539,325.177, 133.002,341.661zM 511.356,411.421C 511.364,449.302, 480.697,480, 442.864,480c-34.617,0-63.239-25.722-67.841-59.119 c-38.537,11.332-81.892,1.748-112.32-28.704l-113.92-113.95l 50.551-50.586l 113.883,113.928c 16.47,16.483, 42.994,16.453, 59.342,0.092 c 16.4-16.415, 16.4-43.057-0.016-59.478l-3.897-3.918l 50.505-50.624l 3.929,3.964c 30.229,30.283, 39.839,73.378, 28.806,111.819 C 485.461,347.841, 511.356,376.606, 511.356,411.421zM 453.133,104.468c 9.051,37.229-0.988,78.162-30.054,107.25L 309.334,325.714l-50.551-50.561l 113.76-114.006 c 16.47-16.498, 16.432-43.048, 0.092-59.424c-16.401-16.407-43.002-16.407-59.418,0.015l-3.883,3.895l-50.497-50.623l 3.866-3.864 c 30.758-30.797, 74.809-40.219, 113.684-28.244C 382.703-8.439, 410.354-32, 443.516-32C 481.318-32, 512-1.325, 512,36.563 C 512,71.163, 486.41,99.791, 453.133,104.468zM 306.172,215.658L 192.404,101.662c-16.355-16.384-43.017-16.414-59.472,0.062c-16.409,16.452-16.416,43.049-0.022,59.485 l 3.904,3.887l-50.543,50.562l-3.867-3.856c-29.38-29.401-39.28-70.917-29.725-108.491C 22.48,96.181,0,68.994,0,36.563 C-0.008-1.31, 30.666-32, 68.491-32c 32.55,0.016, 59.794,22.709, 66.77,53.191c 37.351-9.276, 78.499,0.652, 107.672,29.878 l 113.745,113.98L 306.172,215.658z" />
<glyph unicode="&#xe005;" d="M0,160L 96,64L 256,224L 416,64L 512,160L 256.001,416 z" />
<glyph unicode="&#xe006;" d="M 192,480L 96,384L 256,224L 96,64L 192-32L 448,224 z" />
<glyph unicode="&#xe007;" d="M 512,288L 416,384L 256,224L 96,384L0,288L 256,32.001 z" />
<glyph unicode="&#xe008;" d="M 320-32L 416,64L 256,224L 416,384L 320,480L 64,224 z" />
<glyph unicode="&#xe003;" d="M 416,384L 320,480L 64,224L 320-32L 416,64L 256,224 zM0,480L0-32L 64-32L 64,224L 64,480 z" />
<glyph unicode="&#xe004;" d="M 96,64L 192-32L 448,224L 192,480L 96,384L 256,224 zM 512-32L 512,480L 448,480L 448,224L 448-32 z" />
<glyph unicode="&#xe009;" d="M 512,224C 512,82.615, 397.385-32, 256-32s -256,114.615, -256,256s 114.615,256, 256,256S 512,365.385, 512,224z M 48,224 c 0-114.875 93.125-208 208-208S 464,109.125, 464,224s -93.125,208, -208,208S 48,338.875, 48,224zM 278.627,374.628l 128-128.001c 12.497-12.496 12.497-32.757 0-45.254c -12.497-12.497 -32.758-12.497,-45.255,0L 288,274.745 L 288,96 c 0-17.673 -14.327-32 -32-32c-17.673,0, -32,14.327, -32,32l0,178.745 l -73.372-73.373c -12.497-12.497 -32.759-12.497,-45.256,0 C 99.124,207.621, 96,215.811, 96,224s 3.124,16.379, 9.372,22.627l 128,128.001C 245.869,387.124, 266.131,387.124, 278.627,374.628z" />
<glyph unicode="&#xe00a;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,16 c-114.875,0-208,93.125-208,208S 141.125,432, 256,432s 208-93.125, 208-208S 370.875,16, 256,16zM 406.628,246.627l-128.001,128c-12.496,12.497-32.757,12.497-45.254,0c-12.497-12.497-12.497-32.758,0-45.255L 306.745,256 L 128,256 c-17.673,0-32-14.327-32-32c0-17.673, 14.327-32, 32-32l 178.745,0 l-73.373-73.372c-12.497-12.497-12.497-32.759,0-45.256 C 239.621,67.124, 247.811,64, 256,64s 16.379,3.124, 22.627,9.372l 128.001,128C 419.124,213.869, 419.124,234.131, 406.628,246.627z" />
<glyph unicode="&#xe00b;" d="M 512,224C 512,365.385, 397.385,480, 256,480s -256-114.615, -256-256s 114.615-256, 256-256S 512,82.615, 512,224z M 48,224 c 0,114.875 93.125,208 208,208S 464,338.875, 464,224s -93.125-208, -208-208S 48,109.125, 48,224zM 278.627,73.372l 128,128.001c 12.497,12.496 12.497,32.757 0,45.254c -12.497,12.497 -32.758,12.497,-45.255,0L 288,173.255 L 288,352 c 0,17.673 -14.327,32 -32,32c-17.673,0, -32-14.327, -32-32l0-178.745 l -73.372,73.373c -12.497,12.497 -32.759,12.497,-45.256,0 C 99.124,240.379, 96,232.189, 96,224s 3.124-16.379, 9.372-22.627l 128-128.001C 245.869,60.876, 266.131,60.876, 278.627,73.372z" />
<glyph unicode="&#xe00c;" d="M 256,480C 397.385,480, 512,365.385, 512,224s -114.615-256, -256-256s -256,114.615, -256,256S 114.615,480, 256,480z M 256,16 c 114.875,0 208,93.125 208,208S 370.875,432, 256,432s -208-93.125, -208-208S 141.125,16, 256,16zM 105.372,246.627l 128.001,128c 12.496,12.497 32.757,12.497 45.254,0c 12.497-12.497 12.497-32.758,0-45.255L 205.255,256 L 384,256 c 17.673,0 32-14.327 32-32c0-17.673, -14.327-32, -32-32l-178.745,0 l 73.373-73.372c 12.497-12.497 12.497-32.759,0-45.256 C 272.379,67.124, 264.189,64, 256,64s -16.379,3.124, -22.627,9.372l -128.001,128C 92.876,213.869, 92.876,234.131, 105.372,246.627z" />
<glyph unicode="&#xe00f;" d="M 384,160L 256,288L 128,160 z" />
<glyph unicode="&#xe010;" d="M 192.001,96L 320.001,224L 192.001,352 z" />
<glyph unicode="&#xe011;" d="M 128,288L 256,160L 384,288 z" />
<glyph unicode="&#xe012;" d="M 320.001,352L 192.001,224L 320.001,95.999 z" />
<glyph unicode="&#xe00e;" d="M 384,256L 256,384L 128,256 zM 128,160L 256,32L 384,160 z" />
<glyph unicode="&#xe201;" d="M 160,0L 352,0L 352-32L 160-32zM 160,64L 352,64L 352,32L 160,32zM 160,128L 352,128L 352,96L 160,96zM 256,480L 480,256L 352,256L 352,160L 160,160L 160,256L 32,256 z" />
<glyph unicode="&#xe202;" d="M0,320L 32,320L 32,128L0,128zM 64,320L 96,320L 96,128L 64,128zM 128,320L 160,320L 160,128L 128,128zM 512,224L 288,448L 288,320L 192,320L 192,128L 288,128L 288,0 z" />
<glyph unicode="&#xe203;" d="M 160,480L 352,480L 352,448L 160,448zM 160,416L 352,416L 352,384L 160,384zM 160,352L 352,352L 352,320L 160,320zM 256-32L 480,192L 352,192L 352,288L 160,288L 160,192L 32,192 z" />
<glyph unicode="&#xe204;" d="M 480,320L 512,320L 512,128L 480,128zM 416,320L 448,320L 448,128L 416,128zM 352,320L 384,320L 384,128L 352,128zM0,224L 224,448L 224,320L 320,320L 320,128L 224,128L 224,0 z" />
<glyph unicode="&#x27;" d="M 288,355.814L 288,480 l 192-192L 288,96L 288,222.912 C 64.625,228.153, 74.206,71.016, 131.070-32 C-9.286,119.707, 20.52,362.785, 288,355.814z" />
<glyph unicode="&#x28;" d="M 380.931-32C 437.794,71.016, 447.375,228.153, 224,222.912L 224,96 L 32,288L 224,480l0-124.186 C 491.481,362.785, 521.285,119.707, 380.931-32z" />
<glyph unicode="&#xe205;" d="M 131.070,480C 74.206,376.984, 64.625,219.848, 288,225.088L 288,352 l 192-192L 288-32L 288,92.186 C 20.52,85.215-9.286,328.293, 131.070,480z" />
<glyph unicode="&#xe206;" d="M 224,92.186L 224-32 L 32,160l 192,192l0-126.912 C 447.375,219.848, 437.794,376.984, 380.931,480 C 521.286,328.293, 491.481,85.215, 224,92.186z" />
<glyph unicode="&#x6c;" d="M0,192c0-76.462, 33.524-145.092, 86.675-192l 42.333,48C 89.145,83.182, 64,134.652, 64,192c0,106.038, 85.965,192, 192,192 c 53.021,0, 101.019-21.493, 135.765-56.239L 320,256l 192,0 L 512,448 l-74.985-74.989C 390.688,419.34, 326.693,448, 256,448 C 114.615,448,0,333.385,0,192z" />
<glyph unicode="&#xe207;" d="M 256,448c-70.692,0-134.688-28.66-181.016-74.989L0,448l0-192 l 192,0 l-71.766,71.761C 154.982,362.507, 202.98,384, 256,384 c 106.034,0, 192-85.962, 192-192c0-57.348-25.146-108.818-65.009-144l 42.333-48C 478.475,46.908, 512,115.538, 512,192 C 512,333.385, 397.385,448, 256,448z" />
<glyph unicode="&#x7a;" d="M 512,224L 384,320L 384,256L 288,256L 288,352L 352,352L 256,480L 160,352L 224,352L 224,256L 128,256L 128,320L0,224L 128,128L 128,192L 224,192L 224,96L 160,96L 256-32L 352,96L 288,96L 288,192L 384,192L 384,128 z" />
<glyph unicode="&#x66;" d="M 512,480 L 512,272 L 432,352 L 336,256 L 288,304 L 384,400 L 304,480 ZM 224,144 L 128,48 L 208-32 L 0-32 L 0,176 L 80,96 L 176,192 Z" />
<glyph unicode="&#x67;" d="M 224,192 L 224-16 L 144,64 L 48-32 L 0,16 L 96,112 L 16,192 ZM 512,432 L 416,336 L 496,256 L 288,256 L 288,464 L 368,384 L 464,480 Z" />
<glyph unicode="&#x68;" d="M 512,480 L 512,288 L 442.87,357.13 L 336.87,251.13 L 283.13,304.87 L 389.13,410.87 L 320,480 ZM 122.87,410.87 L 228.87,304.87 L 175.13,251.13 L 69.13,357.13 L 0,288 L 0,480 L 192,480 ZM 442.87,90.87 L 512,160 L 512-32 L 320-32 L 389.13,37.13 L 283.13,143.13 L 336.87,196.87 ZM 228.87,143.13 L 122.87,37.13 L 192-32 L 0-32 L 0,160 L 69.13,90.87 L 175.13,196.87 Z" />
<glyph unicode="&#x69;" d="M 32,192 L 224,192 L 224,0 L 154.87,69.13 L 53.87-31.87 L 0.13,21.87 L 101.13,122.87 ZM 410.87,122.87 L 511.87,21.87 L 458.13-31.87 L 357.13,69.13 L 288,0 L 288,192 L 480,192 ZM 480,256 L 288,256 L 288,448 L 357.13,378.87 L 458.13,479.87 L 511.87,426.13 L 410.87,325.13 ZM 154.87,378.87 L 224,448 L 224,256 L 32,256 L 101.13,325.13 L 0.13,426.13 L 53.87,479.87 Z" />
<glyph unicode="&#xe208;" d="M 96,416L 416,224L 96,32 z" />
<glyph unicode="&#xe209;" d="M 64,416L 224,416L 224,32L 64,32zM 288,416L 448,416L 448,32L 288,32z" />
<glyph unicode="&#xe210;" d="M 64,416L 448,416L 448,32L 64,32z" />
<glyph unicode="&#x7c;" d="M 288,400 L 288,240 L 448,400 L 448,48 L 288,208 L 288,48 L 112,224 Z" />
<glyph unicode="&#x7b;" d="M 256,48 L 256,208 L 96,48 L 96,400 L 256,240 L 256,400 L 432,224 Z" />
<glyph unicode="&#x7d;" d="M 64,32 L 64,416 L 128,416 L 128,240 L 288,400 L 288,240 L 448,400 L 448,48 L 288,208 L 288,48 L 128,208 L 128,32 Z" />
<glyph unicode="&#xe000;" d="M 448,416 L 448,32 L 384,32 L 384,208 L 224,48 L 224,208 L 64,48 L 64,400 L 224,240 L 224,400 L 384,240 L 384,416 Z" />
<glyph unicode="&#xe00d;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,16 c-114.875,0-208,93.125-208,208S 141.125,432, 256,432s 208-93.125, 208-208S 370.875,16, 256,16zM 192,336L 384,224L 192,112 z" />
<glyph unicode="&#xe211;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,16 c-114.875,0-208,93.125-208,208S 141.125,432, 256,432s 208-93.125, 208-208S 370.875,16, 256,16zM 160,320L 224,320L 224,128L 160,128zM 288,320L 352,320L 352,128L 288,128z" />
<glyph unicode="&#xe212;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,16 c-114.875,0-208,93.125-208,208S 141.125,432, 256,432s 208-93.125, 208-208S 370.875,16, 256,16zM 160,320L 352,320L 352,128L 160,128z" />
<glyph unicode="&#xe213;" d="M 256-32c 141.385,0, 256,114.615, 256,256S 397.385,480, 256,480S0,365.385,0,224S 114.615-32, 256-32z M 256,432 c 114.875,0, 208-93.125, 208-208s-93.125-208-208-208S 48,109.125, 48,224S 141.125,432, 256,432zM 352,144L 240,224L 352,304 zM 224,144L 112,224L 224,304 z" />
<glyph unicode="&#xe214;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,16 c-114.875,0-208,93.125-208,208S 141.125,432, 256,432s 208-93.125, 208-208S 370.875,16, 256,16zM 160,304L 272,224L 160,144 zM 288,304L 400,224L 288,144 z" />
<glyph unicode="&#xe001;" d="M 437.011,405.010C 390.685,451.338, 326.693,480, 256,480C 146.256,480, 52.655,410.936, 16.251,313.906l 59.938-22.477 C 103.491,364.202, 173.692,416, 256,416c 53.020,0, 101.010-21.5, 135.753-56.247L 320,288l 192,0 L 512,480 L 437.011,405.010zM 256,32c-53.020,0-101.013,21.496-135.756,56.244L 192,160L0,160 l0-192 l 74.997,74.997C 121.32-3.334, 185.306-32, 256-32 c 109.745,0, 203.346,69.064, 239.75,166.094l-59.938,22.477C 408.51,83.798, 338.309,32, 256,32z" />
<glyph unicode="&#xe002;" d="M 512,352L 384,480l0-96 c-65.386,0-115.376-15.604-152.825-47.704c-2.625-2.25-5.142-4.55-7.581-6.887 c 13.76-19.082, 24.358-38.758, 33.886-57.545C 281.641,301.065, 316.507,320, 384,320l0-96 l0,0 l0-96 c-108.223,0-132.563,48.68-163.378,110.311 c-17.153,34.306-34.89,69.78-67.796,97.985C 115.376,368.396, 65.386,384,0,384l0-64 c 108.223,0, 132.563-48.68, 163.378-110.311 c 17.153-34.306, 34.89-69.78, 67.796-97.985C 268.624,79.604, 318.615,64, 384,64l0-96 l 128,128L 384,224L 512,352zM0,128l0-64 c 65.386,0, 115.375,15.604, 152.825,47.704c 2.625,2.249, 5.142,4.55, 7.581,6.888 c-13.76,19.081-24.359,38.758-33.886,57.545C 102.36,146.936, 67.494,128,0,128z" />
<glyph unicode="&#x53;" d="M 496.131,44.302L 374.855,147.449c-12.537,11.283-25.945,16.463-36.776,15.963C 366.707,196.946, 384,240.451, 384,288 C 384,394.039, 298.039,480, 192,480C 85.962,480,0,394.039,0,288c0-106.039, 85.961-192, 192-192c 47.549,0, 91.054,17.293, 124.588,45.922 c-0.5-10.831, 4.68-24.239, 15.963-36.776l 103.147-121.276c 17.661-19.623, 46.511-21.277, 64.11-3.678S 515.754,26.641, 496.131,44.302z M 192,160c-70.692,0-128,57.308-128,128S 121.308,416, 192,416s 128-57.308, 128-128S 262.693,160, 192,160z" />
<glyph unicode="&#x64;" d="M 192,384L 160,384L 160,320L 96,320L 96,288L 160,288L 160,224L 192,224L 192,288L 256,288L 256,320L 192,320 zM 318.771,201.076C 339.674,230.021, 352,265.568, 352,304C 352,401.202, 273.202,480, 176,480S0,401.202,0,304s 78.798-176, 176-176 c 38.432,0, 73.979,12.326, 102.924,33.229L 448-32l 64,64L 318.771,201.076z M 176,176c-70.692,0-128,57.308-128,128S 105.308,432, 176,432 s 128-57.308, 128-128S 246.693,176, 176,176z" />
<glyph unicode="&#x65;" d="M 96,320L 256,320L 256,288L 96,288zM 318.771,201.076C 339.674,230.021, 352,265.568, 352,304C 352,401.202, 273.202,480, 176,480S0,401.202,0,304s 78.798-176, 176-176 c 38.432,0, 73.979,12.326, 102.924,33.229L 448-32l 64,64L 318.771,201.076z M 176,176c-70.692,0-128,57.308-128,128S 105.308,432, 176,432 s 128-57.308, 128-128S 246.693,176, 176,176z" />
<glyph unicode="&#x2b;" d="M 424,312 L 208,96 L 128,96 L 128,176 L 344,392 ZM 451,339 L 371,419 L 399.029,447.029 C 408.363,456.363 423.636,456.363 432.97,447.029 L 479.029,400.97 C 488.363,391.636 488.363,376.363 479.029,367.029 L 451,339 ZM 384,198.209L 384,32 L 64,32 L 64,352 l 176,0 l 64,64L 48,416 C 21.6,416,0,394.4,0,368l0-352 c0-26.4, 21.6-48, 48-48l 352,0 c 26.4,0, 48,21.6, 48,48L 448,255.681 L 384,198.209z" />
<glyph unicode="&#x2c;" d="M 432,480 C 476.182,480 512,444.183 512,400 C 512,381.99 506.045,365.371 496,352 L 464,320 L 352,432 L 384,464 C 397.371,474.045 413.989,480 432,480 ZM 32,112L0-32l 144,32l 296,296L 328,408L 32,112z M 357.789,298.211l-224-224l-27.578,27.578l 224,224L 357.789,298.211z" />
<glyph unicode="&#x3b;" d="M 160.061,160C 96.036,160, 117.88,46.86,0,21.363c 32.011-21.324, 125.898-39.027, 192.072,10.668 C 249.298,75.006, 224.085,160, 160.061,160zM 505.965,441.965c-32.009,32.007-110.472-72.027-171.617-107.603c-60.98-37.464-144.033-112.027-96.021-160.037 c 48.010-48.013, 122.571,35.040, 160.036,96.022C 433.938,331.495, 537.973,409.958, 505.965,441.965z" />
<glyph unicode="&#x5d;" d="M 496,288L 320,288 L 320,464 c0,8.836-7.164,16-16,16l-96,0 c-8.836,0-16-7.164-16-16l0-176 L 16,288 c-8.836,0-16-7.164-16-16l0-96 c0-8.836, 7.164-16, 16-16l 176,0 l0-176 c0-8.836, 7.164-16, 16-16l 96,0 c 8.836,0, 16,7.164, 16,16L 320,160 l 176,0 c 8.836,0, 16,7.164, 16,16l0,96 C 512,280.836, 504.836,288, 496,288z" />
<glyph unicode="&#x5e;" d="M0,272l0-96 c0-8.836, 7.164-16, 16-16l 480,0 c 8.836,0, 16,7.164, 16,16l0,96 c0,8.836-7.164,16-16,16L 16,288 C 7.164,288,0,280.836,0,272z" />
<glyph unicode="&#x49;" d="M 507.331,68.67c-0.002,0.002-0.004,0.004-0.006,0.005L 352.003,224l 155.322,155.325c 0.002,0.002, 0.004,0.003, 0.006,0.005 c 1.672,1.673, 2.881,3.627, 3.656,5.708c 2.123,5.688, 0.912,12.341-3.662,16.915L 433.952,475.326c-4.574,4.573-11.225,5.783-16.914,3.66 c-2.080-0.775-4.035-1.984-5.709-3.655c0-0.002-0.002-0.003-0.004-0.005L 256.001,320L 100.677,475.325 c-0.002,0.002-0.003,0.003-0.005,0.005c-1.673,1.671-3.627,2.88-5.707,3.655c-5.69,2.124-12.341,0.913-16.915-3.66L 4.676,401.951 c-4.574-4.574-5.784-11.226-3.661-16.914c 0.776-2.080, 1.985-4.036, 3.656-5.708c 0.002-0.001, 0.003-0.003, 0.005-0.005L 160.001,224 L 4.676,68.674c-0.001-0.002-0.003-0.003-0.004-0.005c-1.671-1.673-2.88-3.627-3.657-5.707c-2.124-5.688-0.913-12.341, 3.661-16.915 l 73.374-73.373c 4.575-4.574, 11.226-5.784, 16.915-3.661c 2.080,0.776, 4.035,1.985, 5.708,3.656c 0.001,0.002, 0.003,0.003, 0.005,0.005 l 155.324,155.325l 155.324-155.325c 0.002-0.001, 0.004-0.003, 0.006-0.004c 1.674-1.672, 3.627-2.881, 5.707-3.657 c 5.689-2.123, 12.342-0.913, 16.914,3.661l 73.373,73.374c 4.574,4.574, 5.785,11.227, 3.662,16.915 C 510.212,65.043, 509.003,66.997, 507.331,68.67z" />
<glyph unicode="&#x47;" d="M 432,416L 192,176L 80,288L0,208L 192,16L 512,336 z" />
<glyph unicode="&#x2a;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 288,192l0-128 l-64,0 L 224,192 L 96,192 l0,64 l 128,0 L 224,384 l 64,0 l0-128 l 128,0 l0-64 L 288,192 z" />
<glyph unicode="&#xe215;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,32 c-106.039,0-192,85.961-192,192c0,106.039, 85.961,192, 192,192c 106.039,0, 192-85.961, 192-192C 448,117.961, 362.039,32, 256,32zM 384,192 L 288,192 L 288,96 L 224,96 L 224,192 L 128,192 L 128,256 L 224,256 L 224,352 L 288,352 L 288,256 L 384,256 Z" />
<glyph unicode="&#x4b;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 416,192L 96,192 l0,64 l 320,0 L 416,192 z" />
<glyph unicode="&#xe216;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,32 c-106.039,0-192,85.961-192,192c0,106.039, 85.961,192, 192,192c 106.039,0, 192-85.961, 192-192C 448,117.961, 362.039,32, 256,32zM 128,256L 384,256L 384,192L 128,192z" />
<glyph unicode="&#x4a;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 384,306.745L 301.256,224 L 384,141.256L 384,96 l-45.256,0 L 256,178.744L 173.255,96L 128,96 l0,45.256 L 210.745,224L 128,306.745L 128,352 l 45.255,0 L 256,269.255L 338.744,352L 384,352 L 384,306.745 z" />
<glyph unicode="&#xe217;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,32 c-106.039,0-192,85.961-192,192c0,106.039, 85.961,192, 192,192c 106.039,0, 192-85.961, 192-192C 448,117.961, 362.039,32, 256,32zM 352,173.256 L 352,128 L 306.744,128 L 256,178.744 L 205.255,128 L 160,128 L 160,173.256 L 210.745,224 L 160,274.745 L 160,320 L 205.255,320 L 256,269.255 L 306.744,320 L 352,320 L 352,274.745 L 301.256,224 Z" />
<glyph unicode="&#xe218;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 208,64L 102,202l 47,49l 59-75 l 185,151l 23-23L 208,64z" />
<glyph unicode="&#xe219;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,32 c-106.039,0-192,85.961-192,192c0,106.039, 85.961,192, 192,192c 106.039,0, 192-85.961, 192-192C 448,117.961, 362.039,32, 256,32zM 208,64L 102,202L 149,251L 208,176L 393,327L 416,304 z" />
<glyph unicode="&#xe220;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 224,384l 64,0 l0-64 l-64,0 L 224,384 z M 320,64L 192,64 l0,32 l 32,0 L 224,224 l-32,0 l0,32 l 96,0 l0-160 l 32,0 L 320,64 z" />
<glyph unicode="&#xe221;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,16 c-114.875,0-208,93.125-208,208S 141.125,432, 256,432s 208-93.125, 208-208S 370.875,16, 256,16zM 224,352L 288,352L 288,288L 224,288zM 320,96L 192,96L 192,128L 224,128L 224,224L 192,224L 192,256L 288,256L 288,128L 320,128 z" />
<glyph unicode="&#x45;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.613-256, 256-256c 141.385,0, 256,114.615, 256,256S 397.385,480, 256,480z M 288,64l-64,0 l0,64 l 64,0 L 288,64 z M 384,256c0-35.29-28.71-64-64-64l-31.942,0 c-0.020-0.017-0.041-0.038-0.058-0.058L 288,160 l-64,0 l0,32 c0,35.29, 28.71,64, 64,64l 31.942,0 c 0.020,0.017, 0.041,0.038, 0.058,0.057l0,63.885 c-0.017,0.020-0.037,0.041-0.058,0.058L 160,320 L 160,384 l 160,0 c 35.29,0, 64-28.71, 64-64L 384,256 z" />
<glyph unicode="&#xe222;" d="M 320,384 C 355.29,384 384,355.29 384,320 L 384,256 C 384,220.71 355.29,192 320,192 L 288.059,192 C 288.038,191.982 288.018,191.962 288,191.941 L 288,160 L 224,160 L 224,192 C 224,227.29 252.71,256 288,256 L 319.942,256 C 319.962,256.016 319.983,256.037 320,256.057 L 320,319.942 C 319.983,319.962 319.963,319.983 319.942,320 L 160,320 L 160,384 L 320,384 ZM 224,128L 288,128L 288,64L 224,64zM 256,432 C 200.441,432 148.208,410.364 108.922,371.078 C 69.636,331.792 48,279.559 48,224 C 48,168.441 69.636,116.208 108.922,76.922 C 148.208,37.636 200.441,16 256,16 C 311.559,16 363.792,37.636 403.078,76.922 C 442.364,116.208 464,168.441 464,224 C 464,279.559 442.364,331.792 403.078,371.078 C 363.792,410.364 311.559,432 256,432 Z M 256,480 L 256,480 C 397.385,480 512,365.385 512,224 C 512,82.615 397.385-32 256-32 C 114.615-32 0,82.615 0,224 C 0,365.385 114.615,480 256,480 Z" />
<glyph unicode="&#xe223;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 288,64l-64,0 l0,64 l 64,0 L 288,64 z M 288,192l-64,0 L 224,384 l 64,0 L 288,192 z" />
<glyph unicode="&#xe224;" d="M 256,432 C 200.441,432 148.208,410.364 108.922,371.078 C 69.636,331.792 48,279.559 48,224 C 48,168.441 69.636,116.208 108.922,76.922 C 148.208,37.636 200.441,16 256,16 C 311.559,16 363.792,37.636 403.078,76.922 C 442.364,116.208 464,168.441 464,224 C 464,279.559 442.364,331.792 403.078,371.078 C 363.792,410.364 311.559,432 256,432 Z M 256,480 L 256,480 C 397.385,480 512,365.385 512,224 C 512,82.615 397.385-32 256-32 C 114.615-32 0,82.615 0,224 C 0,365.385 114.615,480 256,480 ZM 224,128L 288,128L 288,64L 224,64zM 224,384L 288,384L 288,192L 224,192z" />
<glyph unicode="&#x48;" d="M 504.978,22.12L 286.441,457.676C 278.070,472.559, 267.035,480, 256,480s-22.070-7.441-30.442-22.324L 7.021,22.12 C-9.722-7.646, 4.521-32, 38.673-32l 434.654,0 C 507.478-32, 521.723-7.646, 504.978,22.12z M 256,32c-17.673,0-32,14.327-32,32 c0,17.674, 14.327,32, 32,32c 17.674,0, 32-14.326, 32-32C 288,46.327, 273.674,32, 256,32z M 278,128l-44,0 l-10,128 c0,17.673, 14.327,32, 32,32s 32-14.327, 32-32L 278,128z" />
<glyph unicode="&#xe225;" d="M 256,400.638 L 83.583,32 L 428.417,32 L 256,400.638 Z M 256,480 L 256,480 C 267.035,480 278.070,472.559 286.442,457.676 L 504.978,22.12 C 521.723-7.646 507.478-32 473.327-32 L 38.673-32 C 4.521-32 -9.722-7.646 7.021,22.12 L 225.558,457.676 C 233.93,472.559 244.965,480 256,480 ZM 224,96A32,32 3060 1 0 288,96A32,32 3060 1 0 224,96zM 256,288 C 273.673,288 288,273.673 288,256 L 278,160 L 234,160 L 224,256 C 224,273.673 238.327,288 256,288 Z" />
<glyph unicode="&#x3d;" d="M0,480l0-512 l 512,0 L 512,480 L0,480 z M 480,0L 32,0 L 32,448 l 448,0 L 480,0 z" />
<glyph unicode="&#x3e;" d="M0,480l0-512 l 512,0 L 512,480 L0,480 z M 480,0L 32,0 L 32,448 l 448,0 L 480,0 z M 384,368L 224,208l-96,96l-64-64l 160-160l 224,224L 384,368z" />
<glyph unicode="&#x3f;" d="M0,480l0-512 l 512,0 L 512,480 L0,480 z M 480,0L 32,0 L 32,448 l 448,0 L 480,0 zM 128,352L 384,352L 384,96L 128,96z" />
<glyph unicode="&#xe226;" d="M0,480L 512,480L 512-32L0-32z" />
<glyph unicode="&#xe227;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,32 c-106.039,0-192,85.961-192,192c0,106.039, 85.961,192, 192,192c 106.039,0, 192-85.961, 192-192C 448,117.961, 362.039,32, 256,32z" />
<glyph unicode="&#xe228;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,32 c-106.039,0-192,85.961-192,192c0,106.039, 85.961,192, 192,192c 106.039,0, 192-85.961, 192-192C 448,117.961, 362.039,32, 256,32zM 160,224A96,96 13140 1 0 352,224A96,96 13140 1 0 160,224z" />
<glyph unicode="&#xe229;" d="M0,224A256,256 5220 1 0 512,224A256,256 5220 1 0 0,224z" />
<glyph unicode="&#xe230;" d="M 224,82.745L 121.373,201.372L 150.627,230.627L 224,173.255L 361.372,294.627L 390.628,265.373 zM 415.886,416c 0.039-0.033, 0.081-0.075, 0.114-0.115l0-383.771 c-0.033-0.039-0.075-0.081-0.114-0.114L 96.114,32 c-0.040,0.033-0.081,0.075-0.114,0.114L 96,415.886 c 0.033,0.040, 0.075,0.081, 0.115,0.114L 32,416 l0-384 c0-35.2, 28.8-64, 64-64l 320,0 c 35.2,0, 64,28.8, 64,64L 480,416 L 415.886,416 z M 320,416L 320,448 c0,17.673-14.327,32-32,32l-64,0 c-17.673,0-32-14.327-32-32l0-32 l-64,0 l0-64 l 256,0 L 384,416 L 320,416 z M 288,416l-64,0 L 224,448 l 64,0 L 288,416 z" />
<glyph unicode="&#x58;" d="M0,480L 224,480L 224,256L0,256zM 288,480L 512,480L 512,256L 288,256zM0,192L 224,192L 224-32L0-32zM 288,192L 512,192L 512-32L 288-32z" />
<glyph unicode="&#x59;" d="M0,480L 128,480L 128,352L0,352zM 192,480L 320,480L 320,352L 192,352zM 384,480L 512,480L 512,352L 384,352zM0,288L 128,288L 128,160L0,160zM 192,288L 320,288L 320,160L 192,160zM 384,288L 512,288L 512,160L 384,160zM0,96L 128,96L 128-32L0-32zM 192,96L 320,96L 320-32L 192-32zM 384,96L 512,96L 512-32L 384-32z" />
<glyph unicode="&#x5a;" d="M 192,448L 320,448L 320,320L 192,320zM 192,288L 320,288L 320,160L 192,160zM 192,128L 320,128L 320,0L 192,0z" />
<glyph unicode="&#x31;" d="M0,480L 128,480L 128,352L0,352zM 192,480L 512,480L 512,352L 192,352zM0,288L 128,288L 128,160L0,160zM 192,288L 512,288L 512,160L 192,160zM0,96L 128,96L 128-32L0-32zM 192,96L 512,96L 512-32L 192-32z" />
<glyph unicode="&#xe231;" d="M0,480L 128,480L 128,352L0,352zM 192,448L 512,448L 512,384L 192,384zM0,288L 128,288L 128,160L0,160zM 192,256L 512,256L 512,192L 192,192zM0,96L 128,96L 128-32L0-32zM 192,64L 512,64L 512,0L 192,0z" />
<glyph unicode="&#xe232;" d="M 448,96L 64,96 c-35.2,0-64-28.8-64-64s 28.8-64, 64-64l 384,0 c 35.2,0, 64,28.8, 64,64S 483.2,96, 448,96zM 448,288L 64,288 c-35.2,0-64-28.8-64-64s 28.8-64, 64-64l 384,0 c 35.2,0, 64,28.8, 64,64S 483.2,288, 448,288zM 64,352l 384,0 c 35.2,0, 64,28.8, 64,64S 483.2,480, 448,480L 64,480 C 28.8,480,0,451.2,0,416S 28.8,352, 64,352z" />
<glyph unicode="&#x2d;" d="M 416,0L 512,256L 96,256L0,0 zM 64,288 L 0,0 L 0,416 L 144,416 L 208,352 L 416,352 L 416,288 Z" />
<glyph unicode="&#x2e;" d="M 224,416L 288,352L 512,352L 512,0L0,0L0,416 z" />
<glyph unicode="&#xe234;" d="M 288,352l-64,64L0,416 l0-416 l 512,0 L 512,352 L 288,352 z M 352,128l-64,0 l0-64 l-64,0 l0,64 l-64,0 l0,64 l 64,0 l0,64 l 64,0 l0-64 l 64,0 L 352,128 z" />
<glyph unicode="&#xe235;" d="M 288,352l-64,64L0,416 l0-416 l 512,0 L 512,352 L 288,352 z M 352,128L 160,128 l0,64 l 192,0 L 352,128 z" />
<glyph unicode="&#xe236;" d="M 210.745,384l 54.628-54.627l 9.372-9.373L 288,320 l 192,0 l0-288 L 32,32 L 32,384 L 210.745,384 M 224,416L0,416 l0-416 l 512,0 L 512,352 L 288,352 L 224,416L 224,416z" />
<glyph unicode="&#xe237;" d="M 288,352l-64,64L0,416 l0-416 l 512,0 L 512,352 L 288,352 z M 480,32L 32,32 L 32,384 l 178.745,0 l 54.628-54.627l 9.372-9.373L 288,320 l 192,0 L 480,32 zM 288,256L 224,256L 224,192L 160,192L 160,128L 224,128L 224,64L 288,64L 288,128L 352,128L 352,192L 288,192 z" />
<glyph unicode="&#xe238;" d="M 288,352l-64,64L0,416 l0-416 l 512,0 L 512,352 L 288,352 z M 480,32L 32,32 L 32,384 l 178.745,0 l 54.628-54.627l 9.372-9.373L 288,320 l 192,0 L 480,32 zM 160,192L 352,192L 352,128L 160,128z" />
<glyph unicode="&#xe016;" d="M 352,480L 32,480 l0-512 l 448,0 L 480,352 L 352,480z M 448,0L 64,0 L 64,448 l 288,0 l0-96 l 96,0 L 448,0 z" />
<glyph unicode="&#xe239;" d="M 352,480L 32,480 l0-512 l 448,0 L 480,352 L 352,480z M 448,0L 64,0 L 64,448 l 288,0 l0-96 l 96,0 L 448,0 zM 128,96L 384,96L 384,64L 128,64zM 128,160L 384,160L 384,128L 128,128zM 128,224L 384,224L 384,192L 128,192z" />
<glyph unicode="&#x29;" d="M 448,96L 448,160L 384,160L 384,96L 320,96L 320,32L 384,32L 384-32L 448-32L 448,32L 512,32L 512,96 zM 32,448L 320,448L 320,352L 416,352L 416,192L 448,192L 448,352L 320,480L0,480L0-32L 288-32L 288,0L 32,0 z" />
<glyph unicode="&#xe017;" d="M 320,96L 512,96L 512,32L 320,32zM 32,448L 320,448L 320,352L 416,352L 416,192L 448,192L 448,352L 320,480L0,480L0-32L 288-32L 288,0L 32,0 z" />
<glyph unicode="&#xe240;" d="M 352-32L 256,80L 296.75,120.75L 352,65.125L 480,192L 512,160 zM 32,448l 288,0 l0-96 l 96,0 l0-160 l 32,0 L 448,352 L 320,480L0,480 l0-512 l 288,0 l0,32 L 32,0 L 32,448 z" />
<glyph unicode="&#xe241;" d="M 32,448l 288,0 l0-96 l 96,0 l0-160 l 32,0 L 448,352 L 320,480L0,480 l0-512 l 288,0 l0,32 L 32,0 L 32,448 zM 461.256,64L 512,114.744L 512,160L 466.744,160L 416,109.256L 365.256,160L 320,160L 320,114.744L 370.744,64L 320,13.256L 320-32L 365.256-32L 416,18.744L 466.744-32L 512-32L 512,13.256 z" />
<glyph unicode="&#xe018;" d="M 416,352l-96,0 L 320,384 L 224,480L0,480 l0-384 l 192,0 l0-128 l 320,0 L 512,256 L 416,352z M 416,306.745L 466.745,256L 416,256 L 416,306.745 z M 224,434.745L 274.745,384L 224,384 L 224,434.745 z M 32,448l 160,0 l0-96 l 96,0 l0-224 L 32,128 L 32,448 z M 480,0L 224,0 l0,96 l 96,0 L 320,320 l 64,0 l0-96 l 96,0 L 480,0 z" />
<glyph unicode="&#xe242;" d="M 440,352l-24,0 l0,24 c0,22.056-17.944,40-40,40l-24,0 L 352,440 c0,22.056-17.943,40-40,40l-240,0 c-22.056,0-40-17.944-40-40l0-304 c0-22.057, 17.944-40, 40-40l 24,0 l0-24 c0-22.057, 17.944-40, 40-40l 24,0 l0-24 c0-22.056, 17.944-40, 40-40l 240,0 c 22.056,0, 40,17.944, 40,40L 480,312 C 480,334.056, 462.056,352, 440,352z M 72.001,128c-4.4,0-8,3.6-8,8L 64.001,440 c0,4.4, 3.6,8, 8,8l 240,0 c 4.4,0, 8-3.6, 8-8l0-24 L 136,416 c-22.056,0-40-17.944-40-40l0-248 L 72.001,128 z M 136,64c-4.4,0-8,3.6-8,8L 128,376 c0,4.4, 3.6,8, 8,8l 240,0 c 4.4,0, 8-3.6, 8-8l0-24 L 200,352 c-22.056,0-40-17.944-40-40l0-248 L 136,64 z M 448,8c0-4.4-3.6-8-8-8L 200,0 c-4.4,0-8,3.6-8,8L 192,312 c0,4.4, 3.6,8, 8,8l 240,0 c 4.4,0, 8-3.6, 8-8L 448,8 z" />
<glyph unicode="&#xe243;" d="M 488,128l-50.411,0 L 320,323.98L 320,424 c0,13.2-10.8,24-24,24l-80,0 c-13.2,0-24-10.8-24-24l0-100.019 L 74.412,128L 24,128 c-13.2,0-24-10.8-24-24l0-80 c0-13.2, 10.8-24, 24-24l 80,0 c 13.2,0, 24,10.8, 24,24L 128,124.020 L 245.588,320l 20.823,0 L 384,124.020L 384,24 c0-13.2, 10.8-24, 24-24l 80,0 c 13.2,0, 24,10.8, 24,24l0,80 C 512,117.2, 501.2,128, 488,128z" />
<glyph unicode="&#xe244;" d="M 488,96l-8,0 L 480,200 c0,30.878-25.121,56-56,56L 288,256 l0,64 l 8,0 c 13.2,0, 24,10.8, 24,24L 320,424 c0,13.2-10.8,24-24,24l-80,0 c-13.2,0-24-10.8-24-24l0-80 c0-13.2, 10.8-24, 24-24l 8,0 l0-64 L 88,256 c-30.878,0-56-25.122-56-56l0-104 l-8,0 c-13.2,0-24-10.8-24-24l0-80 c0-13.2, 10.8-24, 24-24l 80,0 c 13.2,0, 24,10.8, 24,24l0,80 c0,13.2-10.8,24-24,24l-8,0 l0,96 l 128,0 l0-96 l-8,0 c-13.2,0-24-10.8-24-24l0-80 c0-13.2, 10.8-24, 24-24l 80,0 c 13.2,0, 24,10.8, 24,24l0,80 c0,13.2-10.8,24-24,24l-8,0 l0,96 l 128,0 l0-96 l-8,0 c-13.2,0-24-10.8-24-24l0-80 c0-13.2, 10.8-24, 24-24l 80,0 c 13.2,0, 24,10.8, 24,24l0,80 C 512,85.2, 501.2,96, 488,96z M 96,0L 32,0 l0,64 l 64,0 L 96,0 z M 288,0l-64,0 l0,64 l 64,0 L 288,0 z M 224,352L 224,416 l 64,0 l0-64 L 224,352 z M 480,0l-64,0 l0,64 l 64,0 L 480,0 z" />
<glyph unicode="&#xe246;" d="M0,448L 512,448L 512,384L0,384zM0,352L 320,352L 320,288L0,288zM0,160L 320,160L 320,96L0,96zM0,256L 512,256L 512,192L0,192zM0,64L 512,64L 512,0L0,0z" />
<glyph unicode="&#xe247;" d="M0,448L 512,448L 512,384L0,384zM 96,352L 416,352L 416,288L 96,288zM 96,160L 416,160L 416,96L 96,96zM0,256L 512,256L 512,192L0,192zM0,64L 512,64L 512,0L0,0z" />
<glyph unicode="&#xe248;" d="M0,448L 512,448L 512,384L0,384zM 192,352L 512,352L 512,288L 192,288zM 192,160L 512,160L 512,96L 192,96zM0,256L 512,256L 512,192L0,192zM0,64L 512,64L 512,0L0,0z" />
<glyph unicode="&#xe249;" d="M0,448L 512,448L 512,384L0,384zM0,352L 512,352L 512,288L0,288zM0,256L 512,256L 512,192L0,192zM0,160L 512,160L 512,96L0,96zM0,64L 512,64L 512,0L0,0z" />
<glyph unicode="&#xe01c;" d="M 512,64L 512,448 L0,448 l0-384 l 224,0 l0-32 l-96,0 l0-32 l 256,0 l0,32 l-96,0 l0,32 L 512,64 z M 64,384l 384,0 l0-256 L 64,128 L 64,384 z" />
<glyph unicode="&#xe01d;" d="M 400,480L 80,480 C 53.6,480, 32,458.4, 32,432l0-416 c0-26.4, 21.6-48, 48-48l 320,0 c 26.4,0, 48,21.6, 48,48L 448,432 C 448,458.4, 426.4,480, 400,480z M 240-16 c-8.836,0-16,7.163-16,16s 7.164,16, 16,16s 16-7.163, 16-16S 248.836-16, 240-16z M 384,32L 96,32 L 96,416 l 288,0 L 384,32 z" />
<glyph unicode="&#xe01e;" d="M 384,480L 96,480 C 78.4,480, 64,465.601, 64,448l0-448 c0-17.6, 14.399-32, 32-32l 288,0 c 17.6,0, 32,14.4, 32,32L 416,448 C 416,465.601, 401.6,480, 384,480z M 240-8.891c-13.746,0-24.891,11.145-24.891,24.891s 11.145,24.891, 24.891,24.891s 24.891-11.145, 24.891-24.891 S 253.746-8.891, 240-8.891z M 384,64L 96,64 L 96,416 l 288,0 L 384,64 z" />
<glyph unicode="&#x51;" d="M 416,448L 96,448 L0,352l0-336 c0-8.837, 7.163-16, 16-16l 480,0 c 8.836,0, 16,7.163, 16,16L 512,352 L 416,448z M 256,64L 96,192l 96,0 l0,96 l 128,0 l0-96 l 96,0 L 256,64z M 77.255,384l 32,32l 293.489,0 l 32-32L 77.255,384 z" />
<glyph unicode="&#x52;" d="M 416,448L 96,448 L0,352l0-336 c0-8.837, 7.163-16, 16-16l 480,0 c 8.836,0, 16,7.163, 16,16L 512,352 L 416,448z M 320,160l0-96 L 192,64 l0,96 L 96,160 l 160,128 l 160-128L 320,160 z M 77.255,384l 32,32l 293.488,0 l 32-32L 77.255,384 z" />
<glyph unicode="&#xe021;" d="M 448,128L 448,64L 64,64L 64,128L0,128L0,0L 512,0L 512,128 zM 384,288L 288,288L 288,448L 224,448L 224,288L 128,288L 256,96 z" />
<glyph unicode="&#xe022;" d="M 448,128L 448,64L 64,64L 64,128L0,128L0,0L 512,0L 512,128 zM 128,256L 224,256L 224,96L 288,96L 288,256L 384,256L 256,448 z" />
<glyph unicode="&#x21;" d="M 512,184.777 L 256,383.491 L 0,184.777 L 0,265.796 L 256,464.509 L 512,265.795 ZM 448,192 L 448,0 L 64,0 L 64,192 L 256,336 Z" />
<glyph unicode="&#xe250;" d="M 448,192 L 448,0 L 64,0 L 64,192 L 128,192 L 128,64 L 384,64 L 384,192 ZM 512,184.777 L 256,383.491 L 0,184.777 L 0,265.796 L 256,464.509 L 512,265.795 Z" />
<glyph unicode="&#xe024;" d="M 352,192 L 416,256 L 416,0 L 32,0 L 32,384 L 288,384 L 224,320 L 96,320 L 96,64 L 352,64 ZM 480,448 L 480,272 L 414.628,337.372 L 237.255,160 L 192,160 L 192,205.256 L 369.372,382.628 L 304,448 Z" />
<glyph unicode="&#xe251;" d="M 96,448l0-384 l 384,0 L 480,448 L 96,448 z M 448,96L 128,96 L 128,416 l 320,0 L 448,96 zM 64,32L 64,352L 32,384L 32,0L 416,0L 384,32 zM 214.627,137.373L 310.627,233.373L 384,160L 384,352L 192,352L 265.373,278.627L 169.373,182.627 z" />
<glyph unicode="&#xe252;" d="M 476.698,442.679l-2.014,2.021c-47.074,47.067-124.097,47.067-171.163,0L 194.468,335.632 c-47.067-47.066-47.067-124.088,0-171.155l 2.013-2.013c 3.916-3.924, 8.073-7.462, 12.368-10.729l 39.924,39.925 c-4.651,2.747-9.063,6.036-13.058,10.030l-2.021,2.021c-25.557,25.549-25.557,67.136,0,92.695L 342.758,405.462 c 25.558,25.559, 67.137,25.559, 92.693,0l 2.021-2.012c 25.55-25.558, 25.55-67.146,0-92.695l-49.343-49.343 c 8.566-21.154, 12.624-43.7, 12.269-66.193l 76.302,76.302C 523.767,318.589, 523.767,395.61, 476.698,442.679zM 315.521,285.533c-3.916,3.916-8.073,7.461-12.368,10.72l-39.924-39.916c 4.652-2.748, 9.063-6.037, 13.058-10.031l 2.021-2.020 c 25.558-25.558, 25.558-67.136,0-92.694L 169.243,42.525c-25.559-25.551-67.138-25.551-92.694,0l-2.021,2.021 c-25.549,25.56-25.549,67.138,0,92.694l 49.344,49.343c-8.567,21.153-12.623,43.701-12.269,66.193l-76.301-76.299 c-47.068-47.066-47.068-124.089,0-171.162l 2.013-2.016c 47.076-47.064, 124.096-47.064, 171.164,0l 109.055,109.059 c 47.067,47.066, 47.067,124.097,0,171.163L 315.521,285.533z" />
<glyph unicode="&#x2f;" d="M0,416l0-384 l 512,0 L 512,416 L0,416 z M 480,64l-32,0 l-96,144l-64-48L 160,320L 64,64L 32,64 L 32,384 l 448,0 L 480,64 zM 352,304A48,48 13140 1 0 448,304A48,48 13140 1 0 352,304z" />
<glyph unicode="&#x30;" d="M 64,352l0-320 l 448,0 L 512,352 L 64,352 z M 480,85.333L 416,192l-72.533-60.444L 288,224L 96,64L 96,320 l 384,0 L 480,85.333 zM 128,240A48,48 8100 1 0 224,240A48,48 8100 1 0 128,240zM 448,416L0,416L0,96L 32,96L 32,384L 448,384 z" />
<glyph unicode="&#xe014;" d="M 257.54,416C 92.994,416,0,306.648,0,226.653c0-121.887, 109.354-190.477, 200.308-212.956 C 291.27-8.791, 325.48,32.462, 324.022,80c-1.771,57.75, 27.073,58.496, 47.52,56.459C 391.973,134.408, 512,106.695, 512,198.674 C 512,312.5, 422.072,416, 257.54,416z M 224,384c 17.673,0, 32-14.327, 32-32s-14.327-32-32-32s-32,14.327-32,32S 206.327,384, 224,384z M 80,191.754c-8.973,0-16.246,7.273-16.246,16.246S 71.027,224.246, 80,224.246S 96.246,216.973, 96.246,208S 88.973,191.754, 80,191.754z M 128,256c-17.673,0-32,14.327-32,32s 14.327,32, 32,32s 32-14.327, 32-32S 145.673,256, 128,256z M 256,128c-35.346,0-64,21.49-64,48 s 28.654,48, 64,48c 35.347,0, 64-21.49, 64-48S 291.347,128, 256,128z M 368,256c-26.51,0-48,21.49-48,48s 21.49,48, 48,48s 48-21.49, 48-48 S 394.51,256, 368,256z" />
<glyph unicode="&#x55;" d="M 152,176c0-57.438, 46.562-104, 104-104s 104,46.562, 104,104s-46.562,104-104,104S 152,233.438, 152,176z M 480,352L 368,352 c-8,32-16,64-48,64L 192,416 c-32,0-40-32-48-64L 32,352 c-17.6,0-32-14.4-32-32l0-288 c0-17.6, 14.4-32, 32-32l 448,0 c 17.6,0, 32,14.4, 32,32L 512,320 C 512,337.6, 497.6,352, 480,352z M 256,34c-78.425,0-142,63.574-142,142c0,78.425, 63.575,142, 142,142c 78.426,0, 142-63.575, 142-142 C 398,97.574, 334.427,34, 256,34z M 480,256l-64,0 l0,32 l 64,0 L 480,256 z" />
<glyph unicode="&#xe015;" d="M 489.42,351.874c-5.294,0-10.729-1.861-15.718-5.383L 384,283.184L 384,336 c0,26.4-21.6,48-48,48L 48,384 c-26.4,0-48-21.6-48-48l0-224 c0-26.4, 21.6-48, 48-48l 288,0 c 26.4,0, 48,21.6, 48,48l0,52.815 l 89.701-63.307c 4.989-3.521, 10.424-5.382, 15.717-5.383 c 0.001,0, 0.001,0, 0.003,0c 7.044,0, 13.477,3.248, 17.646,8.911c 3.228,4.385, 4.934,10.027, 4.934,16.318L 512.001,326.645 C 512,343.208, 500.641,351.874, 489.42,351.874z" />
<glyph unicode="&#x56;" d="M 490.594,399.946C 418.778,410.271, 339.428,416, 256.001,416c-83.43,0-162.778-5.729-234.597-16.054 C 7.639,346.083,0,286.571,0,224c0-62.57, 7.639-122.083, 21.404-175.945C 93.223,37.729, 172.572,32, 256.001,32 c 83.427,0, 162.776,5.729, 234.593,16.055C 504.36,101.917, 512,161.43, 512,224C 512,286.571, 504.36,346.083, 490.594,399.946z M 192.001,128L 192.001,320 l 160-96L 192.001,128z" />
<glyph unicode="&#x57;" d="M 480,480 L 512,480 L 512,112 C 512,67.817 461.855,32 400,32 C 338.145,32 288,67.817 288,112 C 288,156.184 338.145,192 400,192 C 431.342,192 459.671,182.8 480,167.98 L 480,352 L 224,295.111 L 224,48 C 224,3.817 173.856-32 112-32 C 50.144-32 0,3.817 0,48 C 0,92.184 50.144,128 112,128 C 143.342,128 171.671,118.8 192,103.98 L 192,416 L 480,480 Z" />
<glyph unicode="&#x22;" d="M 311.413,128.632c-11.055,1.759-11.307,32.157-11.307,32.157s 32.484,32.158, 39.564,75.401 c 19.045,0, 30.809,45.973, 11.761,62.148C 352.226,315.365, 375.911,432, 256,432c-119.911,0-96.225-116.635-95.432-133.662 c-19.047-16.175-7.285-62.148, 11.761-62.148c 7.079-43.243, 39.564-75.401, 39.564-75.401s-0.252-30.398-11.307-32.157 C 164.976,122.966, 32,64.315, 32,0l 224,0 l 224,0 C 480,64.315, 347.024,122.966, 311.413,128.632z" />
<glyph unicode="&#xe01f;" d="M 367.497,77.313c-9.476,1.494-9.692,27.327-9.692,27.327s 27.844,27.328, 33.912,64.076 c 16.326,0, 26.407,39.069, 10.082,52.814c 0.681,14.47, 20.984,113.588-81.799,113.588c-102.782,0-82.479-99.118-81.799-113.588 c-16.327-13.745-6.244-52.814, 10.081-52.814c 6.067-36.748, 33.913-64.076, 33.913-64.076s-0.216-25.833-9.692-27.327 C 241.979,72.497, 128,22.655, 128-32l 192,0 l 192,0 C 512,22.655, 398.021,72.497, 367.497,77.313zM 172.027,68.595c 22.047,13.575, 48.813,26.154, 70.769,33.712c-7.876,11.216-16.647,26.468-22.165,44.531 c-7.703,6.283-13.972,15.266-17.999,26.301c-4.033,11.052-5.561,23.426-4.304,34.842c 0.902,8.196, 3.239,15.833, 6.825,22.544 c-2.175,23.293-3.707,69.017, 26.224,102.366c 11.607,12.933, 26.278,22.23, 43.85,27.843C 272.090,393.114, 255.647,431.119, 192,431.119 c-102.782,0-82.479-99.118-81.799-113.588c-16.327-13.745-6.244-52.814, 10.081-52.814c 6.067-36.748, 33.913-64.076, 33.913-64.076 s-0.216-25.833-9.692-27.327C 113.979,168.497,0,118.655,0,64l 164.798,0 C 167.153,65.537, 169.551,67.070, 172.027,68.595z" />
<glyph unicode="&#x6d;" d="M 448,384L 64,384 c-35.2,0-64-28.8-64-64l0-224 c0-35.2, 28.8-64, 64-64l 384,0 c 35.2,0, 64,28.8, 64,64L 512,320 C 512,355.2, 483.2,384, 448,384z M 64,96c0,70.692, 35.817,128, 80,128c-26.51,0-48,21.49-48,48s 21.49,48, 48,48s 48-21.49, 48-48s-21.49-48-48-48 c 44.183,0, 80-57.308, 80-128L 64,96 z M 448,96L 288,96 l0,32 l 160,0 L 448,96 z M 448,192L 288,192 l0,32 l 160,0 L 448,192 z M 448,288L 288,288 l0,32 l 160,0 L 448,288 z" />
<glyph unicode="&#x70;" d="M 32,256L 80,256L 80,176L 32,176zM 32,352L 80,352L 80,272L 32,272zM 32,160L 80,160L 80,80L 32,80zM 32,64L 80,64L 80-16L 32-16zM 96,480l0-512 l 384,0 L 480,480 L 96,480 z M 288,351.835c 35.255,0, 63.835-28.58, 63.835-63.835s-28.58-63.835-63.835-63.835 c-35.255,0-63.835,28.58-63.835,63.835S 252.745,351.835, 288,351.835z M 384,96L 192,96 l0,32 c0,35.347, 28.654,64, 64,64l0,0 l 64,0 c 35.348,0, 64-28.653, 64-64L 384,96 zM 32,448L 80,448L 80,368L 32,368z" />
<glyph unicode="&#x26;" d="M 128,160c0,0, 29.412,96, 192,96l0-96 l 192,128L 320,416l0-96 C 192,320, 128,240.164, 128,160zM 352,96L 64,96 L 64,288 l 62.938,0 c 5.047,5.959, 10.456,11.667, 16.244,17.090c 21.982,20.595, 48.281,36.326, 78.057,46.91L0,352 l0-320 l 416,0 L 416,166.312 l-64-42.667L 352,96 z" />
<glyph unicode="&#xe257;" d="M 192,224 L 32,224 L 32,288 L 192,288 L 192,352 L 288,256 L 192,160 ZM 512,480 L 512,64 L 320-32 L 320,64 L 128,64 L 128,192 L 160,192 L 160,96 L 320,96 L 320,384 L 448,448 L 160,448 L 160,320 L 128,320 L 128,480 Z" />
<glyph unicode="&#xe258;" d="M 384,160 L 384,224 L 224,224 L 224,288 L 384,288 L 384,352 L 480,256 ZM 352,192 L 352,64 L 192,64 L 192-32 L 0,64 L 0,480 L 352,480 L 352,320 L 320,320 L 320,448 L 64,448 L 192,384 L 192,96 L 320,96 L 320,192 Z" />
<glyph unicode="&#x24;" d="M 464,448 C 490.4,448 512,426.4 512,400 L 512,144 C 512,117.6 490.4,96 464,96 L 281.6,96 L 128-32 L 128,96 L 48,96 C 21.6,96 0,117.6 0,144 L 0,400 C 0,426.4 21.6,448 48,448 L 464,448 Z" />
<glyph unicode="&#x25;" d="M 400,480 C 426.4,480 448,458.4 448,432 L 448,272 C 448,245.6 426.4,224 400,224 L 217.6,224 L 64,96 L 64,224 L 48,224 C 21.6,224 0,245.6 0,272 L 0,432 C 0,458.4 21.6,480 48,480 L 400,480 ZM 528,384 C 554.4,384 576,362.4 576,336 L 576,144 C 576,117.6 554.4,96 528,96 L 448,96 L 448-32 L 294.4,96 L 192,96 L 192,160 L 317.57,160 L 416,72.643 L 416,160 L 512,160 L 512,320 L 480,320 L 480,384 L 528,384 Z" horiz-adv-x="576" />
<glyph unicode="&#x60;" d="M 112.5,256 C 174.356,256 224.5,205.855 224.5,144 C 224.5,82.144 174.356,32 112.5,32 C 50.644,32 0.5,82.144 0.5,144 L 0,160 C 0,283.712 100.288,384 224,384 L 224,320 C 181.263,320 141.083,303.357 110.863,273.137 C 105.046,267.319 99.737,261.129 94.948,254.627 C 100.667,255.527 106.528,256 112.5,256 ZM 400.5,256 C 462.355,256 512.5,205.855 512.5,144 C 512.5,82.144 462.355,32 400.5,32 C 338.645,32 288.5,82.144 288.5,144 L 288,160 C 288,283.712 388.288,384 512,384 L 512,320 C 469.263,320 429.083,303.357 398.863,273.137 C 393.045,267.319 387.736,261.129 382.947,254.627 C 388.667,255.527 394.527,256 400.5,256 Z" />
<glyph unicode="&#x61;" d="M 400,160 C 338.144,160 288,210.145 288,272 C 288,333.856 338.144,384 400,384 C 461.856,384 512,333.856 512,272 L 512.5,256 C 512.5,132.288 412.212,32 288.5,32 L 288.5,96 C 331.237,96 371.417,112.643 401.637,142.863 C 407.454,148.681 412.763,154.871 417.552,161.373 C 411.833,160.473 405.972,160 400,160 ZM 112,160 C 50.145,160 0,210.145 0,272 C 0,333.856 50.145,384 112,384 C 173.855,384 224,333.856 224,272 L 224.5,256 C 224.5,132.288 124.212,32 0.5,32 L 0.5,96 C 43.237,96 83.417,112.643 113.637,142.863 C 119.455,148.681 124.764,154.871 129.553,161.373 C 123.833,160.473 117.973,160 112,160 Z" />
<glyph unicode="&#xe259;" d="M 464,480L 48,480 C 21.6,480,0,458.4,0,432l0-288 c0-26.4, 21.6-48, 48-48l 80,0 l0-128 l 153.6,128L 464,96 c 26.4,0, 48,21.6, 48,48L 512,432 C 512,458.4, 490.4,480, 464,480z M 224,344.615c-29.821-6.85-55.189-28.007-70.488-56.941C 155.646,287.889, 157.81,288, 160,288 c 35.346,0, 64-28.654, 64-64c0-35.346-28.654-64-64-64s-64,28.654-64,64c0,43.612, 15.198,84.729, 42.795,115.775 C 162.042,365.927, 191.74,382.388, 224,387.379L 224,344.615 z M 416,344.615c-29.82-6.85-55.189-28.007-70.488-56.941 C 347.646,287.889, 349.81,288, 352,288c 35.346,0, 64-28.654, 64-64c0-35.346-28.654-64-64-64s-64,28.654-64,64 c0,43.612, 15.198,84.729, 42.795,115.775C 354.041,365.927, 383.74,382.388, 416,387.379L 416,344.615 z" />
<glyph unicode="&#xe260;" d="M 457.153,376.352 C 510.42,346.068 512,313.643 512.002,291.003 L 512.002,287.606 C 512.002,282.424 507.533,278.188 502.074,278.188 L 381.928,278.188 C 376.469,278.188 372,282.424 372,287.606 L 372,299.059 C 372,327.664 344.645,332.234 329.551,334.664 C 314.455,337.090 276.934,339.441 256.071,339.441 C 256.045,339.441 256.025,339.441 256.005,339.441 C 255.976,339.441 255.956,339.441 255.928,339.441 C 235.066,339.441 197.541,337.091 182.448,334.664 C 167.355,332.237 139.999,327.666 139.999,299.059 L 139.999,287.606 C 139.999,282.424 135.53,278.188 130.073,278.188 L 9.927,278.188 C 4.47,278.188 0.001,282.424 0.001,287.606 L 0.001,291.003 C 0.001,313.643 1.581,346.068 54.848,376.352 C 118.198,412.362 208.777,416 255.928,416 C 255.956,415.975 255.976,415.945 256.005,415.922 C 256.023,415.944 256.044,415.976 256.071,416 C 303.223,416 393.803,412.366 457.153,376.352 ZM 256.001,288c-28.374,0-87.443-2.126-117.456-38.519C 108.523,213.098, 33.455,32, 100.398,32c 66.956,0, 125.458,0, 155.606,0 c 30.137,0, 88.648,0, 155.595,0c 66.945,0-8.125,181.098-38.137,217.481C 343.444,285.874, 284.362,288, 256.001,288z M 256,96 c-35.346,0-64,28.653-64,64s 28.654,64, 64,64c 35.347,0, 64-28.653, 64-64S 291.347,96, 256,96z" />
<glyph unicode="&#xe261;" d="M 352,160c-32-32-32-64-64-64s-64,32-96,64s-64,64-64,96s 32,32, 64,64S 128,448, 96,448S0,352,0,352c0-64, 65.75-193.75, 128-256 s 192-128, 256-128c0,0, 96,64, 96,96S 384,192, 352,160z" />
<glyph unicode="&#x4d;" d="M 325.608,214.818L 512,86.264L 512,382.211 zM0,382.211L0,86.264L 186.388,214.836 zM 256,152.309L 211.499,192.264L0,64L 512,64L 300.495,192.264 zM 496.64,384L 15.36,384L 256,203.074 z" />
<glyph unicode="&#x4e;" d="M 325.607,118.95L 512-9.605L 512,286.343 zM0,286.343L0-9.605L 186.388,118.968 zM 256,56.44L 211.499,96.395L0-31.868L 512-31.868L 300.494,96.395 zM 15.359,288L 496.64,288L 255.999,468.926 z" />
<glyph unicode="&#x4f;" d="M 352,384L 160,384 L0,192l0-80 l0-48 c0-17.673, 14.327-32, 32-32l 448,0 c 17.674,0, 32,14.327, 32,32l0,48 l0,80 L 352,384z M 384,192l-64-64L 192,128 l-64,64L 41.655,192 l 133.333,160l 162.024,0 l 133.333-160L 384,192 z" />
<glyph unicode="&#x50;" d="M 352,384L 160,384 L0,192l0-128 c0-17.673, 14.327-32, 32-32l 448,0 c 17.674,0, 32,14.327, 32,32L 512,192 L 352,384z M 320,128L 192,128 l-32,32l 192,0 L 320,128z M 41.655,192l 133.333,160l 162.024,0 l 133.333-160L 41.655,192 zM 142.482,288L 369.518,288L 342.851,320L 169.148,320 zM 89.149,224L 422.852,224L 396.185,256L 115.815,256 z" />
<glyph unicode="&#xe020;" d="M 480,352L 352,352 L 352,384 c0,17.6-14.4,32-32,32L 192,416 c-17.602,0-32-14.4-32-32l0-32 L 32,352 c-17.6,0-32-14.4-32-32l0-288 c0-17.601, 14.398-32, 32-32l 448,0 c 17.6,0, 32,14.399, 32,32L 512,320 C 512,337.6, 497.6,352, 480,352z M 192,383.942 c 0.017,0.020, 0.037,0.041, 0.057,0.058l 127.886,0 c 0.021-0.017, 0.041-0.038, 0.059-0.058L 320.002,352 L 192,352 L 192,383.942 z M 480,224l-64,0 l0-48 c0-8.801-7.2-16-16-16l-32,0 c-8.802,0-16,7.199-16,16l0,48 L 160,224 l0-48 c0-8.801-7.2-16-16-16l-32,0 c-8.801,0-16,7.199-16,16l0,48 L 32,224 l0,32 l 448,0 L 480,224 z" />
<glyph unicode="&#xe262;" d="M 272,480L0,208l 240-240l 272,272L 512,480 L 272,480 z M 400,320c-26.51,0-48,21.49-48,48s 21.49,48, 48,48s 48-21.49, 48-48S 426.51,320, 400,320z" />
<glyph unicode="&#xe263;" d="M 448,416 L 298.51,416 L 90.51,208 L 240,58.51 L 448,266.51 L 448,416 Z M 512,480 L 512,480 L 512,240 L 240-32 L 0,208 L 272,480 L 512,480 ZM 320,336A48,48 3060 1 0 416,336A48,48 3060 1 0 320,336z" />
<glyph unicode="&#xe264;" d="M 496,448L 384,448 c-26.4,0-63.273-15.273-81.941-33.941L 113.941,225.941c-18.667-18.667-18.667-49.214,0-67.882l 140.118-140.117 c 18.667-18.668, 49.214-18.668, 67.882,0l 188.117,188.117C 528.727,224.727, 544,261.6, 544,288L 544,400 C 544,426.4, 522.4,448, 496,448z M 432,288 c-26.51,0-48,21.49-48,48s 21.49,48, 48,48s 48-21.49, 48-48S 458.51,288, 432,288zM 43.313,180.687 L 214.502,9.498 C 196.37-0.082 173.271,2.729 158.059,17.942 L 17.941,158.059 C -0.726,176.727 -0.726,207.274 17.941,225.941 L 206.059,414.059 C 224.727,432.727 261.6,448 288,448 L 43.313,203.314 C 37.091,197.091 37.091,186.91 43.313,180.687 Z" horiz-adv-x="544" />
<glyph unicode="&#xe265;" d="M 480,384 L 384,384 C 381.158,384 373.652,382.643 364.621,378.902 C 355.59,375.161 349.322,370.813 347.312,368.804 L 170.509,192 L 288,74.51 L 464.803,251.314 C 466.813,253.323 471.161,259.591 474.901,268.622 C 478.643,277.652 480,285.158 480,288 L 480,384 Z M 496,448 L 496,448 C 522.4,448 544,426.4 544,400 L 544,288 C 544,261.6 528.727,224.727 510.058,206.059 L 321.941,17.942 C 312.607,8.608 300.304,3.941 288,3.941 C 275.696,3.941 263.392,8.608 254.059,17.942 L 113.941,158.059 C 95.274,176.727 95.274,207.274 113.941,225.941 L 302.059,414.059 C 320.727,432.727 357.6,448 384,448 L 496,448 ZM 43.313,180.687 L 214.502,9.498 C 196.37-0.082 173.271,2.729 158.059,17.942 L 17.941,158.059 C -0.726,176.727 -0.726,207.274 17.941,225.941 L 206.059,414.059 C 224.727,432.727 261.6,448 288,448 L 43.313,203.314 C 37.091,197.091 37.091,186.91 43.313,180.687 ZM 384,320A32,32 3060 1 0 448,320A32,32 3060 1 0 384,320z" horiz-adv-x="544" />
<glyph unicode="&#x38;" d="M 466.895,174.875c-26.863,46.527-10.708,106.152, 36.076,133.244l-50.313,87.146c-14.375-8.427-31.088-13.259-48.923-13.259 c-53.768,0-97.354,43.873-97.354,97.995L 205.752,480.001 c 0.133-16.705-4.037-33.641-12.979-49.126 c-26.862-46.528-86.578-62.351-133.431-35.379L 9.030,308.35c 14.485-8.236, 27.025-20.294, 35.943-35.739 c 26.819-46.454, 10.756-105.96-35.854-133.112l 50.313-87.146c 14.325,8.348, 30.958,13.127, 48.7,13.127 c 53.598,0, 97.072-43.596, 97.35-97.479l 100.627,0 c-0.043,16.537, 4.136,33.285, 12.983,48.609 c 26.818,46.453, 86.388,62.297, 133.207,35.506l 50.313,87.145C 488.222,147.494, 475.766,159.51, 466.895,174.875z M 256,120.334 c-57.254,0-103.668,46.412-103.668,103.667c0,57.254, 46.413,103.667, 103.668,103.667c 57.254,0, 103.666-46.413, 103.666-103.667 C 359.665,166.746, 313.254,120.334, 256,120.334z" />
<glyph unicode="&#x37;" d="M 181.861,118.974l 20.649,28.908l-22.627,22.628l-28.909-20.648c-5.361,2.997-11.102,5.387-17.133,7.096L 128,192L 96,192 l-5.84-35.043c-6.031-1.709-11.772-4.099-17.133-7.096L 44.118,170.51L 21.49,147.882l 20.649-28.908 c-2.997-5.36-5.387-11.103-7.096-17.133L0,96l0-32 l 35.043-5.841c 1.709-6.030, 4.099-11.772, 7.096-17.133L 21.49,12.118l 22.627-22.628 l 28.909,20.648c 5.361-2.997, 11.102-5.387, 17.133-7.096L 96-32l 32,0 l 5.84,35.043c 6.031,1.709, 11.772,4.099, 17.133,7.096l 28.909-20.648 l 22.627,22.628l-20.649,28.908c 2.997,5.36, 5.387,11.103, 7.096,17.133L 224,64l0,32 l-35.043,5.841 C 187.248,107.871, 184.858,113.613, 181.861,118.974z M 112,48c-17.674,0-32,14.327-32,32s 14.326,32, 32,32s 32-14.327, 32-32 S 129.674,48, 112,48zM 512,288l0,32 l-33.691,6.125c-0.621,4.023-1.416,7.989-2.362,11.895l 28.779,18.55L 492.48,386.134l-33.472-7.234 c-2.107,3.455-4.363,6.81-6.746,10.065l 19.503,28.171l-22.628,22.627l-28.171-19.503c-3.256,2.383-6.61,4.638-10.065,6.747 l 7.234,33.472L 388.571,472.726l-18.55-28.779c-3.906,0.946-7.872,1.741-11.895,2.362L 352,480l-32,0 l-6.126-33.691 c-4.023-0.621-7.988-1.416-11.895-2.362L 283.43,472.726L 253.866,460.48l 7.234-33.472c-3.455-2.108-6.81-4.364-10.065-6.747 l-28.171,19.503l-22.627-22.627l 19.503-28.171c-2.383-3.255-4.639-6.61-6.747-10.065l-33.472,7.234l-12.246-29.564l 28.779-18.55 c-0.946-3.906-1.741-7.871-2.362-11.895L 160,320l0-32 l 33.691-6.125c 0.621-4.023, 1.416-7.989, 2.362-11.895l-28.779-18.55 l 12.246-29.564l 33.472,7.234c 2.108-3.455, 4.364-6.809, 6.747-10.065l-19.503-28.171l 22.627-22.628l 28.171,19.503 c 3.255-2.383, 6.61-4.638, 10.065-6.746l-7.234-33.472l 29.564-12.246l 18.551,28.779c 3.905-0.946, 7.871-1.741, 11.894-2.362L 320,128l 32,0 l 6.126,33.691c 4.022,0.621, 7.988,1.416, 11.895,2.362l 18.55-28.779l 29.564,12.246l-7.234,33.472 c 3.455,2.108, 6.81,4.363, 10.065,6.746l 28.171-19.503l 22.628,22.628l-19.503,28.171c 2.383,3.256, 4.638,6.61, 6.746,10.065 l 33.472-7.234l 12.246,29.565l-28.779,18.55c 0.946,3.906, 1.741,7.871, 2.362,11.895L 512,288z M 336,234.4 c-38.439,0-69.6,31.161-69.6,69.6c0,38.439, 31.16,69.6, 69.6,69.6s 69.6-31.161, 69.6-69.6C 405.6,265.561, 374.44,234.4, 336,234.4z" />
<glyph unicode="&#x36;" d="M 507.256,84.744L 308.744,283.256c-11.030,11.031-38.41,2.154-65.372-19.758L 96,410.87L 80,448L 28.768,480L0,451.232L 32,400 l 37.13-16l 147.373-147.372c-21.913-26.963-30.79-54.342-19.76-65.372c 0.003-0.003, 0.006-0.005, 0.009-0.008l 198.503-198.504 c 12.976-12.975, 48.565,1.579, 79.494,32.508C 505.677,36.18, 520.23,71.771, 507.256,84.744z M 445.435,34.565 c-3.71-3.71-8.572-5.565-13.435-5.565s-9.725,1.855-13.435,5.565l-160,160c-7.421,7.42-7.421,19.449,0,26.869 c 7.42,7.42, 19.449,7.42, 26.869,0l 160-160C 452.855,54.015, 452.855,41.985, 445.435,34.565z" />
<glyph unicode="&#x3a;" d="M 507.882,411.883L 448,352l-64,64l 59.882,59.883C 435.057,478.557, 425.698,480, 416,480c-53.021,0-96-42.98-96-96 c0-9.697, 1.442-19.057, 4.116-27.882L 123.882,155.883C 115.057,158.557, 105.698,160, 96,160c-53.021,0-96-42.98-96-96 c0-9.697, 1.442-19.058, 4.117-27.882L 64,96l 64-64l-59.883-59.882C 76.943-30.556, 86.302-32, 96-32c 53.020,0, 96,42.981, 96,96 c0,9.698-1.444,19.059-4.118,27.883l 200.234,200.235C 396.943,289.444, 406.302,288, 416,288c 53.020,0, 96,42.981, 96,96 C 512,393.698, 510.556,403.058, 507.882,411.883z" />
<glyph unicode="&#x39;" d="M 144,320L 80,320 c-8.8,0-16-7.2-16-16l0-32 c0-8.8, 7.2-16, 16-16l 64,0 c 8.8,0, 16,7.2, 16,16l0,32 C 160,312.8, 152.8,320, 144,320zM 96,416L 128,416L 128,336L 96,336zM 96,240L 128,240L 128,32L 96,32zM 272,192l-64,0 c-8.8,0-16-7.2-16-16l0-32 c0-8.8, 7.2-16, 16-16l 64,0 c 8.801,0, 16,7.2, 16,16l0,32 C 288,184.8, 280.801,192, 272,192zM 224.001,416L 256.001,416L 256.001,208L 224.001,208zM 224.001,112L 256.001,112L 256.001,32L 224.001,32zM 400,288l-64,0 c-8.799,0-16-7.2-16-16l0-32 c0-8.8, 7.201-16, 16-16l 64,0 c 8.801,0, 16,7.2, 16,16l0,32 C 416,280.8, 408.801,288, 400,288zM 352,416L 384,416L 384,304L 352,304zM 352,208L 384,208L 384,32L 352,32zM 440,480L 40,480 C 17.944,480,0,462.056,0,440l0-432 c0-22.056, 17.944-40, 40-40l 400,0 c 22.056,0, 40,17.944, 40,40L 480,440 C 480,462.056, 462.056,480, 440,480z M 448,8c0-4.4-3.6-8-8-8L 40,0 c-4.4,0-8,3.6-8,8L 32,440 c0,4.4, 3.6,8, 8,8l 400,0 c 4.4,0, 8-3.6, 8-8L 448,8 z" />
<glyph unicode="&#x78;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,32 c-106.039,0-192,85.961-192,192c0,106.039, 85.961,192, 192,192c 106.039,0, 192-85.961, 192-192C 448,117.961, 362.039,32, 256,32zM 224,352A32,32 11340 1 0 288,352A32,32 11340 1 0 224,352zM 320,320A32,32 11340 1 0 384,320A32,32 11340 1 0 320,320zM 128,320A32,32 11340 1 0 192,320A32,32 11340 1 0 128,320zM 224,128L 224,96L 288,96L 288,128L 256,288 z" />
<glyph unicode="&#xe266;" d="M 320,406.706l0-67.979 c 18.103-7.902, 34.75-19.204, 49.137-33.59C 399.358,274.917, 416,234.737, 416,192 s-16.643-82.917-46.863-113.137C 338.917,48.643, 298.738,32, 256,32s-82.917,16.643-113.137,46.863 C 112.643,109.083, 96,149.263, 96,192s 16.643,82.917, 46.863,113.137c 14.387,14.387, 31.034,25.689, 49.137,33.591L 192,406.706 C 99.476,379.166, 32,293.47, 32,192c0-123.712, 100.289-224, 224-224c 123.712,0, 224,100.288, 224,224 C 480,293.47, 412.525,379.166, 320,406.706zM 224,480L 288,480L 288,224L 224,224z" />
<glyph unicode="&#x54;" d="M 256,480C 114.615,480,0,444.183,0,400l0-48 l 192-192l0-160 c0-17.673, 28.653-32, 64-32c 35.346,0, 64,14.327, 64,32L 320,160 l 192,192L 512,400 C 512,444.183, 397.385,480, 256,480z M 47.192,410.588c 11.972,6.829, 28.791,13.31, 48.639,18.744C 139.803,441.37, 196.685,448, 256,448 c 59.314,0, 116.197-6.63, 160.169-18.668c 19.848-5.434, 36.667-11.915, 48.64-18.744c 7.896-4.503, 12.162-8.312, 14.148-10.588 c-1.986-2.276-6.253-6.084-14.148-10.588c-11.973-6.829-28.792-13.31-48.64-18.744C 372.198,358.63, 315.315,352, 256,352 c-59.315,0-116.197,6.63-160.169,18.668c-19.848,5.434-36.667,11.915-48.639,18.744C 39.296,393.916, 35.030,397.724, 33.043,400 C 35.030,402.276, 39.296,406.084, 47.192,410.588z" />
<glyph unicode="&#x4c;" d="M 64,0c0-17.673, 14.327-32, 32-32l 320,0 c 17.674,0, 32,14.327, 32,32L 448,352 L 64,352 L 64,0 z M 320,288l 64,0 l0-256 l-64,0 L 320,288 z M 224,288l 64,0 l0-256 l-64,0 L 224,288 z M 128,288l 64,0 l0-256 l-64,0 L 128,288 zM 448,448L 320,448 L 320,480 L 192,480 l0-32 L 64,448 C 28.654,448,0,419.346,0,384l 512,0 C 512,419.346, 483.347,448, 448,448z" />
<glyph unicode="&#x23;" d="M 416,256l-32,0 l0,96 C 384,422.692, 326.692,480, 256,480c-70.692,0-128-57.308-128-128l0-96 L 96,256 c-17.6,0-32-14.4-32-32l0-224 c0-17.6, 14.4-32, 32-32l 320,0 c 17.6,0, 32,14.4, 32,32L 448,224 C 448,241.6, 433.6,256, 416,256z M 256,64c-17.673,0-32,14.327-32,32 s 14.327,32, 32,32s 32-14.327, 32-32S 273.673,64, 256,64z M 320,256L 192,256 l0,96 c0,35.29, 28.71,64, 64,64s 64-28.71, 64-64L 320,256 z" />
<glyph unicode="&#xe267;" d="M 256,64c-17.673,0-32,14.326-32,32c0,17.673, 14.327,32, 32,32s 32-14.327, 32-32C 288,78.326, 273.673,64, 256,64z M 192,256 l0,96 c0,35.29, 28.71,64, 64,64s 64-28.71, 64-64l0-32 l 64,0 l0,32 C 384,422.692, 326.692,480, 256,480c-70.692,0-128-57.309-128-128l0-96 L 96,256 c-17.601,0-32-14.4-32-32l0-224 c0-17.601, 14.399-32, 32-32l 320,0 c 17.6,0, 32,14.399, 32,32L 448,224 c0,17.6-14.4,32-32,32L 192,256 z" />
<glyph unicode="&#x5f;" d="M 352,480c-88.365,0-160-71.634-160-160c0-10.013, 0.929-19.808, 2.688-29.312L0,96l0-96 c0-17.673, 14.327-32, 32-32 l 32,0 l0,32 l 64,0 l0,64 l 64,0 l0,64 l 64,0 l 41.521,41.521C 314.526,163.363, 332.869,160, 352,160c 88.365,0, 160,71.634, 160,160S 440.365,480, 352,480z M 399.937,319.937c-26.51,0-48,21.49-48,48s 21.49,48, 48,48s 48-21.49, 48-48S 426.447,319.937, 399.937,319.937z" />
<glyph unicode="&#x46;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 160,224 c0,53.020, 42.98,96, 96,96s 96-42.98, 96-96s-42.98-96-96-96S 160,170.98, 160,224z M 462.99,138.262L 462.99,138.262l-88.71,36.745 C 380.539,190.099, 384,206.645, 384,224s-3.461,33.901-9.72,48.993l 61.063,25.293l 27.647,11.452C 473.944,283.327, 480,254.373, 480,224 C 480,193.627, 473.943,164.673, 462.99,138.262L 462.99,138.262z M 341.739,430.99L 341.739,430.99L 341.739,430.99l-36.745-88.71 C 289.902,348.539, 273.356,352, 256,352s-33.901-3.461-48.993-9.72l-17.23,41.599l-19.515,47.112C 196.673,441.943, 225.628,448, 256,448 C 286.373,448, 315.327,441.943, 341.739,430.99z M 49.010,309.738l 47.112-19.515l 41.599-17.23C 131.462,257.901, 128,241.355, 128,224 s 3.461-33.901, 9.72-48.993l-88.71-36.745C 38.057,164.673, 32,193.627, 32,224C 32,254.373, 38.057,283.327, 49.010,309.738z M 170.262,17.010l 11.452,27.647l 25.293,61.063C 222.099,99.461, 238.645,96, 256,96s 33.901,3.461, 48.993,9.72l 36.745-88.71l0,0l0,0 C 315.327,6.058, 286.373,0, 256,0C 225.628,0, 196.673,6.057, 170.262,17.010z" />
<glyph unicode="&#x62;" d="M 256,480C 114.614,480,0,444.184,0,400l0-64 c0-44.183, 114.611-80, 256-80c 141.385,0, 256,35.817, 256,80L 512,400 C 512,444.184, 397.385,480, 256,480 zM 255.193,224C 140.566,224, 43.94,247.543, 11.32,280C 3.705,272.423,0,264.361,0,256l0-64 c0-44.184, 114.611-80, 256-80 c 141.385,0, 256,35.816, 256,80l0,64 c0,8.361-4.516,16.423-12.131,24C 467.25,247.543, 369.82,224, 255.193,224zM 255.193,80C 140.566,80, 43.94,103.544, 11.32,136C 3.705,128.424,0,120.361,0,112l0-64 c0-44.183, 114.611-80, 256-80 c 141.385,0, 256,35.817, 256,80l0,64 c0,8.361-4.516,16.424-12.131,24C 467.25,103.544, 369.82,80, 255.193,80z" />
<glyph unicode="&#xe268;" d="M 390.979-32c-27.208,0.001-61.186,16.608-75.809,53.702c-2.034,4.84-4.271,10.714-6.859,17.509 c-8.285,21.749-20.806,54.616-33.892,68.23c-4.79,4.984-8.495,8.599-11.473,11.504c-2.673,2.607-4.921,4.801-6.946,7.019 c-2.025-2.219-4.273-4.412-6.948-7.022c-2.976-2.904-6.68-6.519-11.468-11.5c-13.086-13.616-25.608-46.488-33.895-68.239 c-2.586-6.791-4.823-12.661-6.856-17.499C 182.208-15.391, 148.231-32, 121.025-32c-5.303,0-10.138,0.646-14.373,1.918 c-26.772,8.046-43.012,37.939-40.411,74.386l 0.372,4.206c 3.287,29.404, 21.199,58.458, 50.435,81.806 c 25.344,20.238, 55.31,32.812, 78.204,32.812c 4.53,0, 8.712-0.494, 12.519-1.472l 15.711,32.209 c-16.148,40.414-39.152,100.774-57.123,153.646c-10.015,29.463-17.448,53.594-22.094,71.721 c-7.352,28.691-6.883,38.393-3.916,44.132L 148.95,480l 107.053-219.465L 363.049,479.999l 8.602-16.635 c 2.967-5.739, 3.438-15.441-3.915-44.132c-4.646-18.126-12.079-42.257-22.093-71.72c-17.97-52.868-40.974-113.229-57.123-153.646 l 15.711-32.209c 3.806,0.978, 7.987,1.472, 12.518,1.472c 22.895,0, 52.861-12.574, 78.206-32.814 c 24.995-19.962, 41.713-44.097, 48.090-69.052l 1.179,0.564l 1.535-17.522c 2.603-36.445-13.635-66.338-40.404-74.386 c-4.235-1.272-9.071-1.918-14.373-1.918C 390.98-32, 390.979-32, 390.979-32z M 346.841,39.052 c 18.936-34.353, 35.854-39.491, 44.263-39.491c 11.447,0, 20.018,9.238, 21.691,18.169c 1.097,5.871, 1.296,11.914, 0.592,17.961 c-2.837,24.156-19.338,44.898-32.678,58.044c-18.334,18.065-38.889,30.062-52.085,35.3c-1.313,0.457-2.121,0.526-2.489,0.526 c-0.255,0-0.354-0.031-0.355-0.031C 321.937,127.034, 317.342,98.010, 346.841,39.052z M 183.13,129.035 c-13.115-5.24-33.545-17.236-51.764-35.301c-13.26-13.145-29.656-33.888-32.475-58.052c-0.704-6.030-0.506-12.069, 0.589-17.953 c 1.661-8.93, 10.179-18.169, 21.556-18.169c 8.356,0, 25.17,5.139, 43.991,39.49c 29.312,58.938, 24.764,87.944, 20.903,90.493 c0-0.001-0.001-0.001-0.004-0.001c-0.020,0-0.125,0.018-0.32,0.018C 185.239,129.561, 184.438,129.492, 183.13,129.035z" />
<glyph unicode="&#x6a;" d="M 416,160L 384,128L 320,288L 256,96L 160,448L 96,128L0,128L0,96L 122.235,96L 164.794,308.803L 225.128,87.58L 252.937-14.385L 322.734,195.005L 354.288,116.115L 372.313,71.057L 429.256,128L 512,128L 512,160 z" />
<glyph unicode="&#x6b;" d="M 258.181,254.091l 94.386,29.34L 256,351.723L 256,480 L 152.532,405.466L 32,448l 42.533-120.533L0,224l 128,0 l 68.567-96.568l 29.341,94.387 L 448-32l 64,64L 258.181,254.091z M 202.327,277.672l-19.579-62.986l-38.084,53.010L 78.712,267.696 l 39.447,52.861L 96.979,383.021l 62.464-21.182 l 52.862,39.447l0-65.952 l 53.008-38.084L 202.327,277.672z" />
<glyph unicode="&#x3c;" d="M 256,384C 144.341,384, 47.559,318.979,0,224c 47.559-94.979, 144.341-160, 256-160c 111.657,0, 208.439,65.021, 256,160 C 464.442,318.979, 367.657,384, 256,384z M 382.225,299.148c 30.081-19.187, 55.571-44.887, 74.717-75.148 c-19.146-30.261-44.637-55.961-74.718-75.149C 344.427,124.743, 300.779,112, 256,112c-44.78,0-88.428,12.743-126.225,36.852 C 99.695,168.038, 74.205,193.738, 55.058,224c 19.146,30.262, 44.637,55.962, 74.717,75.148c 1.959,1.25, 3.938,2.461, 5.929,3.65 C 130.725,289.134, 128,274.387, 128,259c0-70.692, 57.308-128, 128-128s 128,57.308, 128,128c0,15.387-2.725,30.134-7.704,43.799 C 378.286,301.61, 380.265,300.398, 382.225,299.148z M 256,275c0-26.51-21.49-48-48-48s-48,21.49-48,48s 21.49,48, 48,48 S 256,301.51, 256,275z" />
<glyph unicode="&#xe269;" d="M 419.661,331.792 C 458.483,304.277 490.346,267.246 512,224 C 464.439,129.021 367.657,64 256,64 C 224.717,64 194.604,69.106 166.411,78.542 L 205.389,117.52 C 221.918,113.87 238.875,112 256,112 C 300.779,112 344.427,124.743 382.223,148.852 C 412.304,168.040 437.795,193.74 456.941,224.001 C 438.415,253.284 413.934,278.276 385.116,297.248 L 419.661,331.792 ZM 256,131 C 244.638,131 233.624,132.488 223.136,135.267 L 379.729,291.859 C 382.51,281.373 384,270.362 384,259 C 384,188.308 326.692,131 256,131 ZM 480,480l-26.869,0 L 343.325,370.194C 315.787,379.156, 286.448,384, 256,384C 144.341,384, 47.559,318.979,0,224 c 21.329-42.596, 52.564-79.154, 90.597-106.534L0,26.869L0,0 l 26.869,0 L 480,453.131L 480,480 z M 208,323c 24.022,0, 43.923-17.647, 47.446-40.685 l-54.762-54.762C 177.647,231.077, 160,250.978, 160,275C 160,301.51, 181.49,323, 208,323z M 55.058,224 c 19.146,30.262, 44.637,55.962, 74.717,75.148c 1.959,1.25, 3.938,2.461, 5.929,3.65C 130.725,289.134, 128,274.387, 128,259 c0-29.262, 9.825-56.224, 26.349-77.781l-29.275-29.275C 97.038,170.765, 73.197,195.33, 55.058,224z" />
<glyph unicode="&#x6e;" d="M 329.372,105.372L 224,210.745L 224,352L 288,352L 288,237.255L 374.628,150.628 zM 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,32 c-106.039,0-192,85.961-192,192c0,106.039, 85.961,192, 192,192c 106.039,0, 192-85.961, 192-192C 448,117.961, 362.039,32, 256,32z" />
<glyph unicode="&#x6f;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,16 c-114.875,0-208,93.125-208,208S 141.125,432, 256,432s 208-93.125, 208-208S 370.875,16, 256,16zM 304,272l-144,80l-32,0 l0-32 l 80-144l 144-80l 32,0 l0,32 L 304,272z M 256,192c-17.673,0-32,14.327-32,32c0,17.673, 14.327,32, 32,32 c 17.673,0, 32-14.327, 32-32C 288,206.327, 273.673,192, 256,192z" />
<glyph unicode="&#xe01b;" d="M 224,96A32,32 13140 1 0 288,96A32,32 13140 1 0 224,96zM 256,416c-96.026,0-182.161-42.307-240.815-109.286l 24.081-21.071C 92.055,345.923, 169.577,384, 256,384 c 86.423,0, 163.945-38.077, 216.734-98.357l 24.081,21.071C 438.161,373.693, 352.027,416, 256,416zM 256,320c-67.218,0-127.513-29.615-168.571-76.5l 24.082-21.071C 146.703,262.616, 198.385,288, 256,288 c 57.616,0, 109.297-25.384, 144.489-65.571l 24.082,21.071C 383.513,290.385, 323.219,320, 256,320zM 256,224c-38.41,0-72.865-16.923-96.326-43.715l 24.082-21.071C 201.352,179.308, 227.192,192, 256,192 c 28.808,0, 54.648-12.692, 72.245-32.786l 24.081,21.071C 328.865,207.077, 294.41,224, 256,224z" />
<glyph unicode="&#xe271;" d="M 448,416l0-416 L 112,0 c-26.511,0-48,21.49-48,48c0,26.509, 21.489,48, 48,48l 304,0 L 416,480 L 96,480 C 60.801,480, 32,451.2, 32,416l0-384 c0-35.2, 28.801-64, 64-64l 384,0 L 480,416 L 448,416 zM 128,64L 416,64L 416,32L 128,32z" />
<glyph unicode="&#x79;" d="M 192,480L0,224L 192,224L 64-32L 512,288L 256,288L 448,480 z" />
<glyph unicode="&#xe013;" d="M 128,448L 384,448L 384,384L 128,384zM 480,352L 32,352 C 14.4,352,0,337.6,0,320l0-160 c0-17.6, 14.398-32, 32-32l 96,0 l0-128 l 256,0 L 384,128 l 96,0 c 17.6,0, 32,14.4, 32,32L 512,320 C 512,337.6, 497.6,352, 480,352z M 352,32L 160,32 L 160,192 l 192,0 L 352,32 z M 487.2,304c0-12.813-10.387-23.2-23.199-23.2 c-12.813,0-23.201,10.387-23.201,23.2s 10.388,23.2, 23.201,23.2C 476.814,327.2, 487.2,316.813, 487.2,304z" />
<glyph unicode="&#x71;" d="M 426.67,480L 85.343,480 C 38.405,480,0,441.594,0,394.656l0-341.314 C0,6.375, 38.406-32, 85.344-32L 426.67-32 c 46.938,0, 85.33,38.374, 85.33,85.342L 512,394.656 C 512,441.594, 473.608,480, 426.67,480z M 139.472,64.376C 115.487,64.376, 96,83.722, 96,107.69 c0,23.842, 19.486,43.406, 43.472,43.406c 24.079,0, 43.53-19.564, 43.53-43.406C 183.001,83.722, 163.55,64.376, 139.472,64.376z M 248.734,64.002c0,40.905-15.904,79.409-44.73,108.222c-28.857,28.875-67.188,44.813-107.952,44.813L 96.052,279.63 c 118.826,0, 215.563-96.721, 215.563-215.627L 248.734,64.002L 248.734,64.002z M 359.814,64.002 c0,145.531-118.329,263.97-263.688,263.97L 96.126,390.596 c 180.001,0, 326.473-146.562, 326.473-326.596L 359.814,64.002L 359.814,64.002z" />
<glyph unicode="&#x43;" d="M 160,288L 224,288L 224,224L 160,224zM 256,288L 320,288L 320,224L 256,224zM 352,288L 416,288L 416,224L 352,224zM 64,96L 128,96L 128,32L 64,32zM 160,96L 224,96L 224,32L 160,32zM 256,96L 320,96L 320,32L 256,32zM 160,192L 224,192L 224,128L 160,128zM 256,192L 320,192L 320,128L 256,128zM 352,192L 416,192L 416,128L 352,128zM 64,192L 128,192L 128,128L 64,128zM 416,480l0-32 l-64,0 L 352,480 L 128,480 l0-32 L 64,448 L 64,480 L0,480 l0-512 l 480,0 L 480,480 L 416,480 z M 448,0L 32,0 L 32,352 l 416,0 L 448,0 z" />
<glyph unicode="&#x44;" d="M 64,320L 96,320L 96,288L 64,288zM 128,320L 160,320L 160,288L 128,288zM 192,320L 224,320L 224,288L 192,288zM 256,320L 288,320L 288,288L 256,288zM 320,320L 352,320L 352,288L 320,288zM 384,320L 416,320L 416,288L 384,288zM 64,256L 96,256L 96,224L 64,224zM 128,256L 160,256L 160,224L 128,224zM 192,256L 224,256L 224,224L 192,224zM 256,256L 288,256L 288,224L 256,224zM 320,256L 352,256L 352,224L 320,224zM 384,256L 416,256L 416,224L 384,224zM 64,192L 96,192L 96,160L 64,160zM 128,192L 160,192L 160,160L 128,160zM 192,192L 224,192L 224,160L 192,160zM 256,192L 288,192L 288,160L 256,160zM 320,192L 352,192L 352,160L 320,160zM 384,192L 416,192L 416,160L 384,160zM 64,128L 96,128L 96,96L 64,96zM 128,128L 160,128L 160,96L 128,96zM 192,128L 224,128L 224,96L 192,96zM 256,128L 288,128L 288,96L 256,96zM 320,128L 352,128L 352,96L 320,96zM 384,128L 416,128L 416,96L 384,96zM 64,64L 96,64L 96,32L 64,32zM 128,64L 160,64L 160,32L 128,32zM 192,64L 224,64L 224,32L 192,32zM 256,64L 288,64L 288,32L 256,32zM 320,64L 352,64L 352,32L 320,32zM 384,64L 416,64L 416,32L 384,32zM 416,448L 416,480 l-64,0 l0-64 l-32,0 L 320,448 L 160,448 l0-32 l-32,0 L 128,480 L 64,480 l0-32 L0,448 l0-480 l 480,0 L 480,448 L 416,448 z M 448,0L 32,0 L 32,352 l 416,0 L 448,0 z" />
<glyph unicode="&#xe273;" d="M 448,416l-48,0 l0-16 c0-17.645-14.355-32-32-32s-32,14.355-32,32L 336,416 L 176,416 l0-16 c0-17.645-14.355-32-32-32s-32,14.355-32,32L 112,416 L 64,416 c-17.6,0-32-14.4-32-32l0-352 c0-17.6, 14.4-32, 32-32l 384,0 c 17.6,0, 32,14.4, 32,32L 480,384 C 480,401.6, 465.6,416, 448,416z M 448,32.058 c-0.017-0.020-0.038-0.041-0.058-0.058L 64.057,32 c-0.020,0.017-0.041,0.038-0.057,0.058L 64,320 l 384,0 L 448,32.058 zM 144,384c 8.836,0, 16,7.164, 16,16L 160,464 c0,8.836-7.164,16-16,16s-16-7.164-16-16l0-64 C 128,391.164, 135.164,384, 144,384zM 368,384c 8.836,0, 16,7.164, 16,16L 384,464 c0,8.836-7.164,16-16,16s-16-7.164-16-16l0-64 C 352,391.164, 359.164,384, 368,384zM 288,288L 128,288L 128,256L 256,256L 256,192L 128,192L 128,160L 256,160L 256,96L 128,96L 128,64L 288,64 zM 352,64L 384,64L 384,288L 320,288L 320,256L 352,256 zM 436-12L 76-12 c-17.6,0-32,10.4-32,28l0-16 c0-17.6, 14.4-32, 32-32l 360,0 c 17.6,0, 32,14.4, 32,32l0,16 C 468-1.6, 453.6-12, 436-12z" />
<glyph unicode="&#x77;" d="M 224,192L 224,416 C 100.288,416,0,315.712,0,192s 100.288-224, 224-224s 224,100.288, 224,224c0,36.017-8.514,70.042-23.618,100.191 L 224,192zM 456.382,356.191C 419.606,429.599, 343.695,480, 256,480l0-224 L 456.382,356.191z" />
<glyph unicode="&#x76;" d="M0,64L 512,64L 512,0L0,0zM 64,192L 128,192L 128,96L 64,96zM 160,320L 224,320L 224,96L 160,96zM 256,224L 320,224L 320,96L 256,96zM 352,416L 416,416L 416,96L 352,96z" />
<glyph unicode="&#x75;" d="M 496,0L 384,0L 384,16L 368,16L 368,0L 208,0L 208,16L 192,16L 192,0L 80,0L 80,16L 64,16L 64,0L 32,0L 32,144L 48,144L 48,160L 32,160L 32,272L 48,272L 48,288L 32,288L 32,400L 48,400L 48,416L 32,416L 32,480L0,480L0-32L 512-32L 512,16L 496,16 zM 220,284L 212,276L 212,149.941L 220,157.941 zM 204,268L 196,260L 196,133.941L 204,141.941 zM 188,125.941L 188,258L 180,262L 180,128.833L 187.261,125.202 zM 268,332L 260,324L 260,197.941L 268,205.941 zM 236,300L 228,292L 228,165.941L 236,173.941 zM 172,266L 164,270L 164,136.833L 172,132.833 zM 252,316L 244,308L 244,181.941L 252,189.941 zM 124,290L 116,294L 116,160.833L 124,156.833 zM 92,306L 84,310L 84,176.833L 92,172.833 zM 156,274L 148,278L 148,144.833L 156,140.833 zM 108,298L 100,302L 100,168.833L 108,164.833 zM 76,314L 68,318L 68,184.833L 76,180.833 zM 284,348L 276,340L 276,213.941L 284,221.941 zM 140,282L 132,286L 132,152.833L 140,148.833 zM 412,316L 404,308L 404,137.267L 412,149.267 zM 428,332L 420,324L 420,161.267L 428,173.267 zM 444,348L 436,340L 436,185.267L 444,197.267 zM 476,380L 468,372L 468,233.267L 476,245.267 zM 460,364L 452,356L 452,209.267L 460,221.267 zM 508,412L 500,404L 500,281.267L 508,293.267 zM 492,396L 484,388L 484,257.267L 492,269.267 zM 348,312L 340,317.333L 340,162.666L 348,152 zM 332,322.667L 324,328L 324,184L 332,173.333 zM 300,344L 292,349.333L 292,226.667L 300,216 zM 316,333.333L 308,338.667L 308,205.333L 316,194.666 zM 364,301.333L 356,306.667L 356,141.333L 364,130.666 zM 396,300L 388,292L 388,113.268L 396,125.267 zM 380,290.667L 372,296L 372,119.999L 380,109.333 zM 384,64L 288,192L 192,96L 64,160L 64,32L 512,32L 512,256 z" />
<glyph unicode="&#x32;" d="M 512,338.75L 466.747,384L 377.374,294.624L 326.624,345.375L 415.999,434.75L 370.749,480L 281.374,390.625L 224,448L 180.687,404.688L 436.688,148.687L 480,191.999L 422.624,249.375 zM 137.374,105.373c 82.884-82.881, 192.597-18.181, 259.646,37.732L 175.108,365.017 C 119.196,297.969, 54.494,188.256, 137.374,105.373zM 95.999,127.998L 159.996,64L 64-31.996L 0.002,32.001z" />
<glyph unicode="&#x33;" d="M 256,448L 32,352L 256,256L 480,352 zM 32,64L 224-16L 224,208L 32,288 zM 288-16L 480,64L 480,288L 288,208 z" />
<glyph unicode="&#x34;" d="M 479.165,351.875L 394.94,351.875 c-21.715,0.033-43.348,1.503-22.252,38.729c 21.138,37.3, 36.059,89.521-48.802,89.521 c-84.857,0-69.935-52.221-48.797-89.521c 21.096-37.226-0.538-38.694-22.255-38.729l-91.938,0 c-18.060,0-32.835-14.778-32.835-32.834 l0-102.189 c0-21.756, 5.904-43.513-31.393-22.378C 59.372,215.611,0,230.531,0,145.672c0-84.854, 59.37-69.935, 96.67-48.798 c 37.297,21.137, 31.393-0.62, 31.393-22.38l0-73.783 c0-18.062, 14.777-32.835, 32.835-32.835l 91.811,0 c 21.76,0, 43.517,8.706, 22.382,46.004 c-21.137,37.295-36.061,89.519, 48.797,89.519c 84.858,0, 69.938-52.221, 48.8-89.519c-21.135-37.299, 0.623-46.005, 22.381-46.005l 84.096,0 c 18.062,0, 32.837,14.777, 32.837,32.835L 512.002,319.042 C 512.002,337.099, 497.227,351.875, 479.165,351.875z" />
<glyph unicode="&#x72;" d="M 348.916,316.476l-32.476,32.461L 154.035,186.566c-26.907-26.896-26.907-70.524,0-97.422 c 26.902-26.896, 70.53-26.896, 97.437,0l 194.886,194.854c 44.857,44.831, 44.857,117.531,0,162.363 c-44.833,44.852-117.556,44.852-162.391,0L 79.335,241.788l 0.017-0.016c-0.145-0.152-0.306-0.288-0.438-0.423 c-62.551-62.548-62.551-163.928,0-226.453c 62.527-62.528, 163.934-62.528, 226.494,0c 0.137,0.137, 0.258,0.284, 0.41,0.438l 0.016-0.017 l 139.666,139.646l-32.493,32.46L 273.35,47.792l-0.008,0 c-0.148-0.134-0.282-0.285-0.423-0.422 c-44.537-44.529-116.99-44.529-161.538,0c-44.531,44.521-44.531,116.961,0,161.489c 0.152,0.152, 0.302,0.291, 0.444,0.423l-0.023,0.030 l 204.64,204.583c 26.856,26.869, 70.572,26.869, 97.443,0c 26.856-26.867, 26.856-70.574,0-97.42L 218.999,121.625 c-8.968-8.961-23.527-8.961-32.486,0c-8.947,8.943-8.947,23.516,0,32.46L 348.916,316.476z" />
<glyph unicode="&#x74;" d="M 256.003,480c-85.374,0-154.661-68.339-154.661-152.54c0-42.102, 25.089-86.239, 53.788-133.976 c 28.7-47.737, 6.022-100.49, 103.695-99.073c 93.617,1.376, 69.35,44.274, 96.629,92.011c 27.289,47.736, 55.205,98.938, 55.205,141.039 C 410.66,411.662, 341.371,480, 256.003,480zM 191.076,80.777l0-40.615 c 19.95-6.488, 41.896-10.088, 64.927-10.088c 23.029,0, 44.97,3.6, 64.921,10.086l0,37.525 c-11.158-10.273-29.447-13.1-62.1-13.645C 222.605,63.443, 202.953,67.848, 191.076,80.777zM 191.753,14.944c 2.507-13.705, 13.3-46.944, 64.25-46.944c 50.949,0, 61.742,33.239, 64.25,46.944 c-28.826-8.815-41.977-9.291-64.25-9.291C 233.728,5.653, 220.577,6.129, 191.753,14.944z" />
<glyph unicode="&#x73;" d="M 272,480l-48-48l 48-48L 160,256L 48,256 l 88-88L0-12.308L0-32 l 19.692,0 L 200,104l 88-88L 288,128 l 128,112l 48-48l 48,48L 272,480z M 224,208l-32,32 l 112,112l 32-32L 224,208z" />
<glyph unicode="&#x63;" d="M 256,480C 167.634,480, 96,408.366, 96,320c0-160, 160-352, 160-352s 160,192, 160,352C 416,408.366, 344.365,480, 256,480z M 256,224 c-53.020,0-96,42.98-96,96s 42.98,96, 96,96s 96-42.98, 96-96S 309.020,224, 256,224z" />
<glyph unicode="&#xe274;" d="M 131.851,338.143c 2.709-85.392, 23.232-156.27, 61.189-211.080c 17.343-25.043, 38.449-46.778, 62.96-64.873 c 24.511,18.095, 45.618,39.83, 62.959,64.873c 37.957,54.811, 58.48,125.688, 61.189,211.080c-40.225,9.645-79.752,25.45-124.149,49.495 C 211.596,363.589, 172.078,347.788, 131.851,338.143zM 458.873,406.909C 387.436,411.877, 329.919,434.868, 256.002,480C 182.080,434.868, 124.563,411.877, 53.127,406.909 C 33.451,95.568, 202.896-3.16, 256.002-32C 309.105-3.16, 478.55,95.568, 458.873,406.909z M 358.422,99.735 c-35.469-51.219-77.048-80.031-102.421-95.026c-25.374,14.995-66.952,43.807-102.422,95.026 c-49.507,71.489-72.928,164.977-69.753,278.177c 56.394,7.775, 107.891,27.271, 172.175,64.812 c 64.281-37.541, 115.777-57.037, 172.173-64.812C 431.35,264.712, 407.929,171.225, 358.422,99.735z" />
<glyph unicode="&#x35;" d="M 254.059,418.977C 205.881,476.227, 169.369,480, 96,480l0-256 c 128.267,64, 142.636-8.335, 223.506-1.023 C 399.234,230.197, 467.031,291.564, 512,352C 384.644,322.547, 320.54,339.977, 254.059,418.977zM0,480L 64,480L 64-32L0-32z" />
<glyph unicode="&#xe275;" d="M 128,447.5c 19.393-0.786, 33.686-2.681, 46.365-6.903c 19.163-6.381, 35.674-19.009, 55.209-42.224 c 54.165-64.364, 108.925-91.826, 183.107-91.826c 7.729,0, 15.767,0.307, 24.147,0.925c-10.090-11.872-20.705-23.466-31.729-34.059 c-15.453-14.849-30.499-26.521-44.72-34.692c-14.99-8.612-29.547-13.609-43.263-14.851c-1.81-0.164-3.533-0.243-5.271-0.243 c-16.82,0-29.746,7.817-49.442,20.573c-22.574,14.618-50.668,32.812-91.546,32.812c-13.692,0-27.906-2.034-42.859-6.161L 127.998,447.5 M 96,480l0-256 c 30.587,15.262, 54.737,21.011, 74.859,21.011c 61.341,0, 85.367-53.384, 140.988-53.384c 2.648,0, 5.354,0.12, 8.152,0.373 c 79.729,7.221, 147.031,99.564, 192,160c-38.205-8.835-70.726-13.453-99.318-13.453c-66.72,0-112.085,25.129-158.623,80.43 C 205.881,476.227, 169.369,480, 96,480L 96,480zM0,480L 64,480L 64-32L0-32z" />
<glyph unicode="&#xe023;" d="M 96,480L 96-32L 256,128L 416-32L 416,480 z" />
<glyph unicode="&#xe276;" d="M 96,480l0-512 l 160,160l 160-160L 416,480 L 96,480 z M 384,45.255l-128,128l-128-128L 128,448 l 256,0 L 384,45.255 z" />
<glyph unicode="&#xe277;" d="M 376,448c-51.956,0-97.1-29.138-120-71.96C 233.099,418.862, 187.955,448, 136,448C 60.889,448,0,387.11,0,312c0-184, 256-312, 256-312 s 256,128, 256,312C 512,387.11, 451.111,448, 376,448z" />
<glyph unicode="&#xe278;" d="M 256,0l-13.97,6.779C 232.147,11.574,0,126.229,0,300.513C0,381.838, 67.738,448, 151,448c 39.83,0, 77.258-15.237, 105-41.462 C 283.742,432.763, 321.17,448, 361,448c 83.262,0, 151-66.162, 151-147.487c0-174.284-232.147-288.938-242.030-293.733L 256,0z M 151,384 c-47.972,0-87-37.452-87-83.487c0-67.976, 54.123-127.616, 99.526-165.68c 36.25-30.39, 73.062-52.351, 92.474-63.081 c 19.412,10.73, 56.224,32.691, 92.474,63.081C 393.877,172.896, 448,232.537, 448,300.513C 448,346.548, 408.972,384, 361,384 c-32.336,0-61.831-17.070-76.974-44.55L 256,288.59l-28.026,50.86C 212.831,366.93, 183.336,384, 151,384z" />
<glyph unicode="&#x5b;" d="M 464,192 C 500.5,192 480,96 448,96 C 464,96 448,16 416,16 C 416-16 384-32 352-32 C 216.824-32 264.368,1.825 128,16 L 128,272 C 248.461,308.134 368,398.712 368,480 C 394.5,480 464,448 368,288 C 368,288 448,288 464,288 C 512,288 496,192 464,192 ZM 96,272 L 96,16 L 128,16 L 128,0 L 64,0 C 46.4,0 32,21.6 32,48 L 32,240 C 32,266.4 46.4,288 64,288 L 128,288 L 128,272 L 96,272 Z" />
<glyph unicode="&#x5c;" d="M 48,256 C 11.5,256 32,352 64,352 C 48,352 64,432 96,432 C 96,464 128,480 160,480 C 295.176,480 247.632,446.175 384,432 L 384,176 C 263.539,139.866 144,49.288 144-32 C 117.5-32 48,0 144,160 C 144,160 64,160 48,160 C 0,160 16,256 48,256 ZM 416,176 L 416,432 L 384,432 L 384,448 L 448,448 C 465.6,448 480,426.4 480,400 L 480,208 C 480,181.6 465.6,160 448,160 L 384,160 L 384,176 L 416,176 Z" />
<glyph unicode="&#x40;" d="M 512,281.475l-176.89,25.704L 256,467.47l-79.108-160.291L0,281.475l 128-124.769L 97.784-19.47L 256,63.709l 158.216-83.179 l-30.217,176.176L 512,281.475z M 256,103.251l-111.731-58.74l 21.338,124.415l-90.393,88.111l 124.92,18.152L 256,388.387l 55.868-113.198 l 124.918-18.152l-90.394-88.111l 21.339-124.415L 256,103.251z" />
<glyph unicode="&#x41;" d="M 512,281.475l-176.89,25.704L 256,467.47l-79.108-160.291L0,281.475l 128-124.769L 97.784-19.47L 256,63.709l 158.216-83.179 l-30.217,176.176L 512,281.475z M 256,103.251l-0.471-0.248L 256,388.387l 55.868-113.198l 124.918-18.152l-90.394-88.111l 21.339-124.415 L 256,103.251z" />
<glyph unicode="&#x42;" d="M 512,281.475L 335.11,307.179L 256,467.47l-79.108-160.291L0,281.475l 128-124.769L 97.784-19.47L 256,63.709l 158.216-83.179 l-30.217,176.176L 512,281.475z" />
<glyph unicode="&#xe279;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 352,352 c 17.673,0, 32-14.327, 32-32s-14.327-32-32-32s-32,14.327-32,32S 334.327,352, 352,352z M 160,352c 17.673,0, 32-14.327, 32-32 s-14.327-32-32-32s-32,14.327-32,32S 142.327,352, 160,352z M 256,64c-58.255,0-109.232,31.137-137.213,77.672l 41.164,24.698 C 179.538,133.796, 215.222,112, 256,112s 76.462,21.796, 96.049,54.37l 41.164-24.698C 365.232,95.137, 314.255,64, 256,64z" />
<glyph unicode="&#xe280;" d="M 256-32c 141.385,0, 256,114.615, 256,256S 397.385,480, 256,480S0,365.385,0,224S 114.615-32, 256-32z M 256,432 c 114.875,0, 208-93.125, 208-208s-93.125-208-208-208S 48,109.125, 48,224S 141.125,432, 256,432zM 128,320 C 128,337.673 142.327,352 160,352 C 177.673,352 192,337.673 192,320 C 192,302.327 177.673,288 160,288 C 142.327,288 128,302.327 128,320 Z M 320,320 C 320,337.673 334.327,352 352,352 C 369.673,352 384,337.673 384,320 C 384,302.327 369.673,288 352,288 C 334.327,288 320,302.327 320,320 ZM 352.049,166.37 L 393.213,141.672 C 365.232,95.137 314.255,64 256,64 C 197.745,64 146.768,95.137 118.787,141.672 L 159.951,166.37 C 179.538,133.796 215.222,112 256,112 C 296.778,112 332.462,133.796 352.049,166.37 Z" />
<glyph unicode="&#xe281;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 352,352 c 17.673,0, 32-14.327, 32-32s-14.327-32-32-32s-32,14.327-32,32S 334.327,352, 352,352z M 160,352c 17.673,0, 32-14.327, 32-32 s-14.327-32-32-32s-32,14.327-32,32S 142.327,352, 160,352z M 352.049,89.63C 332.462,122.204, 296.777,144, 256,144 c-40.778,0-76.462-21.796-96.049-54.37l-41.164,24.698C 146.767,160.863, 197.745,192, 256,192c 58.254,0, 109.232-31.137, 137.213-77.672 L 352.049,89.63z" />
<glyph unicode="&#xe282;" d="M 256-32c 141.385,0, 256,114.615, 256,256S 397.385,480, 256,480S0,365.385,0,224S 114.615-32, 256-32z M 256,432 c 114.875,0, 208-93.125, 208-208s-93.125-208-208-208S 48,109.125, 48,224S 141.125,432, 256,432zM 128,320 C 128,337.673 142.327,352 160,352 C 177.673,352 192,337.673 192,320 C 192,302.327 177.673,288 160,288 C 142.327,288 128,302.327 128,320 Z M 320,320 C 320,337.673 334.327,352 352,352 C 369.673,352 384,337.673 384,320 C 384,302.327 369.673,288 352,288 C 334.327,288 320,302.327 320,320 ZM 159.951,89.63 L 118.787,114.328 C 146.768,160.863 197.745,192 256,192 C 314.254,192 365.231,160.863 393.213,114.328 L 352.049,89.63 C 332.462,122.204 296.778,144 256,144 C 215.221,144 179.538,122.204 159.951,89.63 Z" />
<glyph unicode="&#xe283;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.613-256, 256-256c 141.385,0, 256,114.615, 256,256S 397.385,480, 256,480z M 320,96L 192,96 l0,32 l 128,0 L 320,96 z M 352,352c 17.673,0, 32-14.327, 32-32c0-17.673-14.327-32-32-32s-32,14.327-32,32C 320,337.673, 334.327,352, 352,352z M 160,352 c 17.673,0, 32-14.327, 32-32c0-17.673-14.327-32-32-32s-32,14.327-32,32C 128,337.673, 142.327,352, 160,352z" />
<glyph unicode="&#xe284;" d="M 256-32c 141.385,0, 256,114.615, 256,256S 397.385,480, 256,480S0,365.385,0,224S 114.615-32, 256-32z M 256,432 c 114.875,0, 208-93.125, 208-208s-93.125-208-208-208S 48,109.125, 48,224S 141.125,432, 256,432zM 128,320c0-17.673, 14.327-32, 32-32s 32,14.327, 32,32s-14.327,32-32,32S 128,337.673, 128,320z M 320,320 c0-17.673, 14.327-32, 32-32s 32,14.327, 32,32s-14.327,32-32,32S 320,337.673, 320,320z M 192,128l 128,0 l0-32 L 192,96 L 192,128 z" />
<glyph unicode="&#xe019;" d="M 64,16A48,48 11340 1 0 160,16A48,48 11340 1 0 64,16zM 384,16A48,48 11340 1 0 480,16A48,48 11340 1 0 384,16zM 480,224L 480,416 L 64,416 C 64,451.346, 35.347,480,0,480l0-32 c 17.645,0, 32-14.355, 32-32l 24.037-206.027C 41.39,198.244, 32,180.223, 32,160 c0-35.347, 28.654-64, 64-64l 384,0 l0,32 L 96,128 c-17.673,0-32,14.327-32,32c0,0.11, 0.007,0.218, 0.008,0.328L 480,224z" />
<glyph unicode="&#xe01a;" d="M 406.494,288L 317.573,403.765C 319.134,407.535, 320,411.666, 320,416c0,17.673-14.326,32-32,32c-17.673,0-32-14.327-32-32 s 14.327-32, 32-32c 1.421,0, 2.816,0.102, 4.188,0.282L 366.144,288L 145.857,288 l 73.956,96.282C 221.184,384.102, 222.58,384, 224,384 c 17.673,0, 32,14.327, 32,32s-14.327,32-32,32s-32-14.327-32-32c0-4.334, 0.866-8.465, 2.427-12.234L 105.506,288L0,288 l0-64 l 32,0 l 32-256l 384,0 l 32,256l 32,0 l0,64 L 406.494,288 z M 160,32L 96,32 l0,64 l 64,0 L 160,32 z M 160,160L 96,160 l0,64 l 64,0 L 160,160 z M 288,32l-64,0 l0,64 l 64,0 L 288,32 z M 288,160l-64,0 l0,64 l 64,0 L 288,160 z M 416,32l-64,0 l0,64 l 64,0 L 416,32 z M 416,160l-64,0 l0,64 l 64,0 L 416,160 z" />
<glyph unicode="&#xe286;" d="M 464,416L 48,416 C 21.6,416,0,394.4,0,368l0-288 c0-26.4, 21.6-48, 48-48l 416,0 c 26.4,0, 48,21.6, 48,48L 512,368 C 512,394.4, 490.4,416, 464,416z M 48,384 l 416,0 c 8.673,0, 16-7.327, 16-16l0-48 L 32,320 l0,48 C 32,376.673, 39.327,384, 48,384z M 464,64L 48,64 c-8.673,0-16,7.327-16,16L 32,224 l 448,0 l0-144 C 480,71.327, 472.673,64, 464,64zM 64,160L 96,160L 96,96L 64,96zM 128,160L 160,160L 160,96L 128,96zM 192,160L 224,160L 224,96L 192,96z" />
<glyph unicode="&#xe287;" d="M 464,416L 48,416 C 21.6,416,0,394.4,0,368l0-288 c0-26.4, 21.6-48, 48-48l 416,0 c 26.4,0, 48,21.6, 48,48L 512,368 C 512,394.4, 490.4,416, 464,416z M 96,96 L 64,96 l0,64 l 32,0 L 96,96 z M 160,96l-32,0 l0,64 l 32,0 L 160,96 z M 224,96l-32,0 l0,64 l 32,0 L 224,96 z M 496,224L 16,224 l0,96 l 480,0 L 496,224 z" />
<glyph unicode="&#x20;" horiz-adv-x="256" />
</font></defs></svg>

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,12 @@
; DO NOT EDIT (unless you know what you are doing)
;
; This subdirectory is a git "subrepo", and this file is maintained by the
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
;
[subrepo]
remote = git@github.com:madgeek-arc/catalogue-ui.git
branch = v4.0
commit = 4ff2bce8844474c6990ba66b9bc09d788d9aff81
parent = 14f605bf8808fbe3b433ce39804e4f5ffc3e1994
method = merge
cmdver = 0.4.3

View File

@ -0,0 +1 @@
# catalogue

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,31 @@
import {NgModule} from "@angular/core";
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {LandingPageComponent} from "./pages/landingpages/dataset/landing-page.component";
import {DynamicFormModule} from "./pages/dynamic-form/dynamic-form.module";
import {ReusableComponentsModule} from "./shared/reusable-components/reusable-components.module";
import {CommonModule} from "@angular/common";
import {SearchComponent} from "./pages/search/search.component";
import {RouterModule} from "@angular/router";
import {FormBuilderModule} from "./pages/form-builder/form-builder.module";
@NgModule({
declarations: [
SearchComponent,
LandingPageComponent,
],
imports: [
CommonModule,
RouterModule,
FormsModule,
ReactiveFormsModule,
ReusableComponentsModule,
DynamicFormModule,
FormBuilderModule
],
providers: [],
exports: [
DynamicFormModule
]
})
export class CatalogueUiModule { }

View File

@ -0,0 +1,181 @@
export class DocDefinition {
header: Content;
content: any[];
styles: object;
images: object;
info: PdfMetadata;
defaultStyle: object;
// pageMargins: [ 40, 60, 40, 60 ];
// pageSize: 'A4';
footer(currentPage, pageCount) {
return {
layout: "noBorders",
fontSize: 8,
margin: [25, 20, 5, 0],
columns: [
{ text: currentPage.toString() + " of " + pageCount, alignment: 'right' },
]
}
}
constructor() {
this.header = null;
this.content = [];
this.styles = {
title: {
bold: true,
alignment: 'center',
fontSize: 24,
margin: [0, 15, 0, 10]
},
chapterHeader: {
bold: true,
fontSize: 18,
alignment: 'center',
margin: [0, 30, 0, 10]
},
tabHeader: {
bold: true,
fontSize: 15,
alignment: 'center',
decoration: 'underline',
margin: [0, 20, 0, 15]
},
link: {
color: 'blue',
},
mt_1: {
margin: [0, 2, 0, 0]
},
mt_3: {
margin: [0, 8, 0, 0]
},
mt_5: {
margin: [0, 25, 0, 0]
},
mx_1: {
margin: [0, 2, 0, 2]
},
mx_3: {
margin: [0, 8, 0, 8]
},
ms_1: {
margin: [3, 0, 0, 0]
},
ms_5: {
margin: [20, 0, 0, 0]
},
marginTopCheckBox: {
margin: [0, 3, 0, 0]
}
};
this.images = {
radioChecked: ' data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAD/klEQVRoQ+2Zj3HVMAzG2wmACUgnoExAmAA6AY8JgAkIEwATkE4ATECYgDIB6QTABKBfse5UP9uy8/7AO6o73UtiW9b3SZadvOOjA5fjA/f/6AbA347gNiNwKmAeifait0W5t3IhNz9Ep6CftwF+UwA4+kx0Jdo1OjRL/w+irwKwxuF/ui8FoI4/D2wvmjwMIipvRN8uAbIEwGOZ6HWC8Z+BUVIEdlXxk+igAGc8eitCDZCnwUY1Ia0AXorlIbJOLvMMx1ukD+MeRIOwRVpVSS0AmIP1lbF6Ge5bHY8dAwgpdM80jHL9QpSoFKUWwLvI+XO5J//dCTwHQjsEAeJJBIKU2hjAIBZIHRXCy7NdSPNcXgRYbO/35LxOE4M4kwbKbVJKAAjrN1F+EdJmtQvaEzZHeabpRJqeiCbTtQTAMvFVDPQ5IxlQcXVp2XkhbRLVhZ1N2xyAmP2HwaAXgE46sF5IPY2cjoFB3Xlnz1Ag7FPol41CDgAVgSMCAnOw70lqj8iNGaShptYTBY0kOzWV75rkAJD7XehZw35cZj2wtI+iXpmEOI3CLNesBReAHcTxIE6F2IaNVo3jtk9NSSZ99NixRmYqAoRX675XeYgS0dpEYBV2c0KktCKtAU4BmGSA5l2xBks/a3wpCI8kuxetrccUgC/iyWnwxsv/7xUp5gEjRe4UOvXSpuvgQq7v274pAL9Mh1J4rWHPSa+9RBRkQqrKNZ89AKWNbl8AcNyS+n8BOMgUYqHoGcRbxLZGe3mea/f2GpuqnMm0wFzZ88ooO+VY8Iw2+xKyBIRXRldilJ0e+ShKWU2v6PB0kN9/dSPjNZOdvwjAli2vRmPIAm6NQM1Rwu417AGkeBEAjbPo3dDLWwd0G0VbU8lLHez2orqJXcp1FzOUq/OW1UkGAcKTlkjUMM98OA8IJDkmB4ATKFHIngIzaGAIICy0+MOVfviiHdue4Liyz1hsr71WlnZayygTkn/J99KMJ8qcNk+ex6YdAjk+4DSSjVgJAEZYMLoWeB3kdLoP4UuIlktyn8KSJK8EAEftUZb75GvdlhENYs9+h1r8WUX94j2Uz4oq1GHq8S4kfq9eq/vxpF4EtP8oF7ZMkk7s0i1rogSYdGW3tbtsTZmt/n+ACWDegphDJACzifTB+c4YwXki7xJUGwG1HacTz6cAjnNKi+A4KcOvldo94mpMKwDGEGaiodVJJ4ctogGgWZTards+VYR9oQsOY4OoWqH/KtiImvK3SwBgjcmJBhpvWNWTh444DiGomzKx8aUA1I4Cgbk4Ih4Q6jsRG5Y4rsY3BWCdJE1IDX47UfuPC/14GYHhyagH0m3fJgB3sl10uAGwC1ZbbB58BH4DHK/eMUOdTWMAAAAASUVORK5CYII=',
radioUnchecked: ' data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAADeUlEQVRoQ+2Zi5HUMAyG7yoAKmCpgKMCQgVABYQKgAoIFQAVsFQAVECogKMCchUAFYA+sGZ0jh3b2SS+HU4zmmwSW9avl+Xs6cmR0+mR639yDaC2B5f0wJmAeSjcCN8U5t7Sudz8FO4df1kC/KEAUPSZcCu8K1RokPEfhV85YIXT/w2fC0AVf+6sPWtxNwmvvBF+OwfIHACPZKHXAYv/chYlRLCuMnriHRjgzIdveKgB8tTJyDZIKYCXIrnzpBPLPEPxEmrcvPveJGQRVlmUCwDLYfXWSL1w96WK+4oBhBC6a17s5fcLYbwySbkA3nnKv5d74j+5QEoB9x4DAeKJB4KQOhhAJxIIHSXcy7M1qHitlAdItg8bKa/L+CAeywvKbZCmAODW78JcIcKmXcPsAZl7eabhRJjeEQ6G6xQAa4lvIqCJCVkBFEbrhTWxo2EbA+Bb/4ETuIKuUZEY7LN7G/VCDAAVgRYBos4jrAbhBd0n2KmpfJcoBoDY37mRNayvSlovDPKQXEgCsJNoDzSJa3iANQkfbTtGxgx5oJMJWve3rDwxA+3lhVakUTKHANi4m6zBG7nE7kWjfAwB+CqKnV2B+A/lwbk8vGcNFwLw2wwgaUiemoQxMarSJZ1TAFKtxlbArFH/LwBHGUIkivYgNTexUBLTk2mB+fs+VUY5UFCHa1Iri3Oggj4JU1bDGe2ednK9qhsZx0z6tEkAtmyxjd+qaX5Z+4ewtjPsAYT4JABeDsK33aiaedCIDtpSX8jvnW/MWJ23YdTLJEDUIJQHBBQ81EwdaPBCtAvcAI21Pl0x1h8dK6d2WusFwBB/S31GSeEn5mkfNGSC1kfIFACEkDCaC3wZoDvdgvgSouWS2KewFB/qUdS2stwHj3ULI7KeR/TszyqqF+dQPisqUYepx2uQ/+11VPf9RXO7zb1MtJ/9CCd26aVygnBlt7W7bNZpMBcAC2B5C2JwngDMIdQ45XdGCMrj+aSBcgHEwonnvQNHn1JCKE7IcLUUrTgh4aUAkIGb8YZWJ5WLtfAGgAZhardu+1QR9pSdUxgZ2h7ofMa3Tka2IeYAQDiL42LY/6cle3E3EMUxCJwMGV/4XAAqR4FgOd8jKSDUdzzWzVFchR8KwCpJmBAaXAkV+48L4ziMYOHecApk8v2SAJKLrTHgGsAaVi2RefQe+APW/7QxCYAvyQAAAABJRU5ErkJggg==',
checked: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAQAAACROWYpAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAF+2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDAgNzkuMTYwNDUxLCAyMDE3LzA1LzA2LTAxOjA4OjIxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMTktMTItMzBUMDE6Mzc6MjArMDE6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDE5LTEyLTMwVDAxOjM4OjI4KzAxOjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDE5LTEyLTMwVDAxOjM4OjI4KzAxOjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMSIgcGhvdG9zaG9wOklDQ1Byb2ZpbGU9IkRvdCBHYWluIDIwJSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowNzVjYjZmMy1jNGIxLTRiZjctYWMyOS03YzUxMWY5MWJjYzQiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDo5ZTM1YTc3ZC0zNDM0LTI5NGQtYmEwOC1iY2I5MjYyMjBiOGIiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowYzc2MDY3Ny0xNDcwLTRlZDUtOGU4ZS1kNTdjODJlZDk1Y2UiPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjBjNzYwNjc3LTE0NzAtNGVkNS04ZThlLWQ1N2M4MmVkOTVjZSIgc3RFdnQ6d2hlbj0iMjAxOS0xMi0zMFQwMTozNzoyMCswMTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTggKE1hY2ludG9zaCkiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjA3NWNiNmYzLWM0YjEtNGJmNy1hYzI5LTdjNTExZjkxYmNjNCIgc3RFdnQ6d2hlbj0iMjAxOS0xMi0zMFQwMTozODoyOCswMTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTggKE1hY2ludG9zaCkiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+jHsR7AAAAUNJREFUOMvN1T9Lw0AYx/EviLVFxFH8M3USgyAFoUsQ0UV8F6Ui4qCTbuJg34HgptBdUATrUoxiqYMgiOBoIcW9BVED+jgkntGm9i6CmN+Sg/vAcc89dwBd5Clzj6uZGg7LJAC62UFipEgKcmroaeZj/gpcIAhl5rE1M0cJQbiCOsIrs5h8WZ4R6j72yBrhcRo+dhE8bCOcoYng/hFOMxAXb/DAHTNxcCGo7JE5LqhjsW2KP6nDcGecCv1vRdC2eJQDLllooach2hbvIghvLJJgM0QHdeq8F0x/5ETRM4b0DonF7be+Pf+y4A4bZnETok4E/XG3xxR3WhasUWeLCg2OGYnXGP1MkPwnLRmJf3UN+RfgtBGe5MnHVQShxBQZzdgcIgjXsKSu/KZmXgKxBkmKsZ6bffoAelilQs3goauyTi+8A8mhgeQlxdNWAAAAAElFTkSuQmCC',
unchecked: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAQAAACROWYpAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAF+2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDAgNzkuMTYwNDUxLCAyMDE3LzA1LzA2LTAxOjA4OjIxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMTktMTItMzBUMDE6Mzc6MjArMDE6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDE5LTEyLTMwVDAxOjM4OjU3KzAxOjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDE5LTEyLTMwVDAxOjM4OjU3KzAxOjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMSIgcGhvdG9zaG9wOklDQ1Byb2ZpbGU9IkRvdCBHYWluIDIwJSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpjMGUyMmJhZC1lY2VkLTQzZWUtYjIzZC1jNDZjOTNiM2UzNWMiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDo5M2FhOTEzYy1hZDVmLWZmNGEtOWE5Ny1kMmUwZjdmYzFlYmUiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDozYmY2ODFlMy1hMTRhLTQyODMtOGIxNi0zNjQ4M2E2YmZlNjYiPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjNiZjY4MWUzLWExNGEtNDI4My04YjE2LTM2NDgzYTZiZmU2NiIgc3RFdnQ6d2hlbj0iMjAxOS0xMi0zMFQwMTozNzoyMCswMTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTggKE1hY2ludG9zaCkiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOmMwZTIyYmFkLWVjZWQtNDNlZS1iMjNkLWM0NmM5M2IzZTM1YyIgc3RFdnQ6d2hlbj0iMjAxOS0xMi0zMFQwMTozODo1NyswMTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTggKE1hY2ludG9zaCkiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+6AB6cQAAAPxJREFUOMvF1b1Kw1AYBuAnFf8QL8WlIHQJIriIdyEu4qCTXop7dwenTgUHpYvgJVhob8AuakE+h9hapJqcFDXvFDgPIXlzvgNLjnQ9GlRM340TK7DsUtRI2zqH09txxUzWn3IrhK4DecXs6wjhnqHwZk/K1fIiDAs81krCW54KPBDG8iTcNBIGf4ND1MWTdmrgqIOL5TM0S8SRhmMu1dAo+2DZ57t9eWajtKrvN1GVnrMK9HewhbBy+nPPJbTsJwmymOn8P7fkfLzQGCoG4G4S3vZc4J4QOnY0KyZ3LYQHjqcjf1Qxrx/inDXtWsfNlU1YdeZOP+Gg67mwwTvIDqR1iAowgQAAAABJRU5ErkJggg==',
}
this.defaultStyle = {
font: 'Roboto',
fontSize: 12,
color: 'black',
}
}
}
export class Content {
text: string;
style: string[];
width: number;
constructor(text: string, style: string[], width?: number) {
this.text = text;
this.style = style;
if (width)
this.width = width;
}
}
export class Columns {
columns: any[];
style: string[];
constructor(style?: string[]) {
this.columns = [];
if (style)
this.style = style;
}
}
export class PdfImage {
image: string;
height: number;
width: number;
style: string[];
constructor(image: string, height: number, width: number, style: string[]) {
this.image = image;
this.height = height;
this.width = width;
this.style = style;
}
}
export class PdfTable {
table: TableDefinition;
styles: string[];
// layout = {
// paddingLeft(i, node) { return 2},
// paddingTop(i, node) { return 8},
// paddingRight(i, node) { return 2},
// paddingBottom(i, node) { return 8}
// };
constructor(table: TableDefinition, styles: string[]) {
this.table = table;
this.styles = styles;
}
}
export class TableDefinition {
body: any[][];
widths: string[];
heights: number[];
constructor(body: any[][], widths: string[], heights?: number[]) {
this.body = body;
this.widths = widths;
if (heights)
this.heights = heights;
}
}
export class PdfUnorderedList {
ul: string[];
type: string;
markerColor: string;
color: string;
constructor(ul: string[], type?: string) {
this.ul = ul;
if (type)
this.type = type;
}
}
export class PdfMetadata {
title: string;
author: string;
subject: string;
keywords: string;
creator: string;
producer: string;
creationDate: any;
modDate: any;
trapped: any;
constructor(title: string) {
this.title = title;
}
}

View File

@ -0,0 +1,207 @@
import BitSet from 'bitset/bitset';
export class Required {
topLevel: number;
total: number;
constructor() {
this.topLevel = 0;
this.total = 0;
}
}
export class Dependent {
id: number;
name: string;
value: string;
}
export class TypeInfo {
type: string;
values: string[];
vocabulary: string;
multiplicity: boolean
constructor() {
this.type = 'string';
this.values = [];
this.vocabulary = null;
this.multiplicity = false;
}
}
export class Form {
dependsOn: Dependent;
affects: Dependent[];
vocabulary: string;
group: string;
description: StyledText;
suggestion: StyledText;
placeholder: string;
mandatory: boolean;
immutable: boolean;
display: Display;
constructor() {
this.dependsOn = null;
this.affects = null;
this.vocabulary = null;
this.group = '';
this.description = new StyledText();
this.suggestion = new StyledText();
this.placeholder = '';
this.mandatory = false;
this.immutable = false;
this.display = new Display();
}
}
export class Display {
hasBorder: boolean;
order: number;
placement: string;
visible: boolean;
cssClasses: string;
style: string;
constructor() {
this.hasBorder = false;
this.order = 0;
this.placement = '';
this.cssClasses = '';
this.style = '';
this.visible = true;
}
}
export class StyledText {
cssClasses: string;
style: string;
text: string;
showLess: boolean;
constructor() {
this.cssClasses = '';
this.style = '';
this.text = '';
this.showLess = false;
}
}
export class Field {
id: string;
name: string;
parentId: string;
parent: string;
label: StyledText;
accessPath: string;
kind: string;
typeInfo: TypeInfo;
includedInSnippet: boolean;
form: Form;
display: Display;
subFields: Field[];
constructor() {
this.id = '';
this.name = '';
this.parentId = '';
this.parent = '';
this.label = new StyledText();
this.accessPath = '';
this.typeInfo = new TypeInfo()
this.includedInSnippet = false;
this.form = new Form();
this.display = new Display();
this.subFields = [];
}
}
export class Section {
id: string;
name: string;
description: string;
subType: string;
order: number;
subSections: Section[];
fields: Field[];
required: Required;
constructor() {
this.id = null;
this.name = '';
this.description = null;
this.subSections = [];
this.order = 0;
}
}
export class GroupedFields {
id: string;
name: string;
description: string;
order: number;
fields: Field[];
required: Required;
constructor() {
this.id = '';
this.name = '';
this.description = '';
this.order = 0;
this.fields = [];
this.required = new Required();
}
}
export class Model {
id: string;
name: string;
description: string;
notice: string;
type: string;
subType: string;
resourceType: string;
creationDate: string;
createdBy: string;
modifiedBy: string;
sections: Section[];
locked: boolean;
}
export class UiVocabulary {
id: string;
name: string;
}
export class Tab {
valid: boolean;
order: number;
requiredOnTab: number;
remainingOnTab: number;
bitSet: BitSet;
constructor() {
this.valid = false;
this.order = 0;
this.requiredOnTab = 0;
this.remainingOnTab = 0;
}
}
export class Tabs {
tabs: Map<string, Tab>;
requiredTabs: number;
completedTabs: number;
completedTabsBitSet: BitSet;
requiredTotal: number;
}
export class HandleBitSet {
field: Field;
position: number;
}

View File

@ -0,0 +1,12 @@
export class Facet {
field: string;
label: string;
values: FacetValue[];
}
export interface FacetValue {
value: string;
count: number;
label: string;
isChecked: boolean;
}

View File

@ -0,0 +1,11 @@
import { Facet } from './facet';
export class Paging<T> {
from: number;
to: number;
total: number;
results: T[];
facets: Facet[];
}

View File

@ -0,0 +1,16 @@
import {UiVocabulary} from './dynamic-form-model';
export class Snippet {
image: URL;
longImage: URL;
paymentTitle: string;
name: string;
description: string;
tagline: string;
logo: URL;
portfolios: UiVocabulary[];
id: string;
pitch: string;
label: string;
user: UiVocabulary[];
}

View File

@ -0,0 +1,4 @@
export class URLParameter {
key: string;
values: string[];
}

View File

@ -0,0 +1,250 @@
import {Component, EventEmitter, Input, OnChanges, Output, SimpleChanges} from '@angular/core';
import {FormControlService} from '../../services/form-control.service';
import {ActivatedRoute, Router} from '@angular/router';
import {FormArray, FormBuilder} from '@angular/forms';
import {Section, Field, HandleBitSet, Tab, Tabs} from '../../domain/dynamic-form-model';
import BitSet from "bitset";
import UIkit from 'uikit';
@Component({
selector: 'app-chapter-edit',
templateUrl: './chapter.component.html',
providers: [FormControlService]
})
export class ChapterEditComponent implements OnChanges{
@Input() form: any = null;
@Input() tabsHeader: string;
@Input() mandatoryFieldsText: string = null;
@Input() readonly : boolean = null;
@Input() validate : boolean = null;
@Input() vocabularies: Map<string, object[]> = null;
@Input() subVocabularies: Map<string, object[]> = null;
@Input() chapter: Section = null;
@Input() fields: Section[] = null;
@Output() chapterHasChanges = new EventEmitter<string[]>();
@Output() submit = new EventEmitter();
editMode = true;
bitset: Tabs = new Tabs;
errorMessage = '';
successMessage = '';
ready = false;
showLoader = false;
hasChanges = false;
pendingService = false;
showBitsets = false;
loaderBitSet = new BitSet;
loaderPercentage = 0;
tabIndex= 0;
constructor(public route: ActivatedRoute,
protected fb: FormBuilder,
protected router: Router) {
}
ngOnInit() {
}
ngOnChanges(changes:SimpleChanges) {
if (this.fields) {
this.initializations();
this.ready = true
}
}
onSubmit(tempSave: boolean, pendingService?: boolean) {
// if (this.form.valid) {
window.scrollTo(0, 0);
this.submit.emit(null);
}
initializations() {
/** Initialize tab bitsets **/
let requiredTabs = 0, requiredTotal = 0;
let obj = new Map();
this.fields.forEach(group => {
let tab = new Tab();
tab.requiredOnTab = tab.remainingOnTab = group.required.topLevel;
tab.valid = false;
tab.order = group.order;
tab.bitSet = new BitSet;
// obj[group.group.id] = tab;
obj.set(group.id, tab);
if (group.required.topLevel > 0) {
requiredTabs++;
}
requiredTotal += group.required.total;
});
this.bitset.tabs = obj;
this.bitset.completedTabs = 0;
this.bitset.completedTabsBitSet = new BitSet;
this.bitset.requiredTabs = requiredTabs;
this.bitset.requiredTotal = requiredTotal;
}
/** Bitsets-->**/
timeOut(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
handleBitSetOfComposite(data: HandleBitSet) {
let field = data.field;
let pos = data.position;
// console.log(field.name);
if (field.typeInfo.multiplicity) {
let formArray = this.form.get(field.accessPath) as FormArray;
let flag = false;
for (let i = 0; i < formArray.length; i++) {
if (formArray.controls[i].valid) {
flag = true;
field.subFields.forEach(f => {
if (f.form.mandatory)
this.loaderBitSet.set(parseInt(f.id), 1);
});
this.decreaseRemainingFieldsPerTab(field.form.group, field.form.display.order);
break;
}
}
if (!flag) {
// console.log('didn't find valid array field')
let found = new Array(field.subFields.length);
for (let j = 0; j < field.subFields.length; j++) {
for (let i = 0; i < formArray.length; i++) {
if (field.subFields[j].form.mandatory && formArray.controls[i].get(field.subFields[j].name).valid) {
found[j] = true;
break;
}
}
}
for (let i = 0; i < found.length; i++) {
if (!found[i]) {
this.loaderBitSet.set(parseInt(field.subFields[i].id), 0);
} else {
this.loaderBitSet.set(parseInt(field.subFields[i].id), 1);
}
}
this.increaseRemainingFieldsPerTab(field.form.group, field.form.display.order);
}
} else if (field.subFields[pos].form.mandatory) {
if (this.form.get(field.subFields[pos].accessPath).valid) {
this.loaderBitSet.set(parseInt(field.subFields[pos].id), 1);
if (this.form.get(field.accessPath).valid) {
this.decreaseRemainingFieldsPerTab(field.form.group, field.form.display.order);
} else {
this.increaseRemainingFieldsPerTab(field.form.group, field.form.display.order);
}
} else {
this.loaderBitSet.set(parseInt(field.subFields[pos].id), 0);
if (this.form.get(field.accessPath).valid) {
this.decreaseRemainingFieldsPerTab(field.form.group, field.form.display.order);
} else {
this.increaseRemainingFieldsPerTab(field.form.group, field.form.display.order);
}
}
}
this.updateLoaderPercentage();
}
handleBitSet(data: Field) {
// console.log(data.name);
if (data.typeInfo.multiplicity) {
this.handleBitSetOfGroup(data);
return;
}
// console.log(this.form.get(data.accessPath).valid);
if (this.form.get(data.accessPath).valid) {
this.decreaseRemainingFieldsPerTab(data.form.group, data.form.display.order);
this.loaderBitSet.set(parseInt(data.id), 1);
} else if (this.form.get(data.accessPath).invalid) {
this.increaseRemainingFieldsPerTab(data.form.group, data.form.display.order);
this.loaderBitSet.set(parseInt(data.id), 0);
} else if (this.form.get(data.accessPath).pending) {
this.timeOut(300).then(() => this.handleBitSet(data));
return;
}
this.updateLoaderPercentage();
}
handleBitSetOfGroup(data: Field) {
let formArray = this.form.get(data.accessPath) as FormArray;
let flag = false;
for (let i = 0; i < formArray.length; i++) {
if (formArray.controls[i].valid) {
flag = true;
this.decreaseRemainingFieldsPerTab(data.form.group, data.form.display.order);
this.loaderBitSet.set(parseInt(data.id), 1);
break;
} else if (formArray.controls[i].pending) {
this.timeOut(300).then(() => this.handleBitSetOfGroup(data));
return;
}
}
if (!flag) {
this.increaseRemainingFieldsPerTab(data.form.group, data.form.display.order);
this.loaderBitSet.set(parseInt(data.id), 0);
}
this.updateLoaderPercentage();
}
updateLoaderPercentage() {
// console.log(this.loaderBitSet.toString(2));
// console.log('cardinality: ', this.loaderBitSet.cardinality());
this.loaderPercentage = Math.round((this.loaderBitSet.cardinality() / this.bitset.requiredTotal) * 100);
// console.log(this.loaderPercentage, '%');
}
decreaseRemainingFieldsPerTab(tabId: string, bitIndex: number) {
this.bitset.tabs.get(tabId).bitSet.set(bitIndex, 1);
this.bitset.tabs.get(tabId).remainingOnTab = this.bitset.tabs.get(tabId).requiredOnTab - this.bitset.tabs.get(tabId).bitSet.cardinality();
if (this.bitset.tabs.get(tabId).remainingOnTab === 0 && this.bitset.completedTabsBitSet.get(this.bitset.tabs.get(tabId).order) !== 1) {
this.calcCompletedTabs(tabId, 1);
}
}
increaseRemainingFieldsPerTab(tabId: string, bitIndex: number) {
this.bitset.tabs.get(tabId).bitSet.set(bitIndex, 0);
this.bitset.tabs.get(tabId).remainingOnTab = this.bitset.tabs.get(tabId).requiredOnTab - this.bitset.tabs.get(tabId).bitSet.cardinality();
if (this.bitset.completedTabsBitSet.get(this.bitset.tabs.get(tabId).order) !== 0) {
this.calcCompletedTabs(tabId, 0);
}
}
calcCompletedTabs(tabId: string, setValue: number) {
if (tabId && this.bitset.tabs.get(tabId).order) {
this.bitset.completedTabsBitSet.set(this.bitset.tabs.get(tabId).order, setValue);
this.bitset.completedTabs = this.bitset.completedTabsBitSet.cardinality();
}
}
/** <--Bitsets**/
/** tab prev next buttons **/
setTabIndex(i: number) {
this.tabIndex = i;
}
goToTab(i: number) {
if (i === -1 || i === this.bitset.tabs.size) {
return;
}
this.tabIndex = i;
let element: HTMLElement = document.getElementById(this.chapter.id + '-tab' + i) as HTMLElement
element.click();
// console.log(element)
}
/** emit changes-->**/
unsavedChangesPrompt(e: boolean, removeChanges: string = null){
if (e) {
this.chapterHasChanges.emit([this.chapter.id, removeChanges]);
}
}
/** <--emit changes**/
}

View File

@ -0,0 +1,125 @@
<div *ngIf="ready" class="uk-section-default uk-section uk-section-xsmall uk-padding-remove-bottom" style="min-height: 325px">
<div class="uk-container uk-container-expand">
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<div class="titleAndActionsBar uk-flex uk-flex-right" style="min-height: 40px">
<div>
<button *ngIf="!readonly" class="uk-button uk-button-secondary uk-margin-left"
(click)="onSubmit(false)" type="submit"> Save
</button>
</div>
</div>
<div *ngIf="successMessage" id="successMessage" class="uk-alert-success" uk-alert="animation: true; duration: 300;">
<a class="uk-alert-close" uk-close></a>
<p>{{successMessage}}</p>
</div>
<div *ngIf="chapter" class="uk-margin-top chapter-description">
<p [innerHtml]="chapter.description"></p>
</div>
<div class="uk-margin-medium-bottom">
<div class="uk-grid">
<!-- MIDDLE -->
<div class="uk-width-expand@m uk-margin-top">
<div>
<div *ngIf="bitset.requiredTotal !== 0 && mandatoryFieldsText" class="requiredFields">
{{mandatoryFieldsText}}
</div>
<div id="serviceForm">
<div *ngIf="errorMessage" class="uk-alert uk-alert-danger">
<p>{{errorMessage}}</p>
</div>
<div *ngIf="showLoader" class="whiteFilm">
<i class="fa fa-spinner fa-spin fa-5x uk-position-center loader" aria-hidden="true"></i>
</div>
<div class="uk-grid">
<div class="uk-width-1-4" [ngStyle]="{'display': fields?.length === 1 ? 'none' : 'block'}">
<div *ngIf="tabsHeader" class="tabsTitle uk-margin-bottom">{{tabsHeader}}</div>
<ul id="{{chapter.name}}" class="uk-width-1-1 uk-margin-remove uk-tab uk-tab-left form-tabs"
[attr.uk-switcher]="'connect: #side-tab-'+chapter.id">
<li *ngFor="let tab of fields; let i=index" (click)="setTabIndex(i)">
<a id="{{chapter.id}}-tab{{i}}" href="#" class="remove-text-decoration uk-flex uk-flex-between"
[ngClass]="{'form-error': bitset.tabs.get(tab.id).valid}">
<span>{{tab.name + (tab.required.topLevel > 0 ? ' *' : '')}}</span>
<span *ngIf="bitset.tabs.get(tab.id).requiredOnTab !== 0 && showBitsets" class="circle-number">
<i *ngIf="bitset.tabs.get(tab.id).remainingOnTab === 0" aria-hidden="true" class="fa fa-check"></i>
{{bitset.tabs.get(tab.id).remainingOnTab != 0 ? bitset.tabs.get(tab.id).remainingOnTab + '*' : ''}}
</span>
</a>
</li>
</ul>
<div *ngIf="bitset.requiredTotal !== 0" class="requiredFields uk-text-right">*Required fields</div>
<div *ngIf="bitset?.tabs" class="uk-margin-small-top uk-flex uk-flex-center">
<button class="uk-button uk-margin-small-right" [disabled]="(tabIndex === 0)"
(click)="goToTab(tabIndex-1)"
[ngClass]="tabIndex === 0 ? 'uk-button-secondary' : 'uk-button-primary'">
<i class="fa fa-angle-left"></i> PREVIOUS
</button>
<button id="next" class="uk-button" [disabled]="(tabIndex === bitset.tabs.size - 1)"
(click)="goToTab(tabIndex+1)"
[ngClass]="tabIndex === bitset.tabs.size - 1 ? 'uk-button-secondary' : 'uk-button-primary'">
NEXT <i class="fa fa-angle-right"></i>
</button>
</div>
<div *ngIf="showBitsets">
<div class="stepsCompleted uk-margin-top uk-text-center">
{{bitset.completedTabs}} of {{bitset.requiredTabs}}
</div>
<div class="uk-margin-small-top">
<progress id="js-progressbar" class="uk-progress uk-margin-remove-bottom"
value="{{loaderPercentage}}"
max="100"></progress>
<div [ngStyle]="{'margin-left.%': (loaderPercentage*0.9).toLocaleString()}"
class="percentageNumber">{{loaderPercentage}}%
</div>
</div>
</div>
</div>
<div *ngIf="form && ready" [ngClass]="fields.length === 1 ? 'uk-width-1-1' : 'uk-width-3-4'">
<form [formGroup]="form">
<div class="formContainer">
<ul id="side-tab-{{chapter.id}}" class="uk-switcher">
<li *ngFor="let group of fields">
<div *ngFor="let fieldsData of group.fields"
[ngClass]="{'uk-card uk-card-body uk-card-default uk-margin-medium-bottom': fieldsData.form.display?.visible}">
<app-field [editMode]="editMode" [fieldData]="fieldsData" [form]="form"
[subVocabularies]="subVocabularies" [vocabularies]="vocabularies"
[readonly]="readonly" (hasChanges)="unsavedChangesPrompt($event)">
<!-- (handleBitSets)="handleBitSet($event)"-->
<!-- (handleBitSetsOfComposite)="handleBitSetOfComposite($event)">-->
</app-field>
</div>
</li>
</ul>
</div>
</form>
<!-- <pre>{{form.value | json}}</pre>-->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="!ready" class="whiteFilm">
<i class="loader-big" aria-hidden="true"></i>
</div>

View File

@ -0,0 +1,105 @@
<div *ngIf="ready" class="uk-section-default uk-section uk-section-xsmall uk-padding-remove-bottom" style="min-height: 325px">
<div class="uk-container uk-container-expand">
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m uk-first-column">
<div *ngIf="chapter" class="uk-margin-top chapter-description">
<p [innerHtml]="chapter.description"></p>
</div>
<div class="uk-margin-medium-bottom">
<div class="uk-grid">
<!-- MIDDLE -->
<div class="uk-width-expand@m uk-margin-top">
<div>
<div id="serviceForm">
<div uk-grid>
<div class="uk-width-1-5">
<div class="uk-padding-small uk-padding-remove-vertical"
[ngStyle]="{'display': fields?.length === 1 ? 'none' : 'block'}">
<div *ngIf="tabsHeader" class="tabsTitle uk-margin-bottom">{{tabsHeader}}</div>
<ul id="{{chapter.name}}" class="uk-width-1-1 uk-margin-remove uk-tab uk-tab-left form-tabs"
[attr.uk-switcher]="'connect: #side-tab-'+chapter.id">
<li *ngFor="let tab of fields; let i=index" (click)="setTabIndex(i)">
<a id="{{chapter.id}}-tab{{i}}" href="#" class="remove-text-decoration uk-flex uk-flex-between">
<span>{{tab.name}}</span>
</a>
</li>
</ul>
<div *ngIf="fields.length > 1" class="uk-margin-small-top uk-flex uk-flex-center">
<button class="uk-button uk-margin-small-right" [disabled]="(tabIndex === 0)"
[ngClass]="tabIndex === 0 ? 'uk-button-secondary' : 'uk-button-primary'"
(click)="goToTab(tabIndex-1)">
<i class="fa fa-angle-left"></i> PREVIOUS
</button>
<button id="next" class="uk-button" [disabled]="(tabIndex === fields.length - 1)"
[ngClass]="tabIndex === fields.length - 1 ? 'uk-button-secondary' : 'uk-button-primary'"
(click)="goToTab(tabIndex+1)">
NEXT <i class="fa fa-angle-right"></i>
</button>
</div>
</div>
</div>
<div *ngIf="formA && ready" [ngClass]="fields.length === 1 ? 'uk-width-1-1' : 'uk-width-4-5'">
<form [formGroup]="formA">
<div class="uk-margin-small-bottom" uk-grid>
<div *ngIf="entryB" class="uk-width-1-2 uk-padding-remove-left uk-flex uk-flex-center">
{{entryA.time | date: 'dd/MM/yyyy, h:mm a'}} - Version({{entryA.version}})
</div>
<div *ngIf="entryB" class="uk-width-1-2 uk-padding-remove-left uk-flex uk-flex-center">
{{entryB.time | date: 'dd/MM/yyyy, h:mm a'}} - Version({{entryB.version}})
</div>
</div>
<ul id="side-tab-{{chapter.id}}" class="uk-switcher uk-margin-remove-top">
<li *ngFor="let group of fields">
<div *ngFor="let fieldsData of group.fields" class="uk-grid-match"
[ngClass]="{'uk-display-none': !fieldsData.form.display?.visible}" uk-grid>
<div *ngIf="formA" class="uk-width-1-1" [ngClass]="{'uk-width-1-2': entryB}">
<div class="uk-card-body uk-card-default uk-margin-medium-bottom">
<app-field [editMode]="false" [fieldData]="fieldsData" [form]="formA"
[subVocabularies]="subVocabularies" [vocabularies]="vocabularies"
class=" uk-margin-medium-top uk-margin-large-bottom">
</app-field>
</div>
</div>
<div *ngIf="formB" class="uk-width-1-2">
<div class="uk-card-body uk-card-default uk-margin-medium-bottom ">
<app-field [editMode]="false" [fieldData]="fieldsData" [form]="formB"
[subVocabularies]="subVocabularies" [vocabularies]="vocabularies"
class="uk-margin-medium-top uk-margin-large-bottom">
</app-field>
</div>
</div>
</div>
</li>
</ul>
</form>
<!-- <pre>{{form.value | json}}</pre>-->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="!ready" class="whiteFilm">
<i class="loader-big" aria-hidden="true"></i>
</div>

View File

@ -0,0 +1,48 @@
import {Component, Input, OnChanges, OnInit, SimpleChanges} from "@angular/core";
import {FormGroup} from "@angular/forms";
import {Section, Tab} from "../../../../domain/dynamic-form-model";
import BitSet from "bitset";
@Component({
selector: 'app-chapter-compare',
templateUrl: 'compare-chapter.component.html'
})
export class CompareChapterComponent implements OnChanges {
@Input() formA: FormGroup = null;
@Input() formB: FormGroup = null;
@Input() entryA: any = null;
@Input() entryB: any = null;
@Input() tabsHeader: string;
@Input() chapter: Section = null;
@Input() fields: Section[] = null;
@Input() vocabularies: Map<string, object[]> = null;
@Input() subVocabularies: Map<string, object[]> = null;
ready = false;
tabIndex= 0;
ngOnChanges(changes: SimpleChanges) {
if (this.fields) {
this.ready = true
}
}
/** tab prev next buttons **/
setTabIndex(i: number) {
this.tabIndex = i;
}
goToTab(i: number) {
if (i === -1 || i === this.fields?.length) {
return;
}
this.tabIndex = i;
let element: HTMLElement = document.getElementById(this.chapter.id + '-tab' + i) as HTMLElement
element.click();
// console.log(element)
}
}

View File

@ -0,0 +1,23 @@
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {CompareSurveysComponent} from "./surveys/compare-surveys.component";
import {CompareChapterComponent} from "./chapters/compare-chapter.component";
import {ReactiveFormsModule} from "@angular/forms";
import {DynamicFormModule} from "../dynamic-form.module";
@NgModule({
declarations: [
CompareSurveysComponent,
CompareChapterComponent
],
imports: [
CommonModule,
ReactiveFormsModule,
DynamicFormModule
],
exports: [
CompareSurveysComponent
]
})
export class CompareModule {}

View File

@ -0,0 +1,29 @@
<!--Chapter Selection-->
<div *ngIf="ready && model" [ngClass]="{'uk-display-none': (model.sections.length === 1 || !model.sections[0].subSections)}">
<ul class="chapter-tabs uk-tab" uk-tab="connect: #top-navigation-tabs; animation: uk-animation-fade">
<li class="" *ngFor="let section of model.sections">
<a *ngIf="(!section.subType || section.subType===subType)">{{section.name}}
<!-- <span *ngIf="chapterChangeMap.get(section.id)" class="material-icons md-10 uk-margin-small-left">circle</span>-->
</a>
</li>
</ul>
</div>
<div class="titleAndActionsBar uk-flex uk-flex-right" style="min-height: 40px"></div>
<div *ngIf="ready && model; else showLoader">
<ul id="top-navigation-tabs" class="uk-switcher">
<li *ngFor="let section of model.sections let i = index">
<app-chapter-compare [formA]="getFormGroup(formA, i)" [formB]="getFormGroup(formB, i)" [tabsHeader]="tabsHeader"
[entryA]="entryA" [entryB]="entryB" [fields]="model.sections[i].subSections"
[chapter]="model.sections[i]" [vocabularies]="vocabulariesMap"
[subVocabularies]="subVocabularies">
</app-chapter-compare>
</li>
</ul>
</div>
<ng-template #showLoader class="whiteFilm" style="min-height: 100vh">
<i class="loader-big" aria-hidden="true"></i>
</ng-template>

View File

@ -0,0 +1,177 @@
import {Component, Input, OnChanges, SimpleChanges} from "@angular/core";
import {FormArray, FormBuilder, FormGroup} from "@angular/forms";
import {Field, Model, Section} from "../../../../domain/dynamic-form-model";
import {FormControlService} from "../../../../services/form-control.service";
@Component({
selector: 'app-compare-surveys',
templateUrl: 'compare-surveys.component.html',
providers: [FormControlService]
})
export class CompareSurveysComponent implements OnChanges{
@Input() payloadA: any = null;
@Input() payloadB: any = null;
@Input() entryA: any = null;
@Input() entryB: any = null;
@Input() model: Model = null;
@Input() subType: string = null;
@Input() vocabulariesMap: Map<string, object[]> = null;
@Input() subVocabularies: Map<string, object[]> = null;
@Input() tabsHeader: string = null;
ready = false;
formA = this.fb.group({});
formB = this.fb.group({});
constructor(private formControlService: FormControlService, private fb: FormBuilder,) {
}
ngOnChanges(changes: SimpleChanges) {
if (this.model && this.payloadA?.answer) {
this.createForm(this.formA);
this.patchForm(this.formA, this.payloadA.answer);
if (this.payloadB?.answer) {
this.createForm(this.formB);
this.patchForm(this.formB, this.payloadB.answer);
}
this.ready = true;
} else {
this.formA = this.fb.group({});
this.formB = this.fb.group({});
}
}
createForm(form: FormGroup) {
this.model.sections = this.model.sections.sort((a, b) => a.order - b.order);
for (let i = 0; i < this.model.sections.length; i++) {
if (this.model.sections[i].subSections === null) {
form.addControl(this.model.name, this.formControlService.toFormGroup(this.model.sections, true));
break;
}
if (!this.model.sections[i].subType || this.model.sections[i].subType === this.subType) {
form.addControl(this.model.sections[i].name, this.formControlService.toFormGroup(this.model.sections[i].subSections, true));
}
}
}
patchForm(form: FormGroup, payload: Object) {
for (let i = 0; i < this.model.sections.length; i++) {
if (payload[this.model.sections[i].name])
this.prepareForm(form, payload[this.model.sections[i].name], this.model.sections[i].subSections);
}
form.patchValue(payload);
// setTimeout(() => {
form.disable();
form.markAsUntouched();
// }, 0);
}
getFormGroup(form: FormGroup, sectionIndex: number): FormGroup {
if (this.model.sections[sectionIndex].subSections === null) {
return form.get(this.model.name) as FormGroup;
} else
// console.log(this.form.get(this.survey.sections[sectionIndex].name));
return form.get(this.model.sections[sectionIndex].name) as FormGroup;
}
/** create additional fields for arrays if needed --> **/
prepareForm(form: FormGroup, answer: Object, fields: Section[], arrayIndex?: number) { // I don't think it will work with greater depth than 2 of array nesting
for (const [key, value] of Object.entries(answer)) {
if (typeof value === 'object' && !Array.isArray(value) && value !== null) {
this.prepareForm(form, value, fields);
} else if (Array.isArray(value)) {
if (value?.length > 1) {
this.pushToFormArray(form, key, value.length, arrayIndex);
}
for (let i = 0 ;i < value?.length; i++) {
if (typeof value[i] === 'object' && !Array.isArray(value[i]) && value[i] !== null) {
this.prepareForm(form, value[i], fields, i);
}
// Maybe a check for array in array should be here
}
} else if (value === null) {
// console.log(key+ ' is null');
}
}
}
pushToFormArray(form: FormGroup, name: string, length: number, arrayIndex?: number) {
let field = this.getModelData(this.model.sections, name);
while (this.getFormControl(form, name, arrayIndex).length < length) {
// for (let i = 0; i < length-1; i++) {
this.getFormControl(form, name, arrayIndex).push(this.formControlService.createField(field));
}
}
getModelData(model: Section[], name: string): Field {
let field = null;
for (let i = 0; i < model.length; i++) {
if (model[i].fields === null) {
field = this.getModelData(model[i].subSections, name);
if (field) {
return field;
}
} else {
field = this.searchSubFields(model[i].fields, name);
if (field) {
return field;
}
}
}
return field;
}
searchSubFields(fields: Field[], name): Field | null {
let field = null;
for (let j = 0; j < fields.length; j++) {
if(fields[j].name === name) {
return fields[j];
} else if (fields[j].subFields?.length > 0) {
field = this.searchSubFields(fields[j].subFields, name);
if (field?.name === name)
return field;
}
}
return null;
}
getFormControl(group: FormGroup | FormArray, name: string, position?: number): FormArray {
let abstractControl = null;
for (const key in group.controls) {
abstractControl = group.controls[key];
if (abstractControl instanceof FormGroup || abstractControl instanceof FormArray) {
if (key === name) {
return abstractControl as FormArray;
} else if (key !== name) {
if (abstractControl instanceof FormArray) {
if (abstractControl.controls.length > position) {
abstractControl = this.getFormControl(abstractControl.controls[position] as FormGroup | FormArray, name, position);
if (abstractControl !== null)
return abstractControl;
} else {
abstractControl = null;
}
} else {
abstractControl = this.getFormControl(abstractControl, name, position);
if (abstractControl !== null)
return abstractControl;
}
}
} else {
if (key === name) {
return abstractControl;
}
abstractControl = null;
}
}
return abstractControl;
}
/** <-- create additional fields for arrays if needed **/
}

View File

@ -0,0 +1,58 @@
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {DynamicFormFieldsComponent} from "./fields/dynamic-form-fields.component";
import {ChapterEditComponent} from "./chapter-edit.component";
import {NgSelectModule} from "@ng-select/ng-select";
import {CompositeFieldComponent} from "./fields/composite-field/composite-field.component";
import {StringFieldComponent} from "./fields/string-field/string-field.component";
import {VocabularyFieldComponent} from "./fields/dropdown-field/vocabulary-field.component";
import {CheckboxFieldComponent} from "./fields/checkbox-field/checkbox-field.component";
import {LargeTextFieldComponent} from "./fields/large-text-field/large-text-field.component";
import {RadioButtonFieldComponent} from "./fields/radio-button-field/radio-button-field.component";
import {DateFieldComponent} from "./fields/date-field/date-field.component";
import {DpDatePickerModule} from "ng2-date-picker";
import {RadioGridFieldComponent} from "./fields/radio-grid-field/radio-grid-field.component";
import {SurveyComponent} from "./survey.component";
import {NumberFieldComponent} from "./fields/number-field/number-field.component";
import {ReusableComponentsModule} from "../../shared/reusable-components/reusable-components.module";
import {RichTextFieldComponent} from "./fields/rich-text-field/rich-text-field.component";
import {CKEditorModule} from "@ckeditor/ckeditor5-angular";
import {ChooseOneComponent} from "./fields/choose-one-composite/choose-one.component";
import {CatalogueUiSharedModule} from "../../shared/catalogue-ui-shared.module";
@NgModule({
declarations: [
StringFieldComponent,
CompositeFieldComponent,
DynamicFormFieldsComponent,
ChapterEditComponent,
VocabularyFieldComponent,
CheckboxFieldComponent,
RadioButtonFieldComponent,
DateFieldComponent,
LargeTextFieldComponent,
RichTextFieldComponent,
RadioGridFieldComponent,
NumberFieldComponent,
ChooseOneComponent,
SurveyComponent
],
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
NgSelectModule,
DpDatePickerModule,
ReusableComponentsModule,
CKEditorModule,
CatalogueUiSharedModule,
],
exports: [
ChapterEditComponent,
SurveyComponent,
DynamicFormFieldsComponent
]
})
export class DynamicFormModule { }

View File

@ -0,0 +1,43 @@
<form [formGroup]="form" class="uk-margin-small-bottom {{fieldData.form.display.cssClasses}}">
<div *ngIf="fieldData.form.description.text" class="uk-form-description uk-margin-top uk-margin-bottom uk-width-9-10 {{fieldData.form.description.cssClasses}}"
[innerHTML]="fieldData.form.description.text" style="{{fieldData.form.description.style}}">
</div>
<div *ngIf="fieldData.typeInfo.multiplicity; else noMultiplicity" [formArrayName]="fieldData.name">
<div *ngFor="let input of fieldAsFormArray().controls; let i=index" class="uk-margin-bottom">
<input [id]="fieldData.name" [formControlName]="i"
class="uk-checkbox uk-width-9-10 uk-animation-slide-top-small" type="checkbox"
[placeholder]="fieldData.form.placeholder ? fieldData.form.placeholder : ''"
[ngClass]="{'uk-form-danger': checkFormArrayValidity(fieldData.name, i, this.editMode)}"
(input)="updateBitSet(fieldData); unsavedChangesPrompt()">
<a *ngIf="fieldAsFormArray().length > 1" class="remove-element uk-padding-small uk-animation-slide-top-small"
(click)="remove(fieldData.name, i); updateBitSet(fieldData); unsavedChangesPrompt()">
<span class="material-icons">clear</span>
</a>
</div>
<div class="uk-width-9-10"><i><small>{{fieldData.form.suggestion.text}}</small></i></div>
<div *ngIf="form.enabled" class="uk-width-9-10 uk-text-center uk-margin-top">
<a class="add-new-element uk-flex uk-flex-middle uk-flex-center"
(click)="push(fieldData.name, fieldData.form.mandatory)">
<span class="material-icons">add</span>Add &nbsp;<span [innerHTML]="fieldData.label.text"></span>
</a>
</div>
</div>
<ng-template #noMultiplicity>
<label *ngIf="fieldData.label.text" class="uk-form-label {{fieldData.label.cssClasses}}" style="{{fieldData.label.style}}">
<input [formControlName]="fieldData.name" [id]="fieldData.id" class="uk-checkbox" type="checkbox"
(input)="updateBitSet(fieldData); unsavedChangesPrompt()"
[ngClass]="{'uk-form-danger': checkFormValidity() }">
<span class="uk-checkbox-label uk-margin-small-left">{{fieldData.label.text + (fieldData.form.mandatory ? ' (*)' : '')}}</span>
</label>
<div *ngIf="fieldData.form.suggestion.text" class="uk-margin-top">
<div class="uk-suggestion uk-width-9-10 {{fieldData.form.suggestion.cssClasses}}" style="{{fieldData.form.suggestion.style}}" [innerHTML]="fieldData.form.suggestion.text"></div>
</div>
</ng-template>
</form>
<!--<pre>{{form.value | json}}</pre>-->

View File

@ -0,0 +1,87 @@
import {Component, EventEmitter, Input, OnInit, Output} from "@angular/core";
import {Field, HandleBitSet} from "../../../../domain/dynamic-form-model";
import {FormArray, FormControl, FormGroup, FormGroupDirective, Validators} from "@angular/forms";
@Component({
selector: 'app-checkbox-field',
templateUrl: './checkbox-field.component.html'
})
export class CheckboxFieldComponent implements OnInit {
@Input() fieldData: Field;
@Input() editMode: any;
@Input() position?: number = null;
@Output() hasChanges = new EventEmitter<boolean>();
@Output() handleBitSets = new EventEmitter<Field>();
@Output() handleBitSetsOfComposite = new EventEmitter<HandleBitSet>();
formControl!: FormControl;
form!: FormGroup;
constructor(private rootFormGroup: FormGroupDirective) {
}
ngOnInit() {
// console.log(this.fieldData);
if (this.position !== null) {
this.form = this.rootFormGroup.control.controls[this.position] as FormGroup;
} else {
this.form = this.rootFormGroup.control;
}
// console.log(this.form);
this.formControl = this.form.get(this.fieldData.name) as FormControl;
// console.log(this.formControl);
}
/** Handle Arrays --> **/
fieldAsFormArray() {
return this.formControl as unknown as FormArray;
}
push(field: string, required: boolean) {
this.fieldAsFormArray().push(required ? new FormControl(null, Validators.required) : new FormControl(null));
}
remove(field: string, i: number) {
this.fieldAsFormArray().removeAt(i);
}
/** check fields validity--> **/
checkFormValidity(): boolean {
return (!this.formControl.valid && (this.formControl.touched || this.formControl.dirty));
}
checkFormArrayValidity(name: string, position: number, edit: boolean, groupName?: string): boolean {
if (groupName) {
return (!this.fieldAsFormArray()?.get([position])?.get(groupName).valid
&& (edit || this.fieldAsFormArray()?.get([position])?.get(groupName).dirty));
}
return (!this.fieldAsFormArray().get([position]).valid
&& (edit || this.fieldAsFormArray().get([position]).dirty));
}
/** Bitsets--> **/
updateBitSet(fieldData: Field) {
this.timeOut(200).then(() => { // Needed for radio buttons strange behaviour
if (fieldData.form.mandatory) {
this.handleBitSets.emit(fieldData);
}
});
}
/** other stuff--> **/
unsavedChangesPrompt() {
this.hasChanges.emit(true);
}
timeOut(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}

View File

@ -0,0 +1,101 @@
<form *ngIf="form" [formGroup]="form" class="{{fieldData.form.display?.cssClasses}}" [ngClass]="{'uk-hidden clear-style': hideField}">
<!-- {{fieldData.name | json}}-->
<div *ngIf="fieldData.label?.text" class="uk-form-label uk-margin-bottom {{fieldData.label?.cssClasses}}"
[attr.for]="fieldData.name" style="{{fieldData.label.style}}">
{{fieldData.label?.text + (fieldData.form.mandatory ? ' (*)' : '')}}
</div>
<ng-container *ngIf="fieldData.form.description?.showLess; else noReadMore">
<div *ngIf="fieldData.form.description.text" class="uk-form-description uk-margin-bottom uk-width-9-10 {{fieldData.form.description.cssClasses}}"
style="{{fieldData.form.description.style}}">
<read-more-text [maxHeight]="46" [text]="fieldData.form.description.text"></read-more-text>
</div>
</ng-container>
<ng-template #noReadMore>
<div *ngIf="fieldData.form.description?.text"
class="uk-form-description uk-margin-bottom uk-width-9-10 {{fieldData.form.description.cssClasses}}"
[innerHTML]="fieldData.form.description.text" style="{{fieldData.form.description.style}}">
<!-- [innerHTML]="'<read-more-text [maxHeight]=&quot260&quot [text]=\'asdsad\'></read-more-text>'">-->
</div>
</ng-template>
<div *ngIf="fieldData.typeInfo.multiplicity; else noMultiplicity">
<div *ngFor="let arrayControl of fieldAsFormArray().controls; let i=index">
<!-- Show radio so user can choose one-->
<div class="uk-margin-small-bottom">
<div *ngFor="let field of fieldData.subFields; let j=index">
<label class="uk-form-label">
<input class="uk-radio uk-margin-small-right" type="radio" [name]="i+'-'+fieldData.name" [checked]="j===0"
(click)="chooseOne(field.name, i)">
{{field.label.text}}
</label>
</div>
</div>
<div [formGroupName]="i" class="uk-width-9-10 uk-display-inline-block" [ngClass]="{'uk-margin-bottom formGroupElement': fieldData.form.display?.hasBorder}">
<div *ngFor="let control of fieldData?.subFields; let j=index">
<div class="">
<div *ngIf="getGroupOfArray(i).contains(control.name)">
<ng-container *ngIf="control.typeInfo.type === 'composite'">
<app-composite-field [fieldData]="control" [subVocabularies]="subVocabularies"
[vocabularies]="vocabularies" (hasChanges)="unsavedChangesPrompt()"
[position]="i" (handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-composite-field>
</ng-container>
<ng-container *ngIf="control.typeInfo.type === 'string' || control.typeInfo.type === 'double' ||
control.typeInfo.type === 'email' || control.typeInfo.type === 'phone' ||
control.typeInfo.type === 'url'">
<app-string-url-email-field [fieldData]="control" [position]="i" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-string-url-email-field>
</ng-container>
</div>
</div>
</div>
</div>
<a *ngIf="fieldAsFormArray().length > 1" class="remove-element uk-padding-small uk-display-inline-block"
(click)="remove(i); updateBitSetOfComposite(fieldData, i); unsavedChangesPrompt();">
<span class="material-icons">clear</span>
</a>
</div>
<div *ngIf="form.enabled" class="uk-width-9-10 uk-text-center uk-margin-top">
<a class="add-new-element uk-flex uk-flex-middle uk-flex-center" (click)="pushComposite(fieldData)">
<span class="material-icons">add</span>Add &nbsp;<span [innerHTML]="fieldData.label.text"></span>
</a>
</div>
</div>
<ng-template #noMultiplicity>
<!-- Show radio so user can choose one-->
<div class="uk-margin-small-bottom">
<div *ngFor="let field of fieldData.subFields; let i=index">
<label class="uk-form-label">
<input class="uk-radio uk-margin-small-right" type="radio" [name]="fieldData.name" [checked]="i===0"
(click)="chooseOne(field.name)">
{{field.label.text}}
</label>
</div>
</div>
<div class="uk-width-1-1 uk-display-inline-block" [ngClass]="{'uk-margin-bottom formGroupElement': fieldData.form.display?.hasBorder}">
<div *ngFor="let control of fieldData?.subFields; let j=index">
<div class="">
<div *ngIf="this.form.contains(control.name) && control.typeInfo.type === 'composite'">
<app-composite-field [fieldData]="control" [subVocabularies]="subVocabularies" [vocabularies]="vocabularies"
(handleBitSets)="handleBitsetOfChildren($event)" (hasChanges)="unsavedChangesPrompt()"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-composite-field>
</div>
</div>
</div>
</div>
</ng-template>
<div *ngIf="fieldData.form.suggestion?.text" class="uk-margin-top">
<div class="uk-suggestion uk-width-9-10 {{fieldData.form.suggestion.cssClasses}}" style="{{fieldData.form.suggestion.style}}" [innerHTML]="fieldData.form.suggestion.text"></div>
</div>
</form>
<!--<pre>{{fieldData | json}}</pre>-->
<!--<pre>{{form.getRawValue() | json}}</pre>-->

View File

@ -0,0 +1,131 @@
import {ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output} from "@angular/core";
import {Field, HandleBitSet, UiVocabulary} from "../../../../domain/dynamic-form-model";
import {FormArray, FormGroup, FormGroupDirective} from "@angular/forms";
import {FormControlService} from "../../../../services/form-control.service";
@Component({
selector: 'app-choose-one',
templateUrl: './choose-one.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChooseOneComponent implements OnInit {
@Input() fieldData: Field;
@Input() vocabularies: Map<string, object[]>;
@Input() subVocabularies: Map<string, object[]>;
@Input() editMode: any;
@Input() position?: number = null;
@Output() hasChanges = new EventEmitter<boolean>();
@Output() handleBitSets = new EventEmitter<Field>();
@Output() handleBitSetsOfComposite = new EventEmitter<HandleBitSet>();
form: FormGroup;
hideField: boolean = null;
constructor(private rootFormGroup: FormGroupDirective, private formService: FormControlService) {
}
ngOnInit() {
if (this.position !== null) {
// console.log(this.rootFormGroup.control.controls[this.position]);
// console.log(this.rootFormGroup.control.controls[this.position].get(this.fieldData.name));
this.form = this.rootFormGroup.control.controls[this.position].get(this.fieldData.name) as FormGroup;
} else {
this.form = this.rootFormGroup.control.get(this.fieldData.name) as FormGroup;
}
if (this.fieldData.typeInfo.multiplicity){
this.chooseOne(Object.entries((this.form.controls[0] as FormGroup).controls)[0][0], 0);
} else {
this.chooseOne(Object.entries(this.form.controls)[0][0])
}
}
/** Choose one to show **/
chooseOne(name: string, index?: number) {
let tmpGroup: FormGroup;
if (index !== undefined) {
tmpGroup = this.form.controls[index] as FormGroup;
} else {
tmpGroup = this.form;
}
for (const control in tmpGroup.controls) {
tmpGroup.removeControl(control);
}
if (this.fieldData.subFields.find(field => field.name === name).typeInfo.type === 'composite')
tmpGroup.addControl(name, this.formService.createCompositeField(this.fieldData.subFields.find(field => field.name === name)));
else if (this.fieldData.subFields.find(field => field.name === name).typeInfo.type === 'string') {
tmpGroup.addControl(name, this.formService.createField(this.fieldData.subFields.find(field => field.name === name)));
}
}
/** Handle Arrays --> **/
fieldAsFormArray() {
return this.form as unknown as FormArray;
}
getGroupOfArray(index: number) {
return this.fieldAsFormArray().controls[index] as FormGroup;
}
remove(i: number) {
this.fieldAsFormArray().removeAt(i);
}
pushComposite(compositeField: Field) {
this.fieldAsFormArray().push(this.formService.createCompositeField(compositeField));
this.chooseOne(Object.entries((this.form.controls[this.fieldAsFormArray().length - 1] as FormGroup).controls)[0][0], this.fieldAsFormArray().length - 1);
}
/** <-- Handle Arrays **/
updateBitSet(fieldData: Field) {
this.timeOut(200).then(() => { // Needed for radio buttons strange behaviour
if (fieldData.form.mandatory) {
this.handleBitSets.emit(fieldData);
}
});
}
updateBitSetOfComposite(fieldData: Field, position: number) {
if (fieldData.form.mandatory) {
let tmp = new HandleBitSet();
tmp.field = fieldData;
tmp.position = position;
this.handleBitSetsOfComposite.emit(tmp);
}
}
handleCompositeBitsetOfChildren(data: HandleBitSet) {
this.handleBitSetsOfComposite.emit(data);
}
handleBitsetOfChildren(data: Field) {
this.handleBitSets.emit(data);
}
/** other stuff--> **/
unsavedChangesPrompt() {
this.hasChanges.emit(true);
}
timeOut(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
enableDisableField(value) {
// console.log(value);
if (value === 'Applicable') {
this.form.enable();
this.hideField = false;
} else {
this.form.disable();
this.form.reset();
this.hideField = true;
// maybe add this if the remaining empty fields are a problem
// (this.formControl as unknown as FormArray).clear();
}
}
}

View File

@ -0,0 +1,213 @@
<form *ngIf="form" [formGroup]="form" class="{{fieldData.form.display?.cssClasses}}" [ngClass]="{'uk-hidden clear-style': (hideField || !fieldData.form.display.visible)}">
<!-- {{fieldData.name | json}}-->
<div *ngIf="fieldData.label?.text" class="uk-form-label uk-margin-bottom {{fieldData.label?.cssClasses}}"
[attr.for]="fieldData.name" style="{{fieldData.label.style}}">
{{fieldData.label?.text + (fieldData.form.mandatory ? ' (*)' : '')}}
</div>
<ng-container *ngIf="fieldData.form.description?.showLess; else noReadMore">
<div class="uk-form-description uk-margin-bottom uk-width-9-10 {{fieldData.form.description.cssClasses}}"
*ngIf="fieldData.form.description.text" style="{{fieldData.form.description.style}}">
<read-more-text [maxHeight]="46" [text]="fieldData.form.description.text"></read-more-text>
</div>
</ng-container>
<ng-template #noReadMore>
<div *ngIf="fieldData.form.description?.text" [innerHTML]="fieldData.form.description.text" style="{{fieldData.form.description.style}}"
class="uk-form-description uk-margin-bottom uk-width-9-10 {{fieldData.form.description.cssClasses}}">
</div>
</ng-template>
<div *ngIf="fieldData.typeInfo.multiplicity; else noMultiplicity">
<div uk-sortable="handle: .uk-sortable-handle" (moved)="movedElement($event)">
<div *ngFor="let control of fieldAsFormArray().controls; let i=index" id="{{i}}" class="uk-width-expand uk-grid">
<div [formGroupName]="i" class="uk-width-9-10 uk-margin-medium-left"
[ngClass]="{'uk-margin-bottom formGroupElement': fieldData.form.display?.hasBorder}">
<div *ngIf="fieldAsFormArray().length > 1" class="uk-flex uk-flex-right">
<span class="uk-sortable-handle uk-text-center" uk-icon="icon: move"></span>
</div>
<div *ngFor="let control of fieldData?.subFields; let j=index">
<div class="">
<div *ngIf="control.typeInfo.type === 'composite'">
<app-composite-field [fieldData]="control" [subVocabularies]="subVocabularies" [readonly]="readonly"
[vocabularies]="vocabularies" (hasChanges)="unsavedChangesPrompt()"
[position]="i" (handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-composite-field>
</div>
<div *ngIf="control.typeInfo.type === 'chooseOne'">
<app-choose-one [fieldData]="control" [subVocabularies]="subVocabularies"
[vocabularies]="vocabularies" (hasChanges)="unsavedChangesPrompt()"
[position]="i" (handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-choose-one>
</div>
<div *ngIf="control.typeInfo.type === 'vocabulary' || control.typeInfo.type === 'select'" class="uk-form-controls uk-margin-medium-top">
<app-vocabulary-field [fieldData]="control" [subVocabularies]="subVocabularies"
[vocabularies]="vocabularies" (hasChanges)="unsavedChangesPrompt()"
[position]="i" (handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-vocabulary-field>
</div>
<div *ngIf="control.typeInfo.type === 'string' || control.typeInfo.type === 'email'||
control.typeInfo.type === 'phone' || control.typeInfo.type === 'url' ||
control.typeInfo.type === 'double'">
<app-string-url-email-field [fieldData]="control" [position]="i" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-string-url-email-field>
</div>
<div *ngIf="control.typeInfo.type === 'number'">
<app-number-field [fieldData]="control" [position]="i" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-number-field>
</div>
<div *ngIf="control.typeInfo.type === 'checkbox'" class="uk-form-controls">
<app-checkbox-field [fieldData]="control" [position]="i" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-checkbox-field>
</div>
<div *ngIf="control.typeInfo.type === 'largeText'">
<app-large-text-field [fieldData]="control" [position]="i" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-large-text-field>
</div>
<div *ngIf="control.typeInfo.type === 'radio'" class="uk-form-controls">
<app-radio-button-field [fieldData]="control" [position]="i" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)" [readonly]="readonly"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-radio-button-field>
</div>
<div *ngIf="control.typeInfo.type === 'richText'" class="uk-form-controls">
<app-rich-text-field [fieldData]="control" [position]="i" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-rich-text-field>
</div>
<div *ngIf="control.typeInfo.type === 'date'">
<app-date-field [fieldData]="control" [position]="i" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-date-field>
</div>
</div>
</div>
</div>
<div *ngIf="fieldAsFormArray().length > 1" class="uk-width-expand uk-padding-remove uk-margin-small-top uk-grid uk-child-width-1-2">
<div class="">
<div>
<a (click)="move(i-1, i)"><span class="material-icons">north</span></a>
</div>
<div>
<a (click)="move(i+1, i)"><span class="material-icons">south</span></a>
</div>
</div>
<div class="uk-padding-small">
<a class="remove-element"
(click)="remove(i); updateBitSetOfComposite(fieldData, i); unsavedChangesPrompt();">
<span class="material-icons">clear</span>
</a>
</div>
</div>
</div>
</div>
<div *ngIf="form.enabled" class="uk-width-9-10 uk-text-center uk-margin-top uk-margin-bottom">
<a class="add-new-element uk-flex uk-flex-middle uk-flex-center" (click)="pushComposite(fieldData)">
<span class="material-icons">add</span>Add &nbsp;<span [innerHTML]="fieldData.label.text"></span>
</a>
</div>
</div>
<ng-template #noMultiplicity>
<div class="uk-width-1-1 uk-display-inline-block" [ngClass]="{'uk-margin-bottom formGroupElement': fieldData.form.display?.hasBorder}">
<div *ngFor="let control of fieldData?.subFields; let j=index">
<div class="">
<div *ngIf="control.typeInfo.type === 'composite'">
<app-composite-field [fieldData]="control" [subVocabularies]="subVocabularies" [vocabularies]="vocabularies"
(handleBitSets)="handleBitsetOfChildren($event)" (hasChanges)="unsavedChangesPrompt()"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-composite-field>
</div>
<div *ngIf="control.typeInfo.type === 'chooseOne'">
<app-choose-one [fieldData]="control" [subVocabularies]="subVocabularies" [vocabularies]="vocabularies"
(handleBitSets)="handleBitsetOfChildren($event)" (hasChanges)="unsavedChangesPrompt()"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-choose-one>
</div>
<div *ngIf="control.typeInfo.type === 'vocabulary' || control.typeInfo.type === 'select'" class="uk-form-controls uk-margin-medium-top">
<app-vocabulary-field [fieldData]="control" [subVocabularies]="subVocabularies"
[vocabularies]="vocabularies" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-vocabulary-field>
</div>
<div *ngIf="control.typeInfo.type === 'string' || control.typeInfo.type === 'url' ||
control.typeInfo.type === 'email' || control.typeInfo.type === 'phone' ||
control.typeInfo.type === 'double'">
<app-string-url-email-field [fieldData]="control" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-string-url-email-field>
</div>
<div *ngIf="control.typeInfo.type === 'number'">
<app-number-field [fieldData]="control" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-number-field>
</div>
<div *ngIf="control.typeInfo.type === 'checkbox'" class="uk-form-controls">
<app-checkbox-field [fieldData]="control" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-checkbox-field>
</div>
<div *ngIf="control.typeInfo.type === 'largeText'" class="uk-form-controls">
<app-large-text-field [fieldData]="control" [readonly]="readonly" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-large-text-field>
</div>
<div *ngIf="control.typeInfo.type === 'richText'" class="uk-form-controls">
<app-rich-text-field [fieldData]="control" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-rich-text-field>
</div>
<div *ngIf="control.typeInfo.type === 'radio'" class="uk-form-controls">
<app-radio-button-field [fieldData]="control" [readonly]="readonly" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-radio-button-field>
</div>
<div *ngIf="control.typeInfo.type === 'date'">
<app-date-field [fieldData]="control" (hasChanges)="unsavedChangesPrompt()"
(handleBitSets)="handleBitsetOfChildren($event)"
(handleBitSetsOfComposite)="handleCompositeBitsetOfChildren($event)">
</app-date-field>
</div>
<div *ngIf="control.typeInfo.type === 'radioGrid'">
<app-radio-grid [fieldData]="control">
</app-radio-grid>
</div>
</div>
</div>
</div>
</ng-template>
<div *ngIf="fieldData.form.suggestion?.text" class="uk-margin-top">
<div class="uk-suggestion uk-width-9-10 {{fieldData.form.suggestion.cssClasses}}" style="{{fieldData.form.suggestion.style}}"
[innerHTML]="fieldData.form.suggestion.text">
</div>
</div>
</form>
<!--<pre>{{fieldData | json}}</pre>-->

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