Skip to content

Commit

Permalink
ufal/fe-add-default-static-pages (#406)
Browse files Browse the repository at this point in the history
* Added static pages from the lindat git

* Fixed redirection and created safeHtml pipe.

* Could redirect out of namespace url, small refactoring.

* Updated tests.

* Added images into the static pages.
  • Loading branch information
milanmajchrak authored Dec 5, 2023
1 parent a5c9d5d commit 5e3c540
Show file tree
Hide file tree
Showing 36 changed files with 2,087 additions and 16 deletions.
4 changes: 3 additions & 1 deletion src/app/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ import { EpersonGroupListComponent } from './eperson-group-list/eperson-group-li
import { EpersonSearchBoxComponent } from './eperson-group-list/eperson-search-box/eperson-search-box.component';
import { GroupSearchBoxComponent } from './eperson-group-list/group-search-box/group-search-box.component';
import { HtmlContentService } from './html-content.service';
import { ClarinSafeHtmlPipe } from './utils/clarin-safehtml.pipe';

const MODULES = [
CommonModule,
Expand Down Expand Up @@ -319,7 +320,8 @@ const PIPES = [
ClarinLicenseCheckedPipe,
ClarinLicenseLabelRadioValuePipe,
ClarinLicenseRequiredInfoPipe,
CharToEndPipe
CharToEndPipe,
ClarinSafeHtmlPipe
];

const COMPONENTS = [
Expand Down
15 changes: 15 additions & 0 deletions src/app/shared/utils/clarin-safehtml.pipe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';

/**
* Pipe to keep html tags e.g., `id` in the `innerHTML` attribute.
*/
@Pipe({
name: 'dsSafeHtml'
})
export class ClarinSafeHtmlPipe implements PipeTransform {
constructor(private sanitized: DomSanitizer) {}
transform(htmlString: string): SafeHtml {
return this.sanitized.bypassSecurityTrustHtml(htmlString);
}
}
2 changes: 1 addition & 1 deletion src/app/static-page/static-page.component.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<div class="container" >
<div [innerHTML]="(htmlContent | async)"></div>
<div [innerHTML]="(htmlContent | async) | dsSafeHtml" (click)="processLinks($event)"></div>
</div>
19 changes: 15 additions & 4 deletions src/app/static-page/static-page.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,42 @@ import { RouterMock } from '../shared/mocks/router.mock';
import { LocaleService } from '../core/locale/locale.service';
import { TranslateModule } from '@ngx-translate/core';
import { of } from 'rxjs';
import { APP_CONFIG } from '../../config/app-config.interface';
import { environment } from '../../environments/environment';
import { ClarinSafeHtmlPipe } from '../shared/utils/clarin-safehtml.pipe';

describe('StaticPageComponent', () => {
let component: StaticPageComponent;
let fixture: ComponentFixture<StaticPageComponent>;

let htmlContentService: HtmlContentService;
let localeService: any;
let appConfig: any;

beforeEach(async () => {
htmlContentService = jasmine.createSpyObj('htmlContentService', {
fetchHtmlContent: of('<div>TEST MESSAGE</div>')
fetchHtmlContent: of('<div id="idShouldNotBeRemoved">TEST MESSAGE</div>')
});
localeService = jasmine.createSpyObj('LocaleService', {
getCurrentLanguageCode: jasmine.createSpy('getCurrentLanguageCode'),
});

appConfig = Object.assign(environment, {
ui: {
namespace: 'testNamespace'
}
});

TestBed.configureTestingModule({
declarations: [ StaticPageComponent ],
declarations: [ StaticPageComponent, ClarinSafeHtmlPipe ],
imports: [
TranslateModule.forRoot()
],
providers: [
{ provide: HtmlContentService, useValue: htmlContentService },
{ provide: Router, useValue: new RouterMock() },
{ provide: LocaleService, useValue: localeService }
{ provide: LocaleService, useValue: localeService },
{ provide: APP_CONFIG, useValue: appConfig }
]
});

Expand All @@ -51,6 +62,6 @@ describe('StaticPageComponent', () => {
// Load `TEST MESSAGE`
it('should load html file content', async () => {
await component.ngOnInit();
expect(component.htmlContent.value).toBe('<div>TEST MESSAGE</div>');
expect(component.htmlContent.value).toBe('<div id="idShouldNotBeRemoved">TEST MESSAGE</div>');
});
});
36 changes: 30 additions & 6 deletions src/app/static-page/static-page.component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Component, OnInit } from '@angular/core';
import { Component, Inject, OnInit } from '@angular/core';
import { HtmlContentService } from '../shared/html-content.service';
import { BehaviorSubject, firstValueFrom } from 'rxjs';
import { Router } from '@angular/router';
import { isEmpty, isNotEmpty } from '../shared/empty.util';
import { LocaleService } from '../core/locale/locale.service';
import { STATIC_FILES_DEFAULT_ERROR_PAGE_PATH, STATIC_FILES_PROJECT_PATH } from './static-page-routing-paths';
import { APP_CONFIG, AppConfig } from '../../config/app-config.interface';

/**
* Component which load and show static files from the `static-files` folder.
Expand All @@ -17,15 +18,17 @@ import { STATIC_FILES_DEFAULT_ERROR_PAGE_PATH, STATIC_FILES_PROJECT_PATH } from
})
export class StaticPageComponent implements OnInit {
htmlContent: BehaviorSubject<string> = new BehaviorSubject<string>('');
htmlFileName: string;

constructor(private htmlContentService: HtmlContentService,
private router: Router,
private localeService: LocaleService) { }
private localeService: LocaleService,
@Inject(APP_CONFIG) protected appConfig?: AppConfig) { }

async ngOnInit(): Promise<void> {
let url = '';
// Fetch html file name from the url path. `static/some_file.html`
let htmlFileName = this.getHtmlFileName();
this.htmlFileName = this.getHtmlFileName();

// Get current language
let language = this.localeService.getCurrentLanguageCode();
Expand All @@ -35,15 +38,15 @@ export class StaticPageComponent implements OnInit {
// Try to find the html file in the translated package. `static-files/language_code/some_file.html`
// Compose url
url = STATIC_FILES_PROJECT_PATH;
url += isEmpty(language) ? '/' + htmlFileName : '/' + language + '/' + htmlFileName;
url += isEmpty(language) ? '/' + this.htmlFileName : '/' + language + '/' + this.htmlFileName;
let potentialContent = await firstValueFrom(this.htmlContentService.fetchHtmlContent(url));
if (isNotEmpty(potentialContent)) {
this.htmlContent.next(potentialContent);
return;
}

// If the file wasn't find, get the non-translated file from the default package.
url = STATIC_FILES_PROJECT_PATH + '/' + htmlFileName;
url = STATIC_FILES_PROJECT_PATH + '/' + this.htmlFileName;
potentialContent = await firstValueFrom(this.htmlContentService.fetchHtmlContent(url));
if (isNotEmpty(potentialContent)) {
this.htmlContent.next(potentialContent);
Expand All @@ -54,6 +57,27 @@ export class StaticPageComponent implements OnInit {
await this.loadErrorPage();
}

processLinks(e) {
const element: HTMLElement = e.target;
if (element.nodeName === 'A') {
e.preventDefault();
const href = element.getAttribute('href')?.replace('/', '');
let redirectUrl = window.location.origin + this.appConfig.ui.nameSpace + '/static/';
// Start with `#` - redirect to the fragment
if (href.startsWith('#')) {
redirectUrl += this.htmlFileName + href;
} else if (href.startsWith('.')) {
// Redirect using namespace e.g. `./test.html` -> `<UI_PATH>/namespace/static/test.html`
redirectUrl += href.replace('.', '') + '.html';
} else {
// Redirect without using namespace e.g. `/test.html` -> `<UI_PATH>/test.html`
redirectUrl = redirectUrl.replace(this.appConfig.ui.nameSpace, '') + href;
}
// Call redirect
window.location.href = redirectUrl;
}
}

/**
* Load file name from the URL - `static/FILE_NAME.html`
* @private
Expand All @@ -69,7 +93,7 @@ export class StaticPageComponent implements OnInit {
}

// If the url is too long take just the first string after `/static` prefix.
return urlInList[1];
return urlInList[1]?.split('#')?.[0];
}

/**
Expand Down
10 changes: 6 additions & 4 deletions src/app/static-page/static-page.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ import { CommonModule } from '@angular/common';

import { StaticPageRoutingModule } from './static-page-routing.module';
import { StaticPageComponent } from './static-page.component';
import { SharedModule } from '../shared/shared.module';


@NgModule({
declarations: [
StaticPageComponent
],
imports: [
CommonModule,
StaticPageRoutingModule,
]
imports: [
CommonModule,
StaticPageRoutingModule,
SharedModule,
]
})
export class StaticPageModule { }
Binary file added src/assets/images/static-pages/bibtex.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/static-pages/refbox.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/static-pages/step1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/static-pages/step2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/static-pages/step2_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/static-pages/step3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/static-pages/step4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/static-pages/step4_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/static-pages/step5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/static-pages/step6_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/static-pages/step6_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/static-pages/step6_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
160 changes: 160 additions & 0 deletions src/static-files/about.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<div id="faq-like">

<h2 id="ufal-point-faq">LINDAT/CLARIAH-CZ repository About and Policies</h2>
<div>hosted at <a href="http://ufal.mff.cuni.cz/">Institute of Formal and Applied Linguistics, Charles University</a></div>

<hr />
<ul id="faqs-list">
<li><a href="#mission-statement">Mission Statement</a></li>
<li><a href="#terms-of-service">Terms of Service</a></li>
<li><a href="#about-repository">About Repository</a></li>
<li><a href="#about-ufal">About UFAL</a></li>
<li><a href="#about-contracts">License Agreement and Contracts</a></li>
<li><a href="#about-ipr">Intellectual Property Rights</a></li>
<li><a href="#privacy-policy">Privacy Policy</a></li>
<li><a href="#metadata-policy">Metadata Policy</a></li>
<li><a href="#preservation-policy">Preservation Policy</a></li>
<li><a href="./cite">Citing Data Policy</a></li>
</ul>
<hr />
<div>
<h3 id="mission-statement">Mission Statement</h3>
<br/>
<p>
The ultimate objective of CLARIN ERIC (which LINDAT/CLARIAH-CZ is part of) is to advance research in humanities
and social sciences by giving researchers unified single sign-on access to a platform which integrates language-based resources and advanced tools at a European level. This shall be implemented by the construction and operation of a shared distributed infrastructure that aims at making language resources, technology and expertise available to the humanities and social sciences (henceforth abbreviated HSS) research communities at large.
See more information about <a href="/about-lindat-clarin">LINDAT/CLARIAH-CZ</a>.
</p>
<p>
To know more about CLARIN ERIC visit <a href="http://www.clarin.eu/sites/default/files/centres-CLARIN-ShortGuide.pdf">CLARIN-ShortGuide.pdf</a>
</p>
</div>
<br/>
<div>
<h3 id="terms-of-service">Terms of Service</h3>
<p>
To achieve our mission statement,we set out some ground rules through the <a href="./terms-of-service">Terms of Service</a>. By accessing or using any kind of data or services provided by the Repository, you agree to abide by the Terms contained in the above mentioned document.
</p>
<p>
Data in LINDAT/CLARIAH-CZ repository are made available under the licence attached to the resources. In case there is no licence, data is made freely available for access, printing and download for the purposes of non-commercial research or private study.

Users <strong>must</strong> acknowledge in any publication, the Deposited Work using a persistent identifier (see <a href="./cite">Citing Data</a>), its original author(s)/creator(s), and any publisher where applicable. Full items must not be harvested by robots except transiently for full-text indexing or citation analysis. Full items must not be sold commercially unless explicitly granted by the attached licence without formal permission of the copyright holders.
</p>
</div>

<br/>
<div>
<h3 id="about-repository">About Repository</h3>
<p>It is like a library for linguistic data and tools.</p>
<ul>
<li>Search for data and tools and easily download them.</li>
<li>Deposit the data and be sure it is safely stored, everyone
can find it, use it, and correctly cite it (giving you credit)</li>
</ul>
</div>
<br/>
<div>
<h3 id="about-ufal">About UFAL</h3>
<p>
The Institute of Formal and Applied Linguistics (UFAL) at the Computer Science School, Faculty of Mathematics and Physics, Charles University, Czech Republic was established in 1990 as a continuation of the research and teaching activities carried out by the former Laboratory of Algebraic Linguistics since the early 60s at the Faculty of Philosophy and later at the Faculty of Mathematics and Physics, Charles University in Prague, is a primarily research department working on many topics in the area of Computational Linguistics, and on many research projects both nationally and internationally. However, the Institute of Formal and Applied Linguistics is also a regular department in the sense that it carries a comprehensive teaching program both for the Master's degree (Mgr., or MSc.) as well as for a doctorate (Ph.D.) in Computational Linguistics. Both programs are taught in Czech and English. The Institute is also a member of the double-degree "Master's LCT programme" of the EU. Students also can take advantage of the Erasmus program for typically semester-long stays at partner Universities abroad.
</p>
</div>
<br/>
<div>
<h3 id="about-contracts">License Agreement and Contracts</h3>
<p>At the moment, UFAL distinguishes three types of contracts.</p>
<ul>
<li>For every deposit, we enter into a standard contract with the submitter, the so-called <a id="distribution-link" href="contract">"Distribution License Agreement"</a>, in which we describe our rights and duties and the submitter acknowledges that they have the right to submit the data and gives us (the repository centre) right to distribute the data on their behalf.</li>
<li>Everyone who downloads data is bound by the licence assigned to the item - in order to download protected data, one has to be authenticated and needs to electronically sign the licence. A list of available licenses in our repository can be found <a href="licenses" id="available-licenses">here.</a></li>
<li>For submitters, there is a possibility for setting custom licences to items during the submission workflow.</li>
</ul>
</div>
<br/>
<div>
<h3 id="about-ipr">Intellectual Property Rights</h3>
<p>
As mentioned in the section <a href="#about-contracts">License Agreement and Contracts</a>, we require the depositor of data or tools to sign a Distribution License Agreement, which specifies that they have the right to submit the data and gives us (the repository centre) right to distribute the data on their behalf. This means that depositors are solely responsible for taking care of IPR issues before publishing data or tools by submitting them to us.
<br/>
Should anyone have a suspicion that any of the datasets or tools in our repository violate Intellectual Property Rights, they should contact us immediately at our help desk.
</p>
</div>
<br/>

<div>
<h3 id="privacy-policy">Privacy Policy</h3>
<p>Read our <a href="https://lindat.mff.cuni.cz/privacypolicy.html">Privacy Policy</a> in order to learn how we manage personal data collected by the LINDAT/CLARIAH-CZ repository and services.
</p>
</div>
<br/>

<div>
<h3 id="metadata-policy">Metadata Policy</h3>
<p>
Deposited content must be accompanied by <a href="metadata">sufficient metadata</a> describing its content, provenance and formats in order to support its preservation and dissemination. Metadata are freely accessible and are distributed in the public domain (under <a href="http://creativecommons.org/about/cc0">CC0</a>). However, we reserve the right to be informed about commercial usage of metadata from LINDAT/CLARIAH-CZ repository including a description of your use case at <a class="helpdesk-tolink" href="#">Help Desk</a>.
</p>
</div>
<br/>

<div>
<h3 id="preservation-policy">Preservation Policy</h3>
<p>
LINDAT/CLARIAH-CZ is committed to the long-term care of items deposited in the repository, to preserve the
research and to help in keeping research replicable and strives to adopt the
current best practice in digital preservation. See the <a href="#mission-statement">Mission Statement</a>.
We follow best practice guidelines, standards and regulations set forth by CLARIN, OAIS and/or Charles
University.
</p>
<p>
In order to stay a reliable and trustworthy repository, we undergo periodical assessments by CLARIN ERIC and
<a href="https://www.coretrustseal.org/wp-content/uploads/2019/08/LINDAT-CLARIN.pdf">CTS</a> (formerly DSA).
</p>
<p>
To fulfill the commitments, the repository ensures that datasets are ingested and distributed in
accordance with their license (see <a href="#about-contracts">agreements and contracts</a>). Sometimes
(for licenses that do not permit public access) this means only authorized users can access the dataset.
</p>
<p>
The submission workflow as described in <a href="deposit">deposit</a> and the work of our editors ensures
discoverability (by requiring accurate <a href="#metadata-policy">metadata</a>) via our search engine,
externally through OAI-PMH and in page metadata for certain web crawlers. Metadata are freely accessible.
</p>
<p>
There are various automated procedures including fixity checks, to ensure integrity of the submitted
datasets and completeness of metadata. On the
system level we employ various on-site and off-site backup strategies and hardware monitoring. The
datasets are accessible online.
</p>
<p>
We view data and tools as primary research outputs, each submission receives a Persistent IDentifier for reference and
the users are <a href="cite">guided to</a> use them. Changes in a dataset after it has been published are
not permitted, new submission is required instead. The old and new submissions are linked through their
metadata (see <a href="https://github.com/ufal/clarin-dspace/wiki/New-Version-Guide">new version
guide</a> for more details).
</p>
<p>
Through regular participation in CLARIN activities, Open Repositories and various other meetings, schools
and conferences, the repository staff is informed of new developments in technologies and/or initiatives.
</p>
<p>
The various export options offered by the repository system (DSpace) ensures that data and their metadata
are not locked in and can be moved to a different repository system.
</p>
<p>
The repository encourages the usage of specific file formats as recommended by CLARIN. The preferred file
formats will change over time, in which case the repository will make every effort to migrate to other
formats, while keeping originals intact for reproducibility purposes (ie. migrated item will be a new
repository record linked to the old). The guiding principles for format selection are: open standards are
preferred over proprietary standards, formats should be well-documented, verifiable and proven,
text-based formats are preferred over binary formats where possible, in the case of digitalization of analogue signal lossless or no compression is recommended.
</p>
<p>
In the case of a withdrawal of funding, the repositories content would be transferred to another CLARIN
centre. While the legal aspects of the process of relocating data to another institution are underway the
hosting institute (UFAL) offers a timeframe of at least 10 years, in which it will provide access to the
data.
</p>
</div>
<br/>


</div>
Loading

0 comments on commit 5e3c540

Please sign in to comment.