- npm updates for webpack-encore and postcss-loader - DatasetExtension.ts: use relation contributors for PersonContributor - added DoiClient.ts and DoiClientContract.ts - rozes.ts: addes routes for creating and storing doi identifier - addes xslt doi_datacite.xslt needed for registering DOI identifier
This commit is contained in:
parent
ebc62d9117
commit
c9ba7d6adc
|
@ -42,7 +42,8 @@
|
||||||
"@eidellev/adonis-stardust",
|
"@eidellev/adonis-stardust",
|
||||||
"./providers/QueryBuilderProvider",
|
"./providers/QueryBuilderProvider",
|
||||||
"./providers/TokenWorkerProvider",
|
"./providers/TokenWorkerProvider",
|
||||||
"@adonisjs/redis"
|
"@adonisjs/redis",
|
||||||
|
"./providers/DoiProvider"
|
||||||
],
|
],
|
||||||
"metaFiles": [
|
"metaFiles": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@ import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
||||||
import { Client } from '@opensearch-project/opensearch';
|
import { Client } from '@opensearch-project/opensearch';
|
||||||
import User from 'App/Models/User';
|
import User from 'App/Models/User';
|
||||||
import Dataset from 'App/Models/Dataset';
|
import Dataset from 'App/Models/Dataset';
|
||||||
|
import DatasetIdentifier from 'App/Models/DatasetIdentifier';
|
||||||
import XmlModel from 'App/Library/XmlModel';
|
import XmlModel from 'App/Library/XmlModel';
|
||||||
import { XMLBuilder } from 'xmlbuilder2/lib/interfaces';
|
import { XMLBuilder } from 'xmlbuilder2/lib/interfaces';
|
||||||
import { create } from 'xmlbuilder2';
|
import { create } from 'xmlbuilder2';
|
||||||
|
@ -10,6 +11,12 @@ import { transform } from 'saxon-js';
|
||||||
import type { ModelQueryBuilderContract } from '@ioc:Adonis/Lucid/Orm';
|
import type { ModelQueryBuilderContract } from '@ioc:Adonis/Lucid/Orm';
|
||||||
import { schema, CustomMessages } from '@ioc:Adonis/Core/Validator';
|
import { schema, CustomMessages } from '@ioc:Adonis/Core/Validator';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
|
import Index from 'App/Library/Utils/Index';
|
||||||
|
import { getDomain } from 'App/Utils/utility-functions';
|
||||||
|
import { DoiClient } from 'App/Library/Doi/DoiClient';
|
||||||
|
import DoiClientException from 'App/Exceptions/DoiClientException';
|
||||||
|
import Logger from '@ioc:Adonis/Core/Logger';
|
||||||
|
import { HttpException } from 'node-exceptions';
|
||||||
|
|
||||||
// Create a new instance of the client
|
// Create a new instance of the client
|
||||||
const client = new Client({ node: 'http://localhost:9200' }); // replace with your OpenSearch endpoint
|
const client = new Client({ node: 'http://localhost:9200' }); // replace with your OpenSearch endpoint
|
||||||
|
@ -66,6 +73,7 @@ export default class DatasetsController {
|
||||||
.where('editor_id', user.id)
|
.where('editor_id', user.id)
|
||||||
.doesntHave('identifier', 'and');
|
.doesntHave('identifier', 'and');
|
||||||
})
|
})
|
||||||
|
// .preload('identifier')
|
||||||
.preload('titles')
|
.preload('titles')
|
||||||
.preload('user', (query) => query.select('id', 'login'))
|
.preload('user', (query) => query.select('id', 'login'))
|
||||||
.preload('editor', (query) => query.select('id', 'login'))
|
.preload('editor', (query) => query.select('id', 'login'))
|
||||||
|
@ -273,13 +281,79 @@ export default class DatasetsController {
|
||||||
dataset.publisher_name = publisherName;
|
dataset.publisher_name = publisherName;
|
||||||
|
|
||||||
if (await dataset.save()) {
|
if (await dataset.save()) {
|
||||||
|
const index_name = 'tethys-records';
|
||||||
|
await Index.indexDocument(dataset, index_name);
|
||||||
return response.toRoute('editor.dataset.list').flash('message', 'You have successfully published the dataset!');
|
return response.toRoute('editor.dataset.list').flash('message', 'You have successfully published the dataset!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async create({}: HttpContextContract) {}
|
public async doiCreate({ request, inertia }: HttpContextContract) {
|
||||||
|
const id = request.param('id');
|
||||||
|
const dataset = await Dataset.query()
|
||||||
|
.where('id', id)
|
||||||
|
.preload('titles')
|
||||||
|
.preload('descriptions')
|
||||||
|
// .preload('identifier')
|
||||||
|
.preload('authors')
|
||||||
|
.firstOrFail();
|
||||||
|
return inertia.render('Editor/Dataset/Doi', {
|
||||||
|
dataset,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public async store({}: HttpContextContract) {}
|
public async doiStore({ request, response }: HttpContextContract) {
|
||||||
|
const dataId = request.param('publish_id');
|
||||||
|
const dataset = await Dataset.query()
|
||||||
|
// .preload('xmlCache')
|
||||||
|
.where('publish_id', dataId)
|
||||||
|
.firstOrFail();
|
||||||
|
const xmlMeta = (await Index.getDoiRegisterString(dataset)) as string;
|
||||||
|
|
||||||
|
let prefix = '';
|
||||||
|
let base_domain = '';
|
||||||
|
const datacite_environment = process.env.DATACITE_ENVIRONMENT || 'debug';
|
||||||
|
if (datacite_environment === 'debug') {
|
||||||
|
prefix = process.env.DATACITE_TEST_PREFIX || '';
|
||||||
|
base_domain = process.env.TEST_BASE_DOMAIN || '';
|
||||||
|
} else if (datacite_environment === 'production') {
|
||||||
|
prefix = process.env.DATACITE_PREFIX || '';
|
||||||
|
base_domain = process.env.BASE_DOMAIN || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// register DOI:
|
||||||
|
const doiValue = prefix + '/tethys.' + dataset.publish_id; //'10.21388/tethys.213'
|
||||||
|
const landingPageUrl = 'https://doi.' + getDomain(base_domain) + '/' + prefix + '/tethys.' + dataset.publish_id; //https://doi.dev.tethys.at/10.21388/tethys.213
|
||||||
|
const doiClient = new DoiClient();
|
||||||
|
const dataciteResponse = await doiClient.registerDoi(doiValue, xmlMeta, landingPageUrl);
|
||||||
|
|
||||||
|
if (dataciteResponse?.status === 201) {
|
||||||
|
// if response OK 201; save the Identifier value into db
|
||||||
|
const doiIdentifier = new DatasetIdentifier();
|
||||||
|
doiIdentifier.value = doiValue;
|
||||||
|
doiIdentifier.dataset_id = dataset.id;
|
||||||
|
doiIdentifier.type = 'doi';
|
||||||
|
doiIdentifier.status = 'findable';
|
||||||
|
// save modified date of datset for re-caching model in db an update the search index
|
||||||
|
dataset.server_date_modified = DateTime.now();
|
||||||
|
|
||||||
|
// save updated dataset to db an index to OpenSearch
|
||||||
|
try {
|
||||||
|
await dataset.related('identifier').save(doiIdentifier);
|
||||||
|
const index_name = 'tethys-records';
|
||||||
|
await Index.indexDocument(dataset, index_name);
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error(`${__filename}: Indexing document ${dataset.id} failed: ${error.message}`);
|
||||||
|
// Log the error or handle it as needed
|
||||||
|
throw new HttpException(error.message);
|
||||||
|
}
|
||||||
|
return response.toRoute('editor.dataset.list').flash('message', 'You have successfully created a DOI for the dataset!');
|
||||||
|
} else {
|
||||||
|
const message = `Unexpected DataCite MDS response code ${dataciteResponse?.status}`;
|
||||||
|
// Log the error or handle it as needed
|
||||||
|
throw new DoiClientException(dataciteResponse?.status, message);
|
||||||
|
}
|
||||||
|
// return response.toRoute('editor.dataset.list').flash('message', xmlMeta);
|
||||||
|
}
|
||||||
|
|
||||||
public async show({}: HttpContextContract) {}
|
public async show({}: HttpContextContract) {}
|
||||||
|
|
||||||
|
@ -404,8 +478,6 @@ export default class DatasetsController {
|
||||||
|
|
||||||
public async destroy({}: HttpContextContract) {}
|
public async destroy({}: HttpContextContract) {}
|
||||||
|
|
||||||
public async syncOpensearch({}: HttpContextContract) {}
|
|
||||||
|
|
||||||
private async createXmlRecord(dataset: Dataset, datasetNode: XMLBuilder) {
|
private async createXmlRecord(dataset: Dataset, datasetNode: XMLBuilder) {
|
||||||
const domNode = await this.getDatasetXmlDomNode(dataset);
|
const domNode = await this.getDatasetXmlDomNode(dataset);
|
||||||
if (domNode) {
|
if (domNode) {
|
||||||
|
|
110
app/Controllers/Http/Editor/deleteDoiMetadata.xml
Normal file
110
app/Controllers/Http/Editor/deleteDoiMetadata.xml
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<root>
|
||||||
|
<Dataset>
|
||||||
|
<Rdr_Dataset Id="306" PublisherName="GeoSphere Austria" PublishId="213"
|
||||||
|
CreatingCorporation="Tethys RDR" Language="en" ServerState="published"
|
||||||
|
Type="measurementdata">
|
||||||
|
<CreatedAt Year="2023" Month="11" Day="30" Hour="10" Minute="20" Second="58"
|
||||||
|
UnixTimestamp="1701336058" Timezone="Europe/Berlin" />
|
||||||
|
<ServerDateModified Year="2024" Month="1" Day="22" Hour="12" Minute="28" Second="17"
|
||||||
|
UnixTimestamp="1705922897" Timezone="Europe/Berlin" />
|
||||||
|
<ServerDatePublished Year="2024" Month="1" Day="22" Hour="12" Minute="28" Second="8"
|
||||||
|
UnixTimestamp="1705922888" Timezone="Europe/Berlin" />
|
||||||
|
<TitleMain Id="682" DocumentId="306" Type="Main" Value="rewerewr" Language="en" />
|
||||||
|
<TitleAbstract Id="1017" DocumentId="306" Type="Abstract" Value="rewrewr" Language="en" />
|
||||||
|
<Licence Id="1" Active="true"
|
||||||
|
LinkLicence="https://creativecommons.org/licenses/by/4.0/deed.en"
|
||||||
|
LinkLogo="https://licensebuttons.net/l/by/4.0/88x31.png"
|
||||||
|
NameLong="Creative Commons Attribution 4.0 International (CC BY 4.0)"
|
||||||
|
Name="CC-BY-4.0" SortOrder="1" />
|
||||||
|
<PersonAuthor Id="1" Email="m.moser@univie.ac.at" FirstName="Michael" LastName="Moser"
|
||||||
|
Status="true" NameType="Personal" Role="author" SortOrder="1"
|
||||||
|
AllowEmailContact="false" />
|
||||||
|
<PersonContributor Id="28" Email="juergen.reitner@geologie.ac.at" FirstName="Jürgen"
|
||||||
|
LastName="Reitner" Status="false" NameType="Personal" Role="contributor"
|
||||||
|
SortOrder="1" AllowEmailContact="false" />
|
||||||
|
<Subject Id="143" Language="de" Type="Geoera" Value="Aletshausen-Langenneufnach Störung"
|
||||||
|
CreatedAt="2023-11-21 17:17:43" UpdatedAt="2023-11-21 17:17:43" />
|
||||||
|
<Subject Id="164" Language="de" Type="Geoera" Value="Wolfersberg-Moosach Störung"
|
||||||
|
ExternalKey="https://data.geoscience.earth/ncl/geoera/hotLime/faults/3503"
|
||||||
|
CreatedAt="2023-11-30 10:20:58" UpdatedAt="2023-11-30 10:20:58" />
|
||||||
|
<Subject Id="165" Language="en" Type="Uncontrolled" Value="wefwef"
|
||||||
|
CreatedAt="2023-11-30 10:20:58" UpdatedAt="2023-11-30 10:20:58" />
|
||||||
|
<File Id="1037" DocumentId="306" PathName="files/306/file-clpkzkkgq0001nds14fua5um6.png"
|
||||||
|
Label="freieIP.png" MimeType="image/png" FileSize="112237" VisibleInFrontdoor="true"
|
||||||
|
VisibleInOai="true" SortOrder="0" CreatedAt="2023-11-30 10:21:14"
|
||||||
|
UpdatedAt="2023-11-30 10:21:14" />
|
||||||
|
<Coverage Id="284" DatasetId="306" XMin="11.71142578125" XMax="14.414062500000002"
|
||||||
|
YMin="46.58906908309185" YMax="47.45780853075031" CreatedAt="2023-11-30 10:20:58"
|
||||||
|
UpdatedAt="2023-11-30 10:20:58" />
|
||||||
|
<Collection Id="21" RoleId="3" Number="551" Name="Geology, hydrology, meteorology"
|
||||||
|
ParentId="20" Visible="true" VisiblePublish="true" />
|
||||||
|
</Rdr_Dataset>
|
||||||
|
</Dataset>
|
||||||
|
</root>
|
||||||
|
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resource xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4"
|
||||||
|
xsi:schemaLocation="http://datacite.org/schema/kernel-4 http://schema.datacite.org/meta/kernel-4.3/metadata.xsd">
|
||||||
|
<identifier identifierType="DOI">10.21388/tethys.213</identifier>
|
||||||
|
<creators>
|
||||||
|
<creator>
|
||||||
|
<creatorName nameType="Personal">Moser, Michael</creatorName>
|
||||||
|
<givenName>Michael</givenName>
|
||||||
|
<familyName>Moser</familyName>
|
||||||
|
<affiliation>GBA</affiliation>
|
||||||
|
</creator>
|
||||||
|
</creators>
|
||||||
|
<titles>
|
||||||
|
<title xml:lang="en">rewerewr</title>
|
||||||
|
</titles>
|
||||||
|
<publisher>Tethys RDR</publisher>
|
||||||
|
<publicationYear>2024</publicationYear>
|
||||||
|
<subjects>
|
||||||
|
<subject xml:lang="de">Aletshausen-Langenneufnach Störung</subject>
|
||||||
|
<subject xml:lang="de">Wolfersberg-Moosach Störung</subject>
|
||||||
|
<subject xml:lang="en">wefwef</subject>
|
||||||
|
</subjects>
|
||||||
|
<language>en</language>
|
||||||
|
<contributors>
|
||||||
|
<contributor contributorType="RegistrationAuthority">
|
||||||
|
<contributorName>Jürgen Reitner</contributorName>
|
||||||
|
</contributor>
|
||||||
|
</contributors>
|
||||||
|
<dates>
|
||||||
|
<date dateType="Created">2023-11-30</date>
|
||||||
|
</dates>
|
||||||
|
<version>1</version>
|
||||||
|
<resourceType resourceTypeGeneral="Dataset">Dataset</resourceType>
|
||||||
|
<alternateIdentifiers>
|
||||||
|
<alternateIdentifier alternateIdentifierType="url">https://www.tethys.at/dataset/213</alternateIdentifier>
|
||||||
|
</alternateIdentifiers>
|
||||||
|
<rightsList>
|
||||||
|
<rights xml:lang="" rightsURI="https://creativecommons.org/licenses/by/4.0/deed.en"
|
||||||
|
schemeURI="https://spdx.org/licenses/" rightsIdentifierScheme="SPDX"
|
||||||
|
rightsIdentifier="CC-BY-4.0">Creative Commons Attribution 4.0 International (CC BY 4.0)</rights>
|
||||||
|
<rights rightsURI="info:eu-repo/semantics/openAccess">Open Access</rights>
|
||||||
|
</rightsList>
|
||||||
|
<sizes>
|
||||||
|
<size>1 datasets</size>
|
||||||
|
</sizes>
|
||||||
|
<formats>
|
||||||
|
<format>image/png</format>
|
||||||
|
</formats>
|
||||||
|
<descriptions>
|
||||||
|
<description xml:lang="en" descriptionType="Abstract">rewrewr</description>
|
||||||
|
</descriptions>
|
||||||
|
<geoLocations>
|
||||||
|
<geoLocation>
|
||||||
|
<geoLocationBox>
|
||||||
|
<westBoundLongitude>11.71142578125</westBoundLongitude>
|
||||||
|
<eastBoundLongitude>14.414062500000002</eastBoundLongitude>
|
||||||
|
<southBoundLatitude>46.58906908309185</southBoundLatitude>
|
||||||
|
<northBoundLatitude>47.45780853075031</northBoundLatitude>
|
||||||
|
</geoLocationBox>
|
||||||
|
</geoLocation>
|
||||||
|
</geoLocations>
|
||||||
|
</resource>
|
12
app/Exceptions/DoiClientException.ts
Normal file
12
app/Exceptions/DoiClientException.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
class DoiClientException extends Error {
|
||||||
|
public status: number;
|
||||||
|
public message: string;
|
||||||
|
|
||||||
|
constructor(status: number, message: string) {
|
||||||
|
super(message);
|
||||||
|
this.status = status;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DoiClientException;
|
119
app/Library/Doi/DoiClient.ts
Normal file
119
app/Library/Doi/DoiClient.ts
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
// import { Client } from 'guzzle';
|
||||||
|
// import { Log } from '@adonisjs/core/build/standalone';
|
||||||
|
// import { DoiInterface } from './interfaces/DoiInterface';
|
||||||
|
import DoiClientContract from 'App/Library/Doi/DoiClientContract';
|
||||||
|
import DoiClientException from 'App/Exceptions/DoiClientException';
|
||||||
|
import { StatusCodes } from 'http-status-codes';
|
||||||
|
import Logger from '@ioc:Adonis/Core/Logger';
|
||||||
|
import axios, {AxiosResponse} from 'axios';
|
||||||
|
|
||||||
|
export class DoiClient implements DoiClientContract {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
serviceUrl: string;
|
||||||
|
// prefix: string;
|
||||||
|
// base_domain: string;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
const datacite_environment = process.env.DATACITE_ENVIRONMENT || 'debug';
|
||||||
|
if (datacite_environment === 'debug') {
|
||||||
|
this.username = process.env.DATACITE_TEST_USERNAME || '';
|
||||||
|
this.password = process.env.DATACITE_TEST_PASSWORD || '';
|
||||||
|
this.serviceUrl = process.env.DATACITE_TEST_SERVICE_URL || '';
|
||||||
|
// this.prefix = process.env.DATACITE_TEST_PREFIX || '';
|
||||||
|
// this.base_domain = process.env.TEST_BASE_DOMAIN || '';
|
||||||
|
} else if (datacite_environment === 'production') {
|
||||||
|
this.username = process.env.DATACITE_USERNAME || '';
|
||||||
|
this.password = process.env.DATACITE_PASSWORD || '';
|
||||||
|
this.serviceUrl = process.env.DATACITE_SERVICE_URL || '';
|
||||||
|
// this.prefix = process.env.DATACITE_PREFIX || '';
|
||||||
|
// this.base_domain = process.env.BASE_DOMAIN || '';
|
||||||
|
}
|
||||||
|
if (this.username === '' || this.password === '' || this.serviceUrl === '') {
|
||||||
|
const message = 'issing configuration settings to properly initialize DOI client';
|
||||||
|
Logger.error(message);
|
||||||
|
throw new DoiClientException(StatusCodes.BAD_REQUEST, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a DOI with the given identifier
|
||||||
|
*
|
||||||
|
* @param doiValue The desired DOI identifier e.g. '10.5072/tethys.999',
|
||||||
|
* @param xmlMeta
|
||||||
|
* @param landingPageUrl e.g. https://www.tethys.at/dataset/1
|
||||||
|
*
|
||||||
|
* @return Promise<number> The http response in the form of a axios response
|
||||||
|
*/
|
||||||
|
public async registerDoi(doiValue: string, xmlMeta: string, landingPageUrl: string): Promise<AxiosResponse<any>> {
|
||||||
|
//step 1: register metadata via xml upload
|
||||||
|
// state draft
|
||||||
|
let response;
|
||||||
|
let url = `${this.serviceUrl}/metadata/${doiValue}`; //https://mds.test.datacite.org/metadata/10.21388/tethys.213
|
||||||
|
const auth = {
|
||||||
|
username: this.username,
|
||||||
|
password: this.password,
|
||||||
|
};
|
||||||
|
let headers = {
|
||||||
|
'Content-Type': 'application/xml;charset=UTF-8',
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
response = await axios.put(url, xmlMeta, {
|
||||||
|
auth,
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
const message = `request to ${url} failed with ${error.message}`;
|
||||||
|
// Handle the error, log it, or rethrow as needed
|
||||||
|
Logger.error(message);
|
||||||
|
throw new DoiClientException(StatusCodes.SERVICE_UNAVAILABLE, message);
|
||||||
|
}
|
||||||
|
// let test = response.data; // 'OK (10.21388/TETHYS.213)'
|
||||||
|
|
||||||
|
// Response Codes
|
||||||
|
// 201 Created: operation successful
|
||||||
|
// 401 Unauthorised: no login
|
||||||
|
// 403 Forbidden: login problem, quota exceeded
|
||||||
|
// 415 Wrong Content Type : Not including content type in the header.
|
||||||
|
// 422 Unprocessable Entity : invalid XML
|
||||||
|
if (response.status !== 201) {
|
||||||
|
const message = 'unexpected DataCite MDS response code ' + response.status;
|
||||||
|
// $this->log($message, 'err');
|
||||||
|
throw new DoiClientException(response.status, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// step 2: Register the DOI name
|
||||||
|
// // DOI und URL der Frontdoor des zugehörigen Dokuments übergeben: state findable
|
||||||
|
// const url2 = this.serviceUrl + "/doi/" + doiValue;
|
||||||
|
url = `${this.serviceUrl}/doi/${doiValue}`; //'https://mds.test.datacite.org/doi/10.21388/tethys.213'
|
||||||
|
headers = {
|
||||||
|
'Content-Type': 'text/plain;charset=UTF-8',
|
||||||
|
};
|
||||||
|
const data = `doi=${doiValue}\nurl=${landingPageUrl}`;
|
||||||
|
try {
|
||||||
|
response = await axios.put(url, data, {
|
||||||
|
auth,
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Access the response data using response.data
|
||||||
|
// Do something with the response.data
|
||||||
|
} catch (error) {
|
||||||
|
const message = `request to ${url} failed with ${error.message}`;
|
||||||
|
// Handle the error, log it, or rethrow as needed
|
||||||
|
throw new DoiClientException(response.status, message);
|
||||||
|
}
|
||||||
|
// Response Codes
|
||||||
|
// 201 Created: operation successful
|
||||||
|
// 400 Bad Request: request body must be exactly two lines: DOI and URL; wrong domain, wrong prefix;
|
||||||
|
// 401 Unauthorised: no login
|
||||||
|
// 403 Forbidden: login problem, quota exceeded
|
||||||
|
// 412 Precondition failed: metadata must be uploaded first.
|
||||||
|
if (response.status != 201) {
|
||||||
|
const message = 'unexpected DataCite MDS response code ' + response.status;
|
||||||
|
Logger.error(message);
|
||||||
|
throw new DoiClientException(response.status, message);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
12
app/Library/Doi/DoiClientContract.ts
Normal file
12
app/Library/Doi/DoiClientContract.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// import ResumptionToken from './ResumptionToken';
|
||||||
|
|
||||||
|
export default interface DoiClientContract {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
serviceUrl: string;
|
||||||
|
// prefix: string;
|
||||||
|
// base_domain: string;
|
||||||
|
registerDoi(doiValue: string, xmlMeta: string, landingPageUrl: string);
|
||||||
|
// get(key: string): Promise<ResumptionToken | null>;
|
||||||
|
// set(token: ResumptionToken): Promise<string>;
|
||||||
|
}
|
|
@ -110,7 +110,7 @@ export default class Strategy {
|
||||||
private mapModelAttributes(myObject, childNode: XMLBuilder) {
|
private mapModelAttributes(myObject, childNode: XMLBuilder) {
|
||||||
Object.keys(myObject).forEach((prop) => {
|
Object.keys(myObject).forEach((prop) => {
|
||||||
let value = myObject[prop];
|
let value = myObject[prop];
|
||||||
console.log(`${prop}: ${value}`);
|
// console.log(`${prop}: ${value}`);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
if (value instanceof DateTime) {
|
if (value instanceof DateTime) {
|
||||||
value = value.toFormat('yyyy-MM-dd HH:mm:ss').trim();
|
value = value.toFormat('yyyy-MM-dd HH:mm:ss').trim();
|
||||||
|
|
194
app/Library/Utils/Index.ts
Normal file
194
app/Library/Utils/Index.ts
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
import Dataset from 'App/Models/Dataset';
|
||||||
|
import { Client } from '@opensearch-project/opensearch';
|
||||||
|
import { create } from 'xmlbuilder2';
|
||||||
|
import { transform } from 'saxon-js';
|
||||||
|
import XmlModel from 'App/Library/XmlModel';
|
||||||
|
import { XMLBuilder } from 'xmlbuilder2/lib/interfaces';
|
||||||
|
import Logger from '@ioc:Adonis/Core/Logger';
|
||||||
|
import { readFileSync } from 'fs';
|
||||||
|
import { DateTime } from 'luxon';
|
||||||
|
// import Config from '@ioc:Adonis/Core/Config';
|
||||||
|
import { getDomain } from 'App/Utils/utility-functions';
|
||||||
|
|
||||||
|
// const opensearchNode = process.env.OPENSEARCH_HOST || 'localhost';
|
||||||
|
// const client = new Client({ node: `http://${opensearchNode}` }); // replace with your OpenSearch endpoint
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// opensearchNode: process.env.OPENSEARCH_HOST || 'localhost',
|
||||||
|
client: new Client({ node: `http://${process.env.OPENSEARCH_HOST || 'localhost'}` }), // replace with your OpenSearch endpoint
|
||||||
|
|
||||||
|
async getDoiRegisterString(dataset: Dataset): Promise<string | undefined> {
|
||||||
|
try {
|
||||||
|
const proc = readFileSync('public/assets2/doi_datacite.sef.json');
|
||||||
|
const xsltParameter = {};
|
||||||
|
let xml = create({ version: '1.0', encoding: 'UTF-8', standalone: true }, '<root></root>');
|
||||||
|
const datasetNode = xml.root().ele('Dataset');
|
||||||
|
await createXmlRecord(dataset, datasetNode);
|
||||||
|
const xmlString = xml.end({ prettyPrint: false });
|
||||||
|
|
||||||
|
// set timestamp
|
||||||
|
const date = DateTime.now();
|
||||||
|
const unixTimestamp = date.toUnixInteger();
|
||||||
|
xsltParameter['unixTimestamp'] = unixTimestamp;
|
||||||
|
|
||||||
|
// set prefix
|
||||||
|
let prefix = '';
|
||||||
|
let base_domain = '';
|
||||||
|
const datacite_environment = process.env.DATACITE_ENVIRONMENT || 'debug';
|
||||||
|
if (datacite_environment === 'debug') {
|
||||||
|
prefix = process.env.DATACITE_TEST_PREFIX || '';
|
||||||
|
base_domain = process.env.TEST_BASE_DOMAIN || '';
|
||||||
|
} else if (datacite_environment === 'production') {
|
||||||
|
prefix = process.env.DATACITE_PREFIX || '';
|
||||||
|
base_domain = process.env.BASE_DOMAIN || '';
|
||||||
|
}
|
||||||
|
xsltParameter['prefix'] = prefix;
|
||||||
|
|
||||||
|
const repIdentifier = 'tethys';
|
||||||
|
xsltParameter['repIdentifier'] = repIdentifier;
|
||||||
|
|
||||||
|
let xmlOutput; // = xmlString;
|
||||||
|
try {
|
||||||
|
const result = await transform({
|
||||||
|
// stylesheetFileName: `${config.TMP_BASE_DIR}/data-quality/rules/iati.sef.json`,
|
||||||
|
stylesheetText: proc,
|
||||||
|
destination: 'serialized',
|
||||||
|
// sourceFileName: sourceFile,
|
||||||
|
sourceText: xmlString,
|
||||||
|
stylesheetParams: xsltParameter,
|
||||||
|
// logLevel: 10,
|
||||||
|
});
|
||||||
|
xmlOutput = result.principalResult;
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error('An error occurred while creating the user', error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return xmlOutput;
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error(`An error occurred while indexing datsaet with publish_id ${dataset.publish_id}.`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async indexDocument(dataset: Dataset, index_name: string): Promise<void> {
|
||||||
|
try {
|
||||||
|
const proc = readFileSync('public/assets2/solr.sef.json');
|
||||||
|
const doc: string = await this.getTransformedString(dataset, proc);
|
||||||
|
|
||||||
|
let document = JSON.parse(doc);
|
||||||
|
await this.client.index({
|
||||||
|
id: dataset.publish_id?.toString(),
|
||||||
|
index: index_name,
|
||||||
|
body: document,
|
||||||
|
refresh: true,
|
||||||
|
});
|
||||||
|
Logger.info(`dataset with publish_id ${dataset.publish_id} successfully indexed`);
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error(`An error occurred while indexing datsaet with publish_id ${dataset.publish_id}.`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async getTransformedString(dataset, proc): Promise<string> {
|
||||||
|
let xml = create({ version: '1.0', encoding: 'UTF-8', standalone: true }, '<root></root>');
|
||||||
|
const datasetNode = xml.root().ele('Dataset');
|
||||||
|
await createXmlRecord(dataset, datasetNode);
|
||||||
|
const xmlString = xml.end({ prettyPrint: false });
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await transform({
|
||||||
|
stylesheetText: proc,
|
||||||
|
destination: 'serialized',
|
||||||
|
sourceText: xmlString,
|
||||||
|
});
|
||||||
|
return result.principalResult;
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error(`An error occurred while creating the user, error: ${error.message},`);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Return the default global focus trap stack
|
||||||
|
*
|
||||||
|
* @return {import('focus-trap').FocusTrap[]}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// export const indexDocument = async (dataset: Dataset, index_name: string, proc: Buffer): Promise<void> => {
|
||||||
|
// try {
|
||||||
|
// const doc = await getJsonString(dataset, proc);
|
||||||
|
|
||||||
|
// let document = JSON.parse(doc);
|
||||||
|
// await client.index({
|
||||||
|
// id: dataset.publish_id?.toString(),
|
||||||
|
// index: index_name,
|
||||||
|
// body: document,
|
||||||
|
// refresh: true,
|
||||||
|
// });
|
||||||
|
// Logger.info(`dataset with publish_id ${dataset.publish_id} successfully indexed`);
|
||||||
|
// } catch (error) {
|
||||||
|
// Logger.error(`An error occurred while indexing datsaet with publish_id ${dataset.publish_id}.`);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const getJsonString = async (dataset, proc): Promise<string> => {
|
||||||
|
// let xml = create({ version: '1.0', encoding: 'UTF-8', standalone: true }, '<root></root>');
|
||||||
|
// const datasetNode = xml.root().ele('Dataset');
|
||||||
|
// await createXmlRecord(dataset, datasetNode);
|
||||||
|
// const xmlString = xml.end({ prettyPrint: false });
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// const result = await transform({
|
||||||
|
// stylesheetText: proc,
|
||||||
|
// destination: 'serialized',
|
||||||
|
// sourceText: xmlString,
|
||||||
|
// });
|
||||||
|
// return result.principalResult;
|
||||||
|
// } catch (error) {
|
||||||
|
// Logger.error(`An error occurred while creating the user, error: ${error.message},`);
|
||||||
|
// return '';
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
const createXmlRecord = async (dataset: Dataset, datasetNode: XMLBuilder): Promise<void> => {
|
||||||
|
const domNode = await getDatasetXmlDomNode(dataset);
|
||||||
|
if (domNode) {
|
||||||
|
// add frontdoor url and data-type
|
||||||
|
dataset.publish_id && addLandingPageAttribute(domNode, dataset.publish_id.toString());
|
||||||
|
addSpecInformation(domNode, 'data-type:' + dataset.type);
|
||||||
|
if (dataset.collections) {
|
||||||
|
for (const coll of dataset.collections) {
|
||||||
|
const collRole = coll.collectionRole;
|
||||||
|
addSpecInformation(domNode, collRole.oai_name + ':' + coll.number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
datasetNode.import(domNode);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDatasetXmlDomNode = async (dataset: Dataset): Promise<XMLBuilder | null> => {
|
||||||
|
const xmlModel = new XmlModel(dataset);
|
||||||
|
// xmlModel.setModel(dataset);
|
||||||
|
xmlModel.excludeEmptyFields();
|
||||||
|
xmlModel.caching = true;
|
||||||
|
// const cache = dataset.xmlCache ? dataset.xmlCache : null;
|
||||||
|
// dataset.load('xmlCache');
|
||||||
|
await dataset.load('xmlCache');
|
||||||
|
if (dataset.xmlCache) {
|
||||||
|
xmlModel.xmlCache = dataset.xmlCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return cache.getDomDocument();
|
||||||
|
const domDocument: XMLBuilder | null = await xmlModel.getDomDocument();
|
||||||
|
return domDocument;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addLandingPageAttribute = (domNode: XMLBuilder, dataid: string) => {
|
||||||
|
const baseDomain = process.env.OAI_BASE_DOMAIN || 'localhost';
|
||||||
|
const url = 'https://' + getDomain(baseDomain) + '/dataset/' + dataid;
|
||||||
|
// add attribute du dataset xml element
|
||||||
|
domNode.att('landingpage', url);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addSpecInformation= (domNode: XMLBuilder, information: string) => {
|
||||||
|
domNode.ele('SetSpec').att('Value', information);
|
||||||
|
};
|
|
@ -20,6 +20,9 @@ export default class DatasetIdentifier extends BaseModel {
|
||||||
@column({})
|
@column({})
|
||||||
public type: string;
|
public type: string;
|
||||||
|
|
||||||
|
@column({})
|
||||||
|
public status: string;
|
||||||
|
|
||||||
@column({})
|
@column({})
|
||||||
public value: string;
|
public value: string;
|
||||||
|
|
||||||
|
@ -38,4 +41,9 @@ export default class DatasetIdentifier extends BaseModel {
|
||||||
foreignKey: 'dataset_id',
|
foreignKey: 'dataset_id',
|
||||||
})
|
})
|
||||||
public dataset: BelongsTo<typeof Dataset>;
|
public dataset: BelongsTo<typeof Dataset>;
|
||||||
|
|
||||||
|
// // Specify the relationships to touch when this model is updated
|
||||||
|
// public static get touches() {
|
||||||
|
// return ['dataset'];
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ export default abstract class DatasetExtension extends LucidBaseModel {
|
||||||
sort_order: 'sort_order',
|
sort_order: 'sort_order',
|
||||||
allow_email_contact: 'allow_email_contact',
|
allow_email_contact: 'allow_email_contact',
|
||||||
},
|
},
|
||||||
relation: 'persons',
|
relation: 'contributors',
|
||||||
fetch: 'eager',
|
fetch: 'eager',
|
||||||
},
|
},
|
||||||
Reference: {
|
Reference: {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BaseCommand, flags } from '@adonisjs/core/build/standalone';
|
import { BaseCommand, flags } from '@adonisjs/core/build/standalone';
|
||||||
import Logger from '@ioc:Adonis/Core/Logger';
|
// import Logger from '@ioc:Adonis/Core/Logger';
|
||||||
import { XMLBuilder } from 'xmlbuilder2/lib/interfaces';
|
import { XMLBuilder } from 'xmlbuilder2/lib/interfaces';
|
||||||
import { create } from 'xmlbuilder2';
|
import { create } from 'xmlbuilder2';
|
||||||
import Dataset from 'App/Models/Dataset';
|
import Dataset from 'App/Models/Dataset';
|
||||||
|
@ -7,6 +7,7 @@ import XmlModel from 'App/Library/XmlModel';
|
||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
import { transform } from 'saxon-js';
|
import { transform } from 'saxon-js';
|
||||||
import { Client } from '@opensearch-project/opensearch';
|
import { Client } from '@opensearch-project/opensearch';
|
||||||
|
import { getDomain } from 'App/Utils/utility-functions';
|
||||||
|
|
||||||
const opensearchNode = process.env.OPENSEARCH_HOST || 'localhost';
|
const opensearchNode = process.env.OPENSEARCH_HOST || 'localhost';
|
||||||
const client = new Client({ node: `http://${opensearchNode}` }); // replace with your OpenSearch endpoint
|
const client = new Client({ node: `http://${opensearchNode}` }); // replace with your OpenSearch endpoint
|
||||||
|
@ -43,9 +44,9 @@ export default class IndexDatasets extends BaseCommand {
|
||||||
|
|
||||||
for (var dataset of datasets) {
|
for (var dataset of datasets) {
|
||||||
// Logger.info(`File publish_id ${dataset.publish_id}`);
|
// Logger.info(`File publish_id ${dataset.publish_id}`);
|
||||||
const jsonString = await this.getJsonString(dataset, proc);
|
// const jsonString = await this.getJsonString(dataset, proc);
|
||||||
// console.log(jsonString);
|
// console.log(jsonString);
|
||||||
await this.indexDocument(dataset, index_name, jsonString);
|
await this.indexDocument(dataset, index_name, proc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +58,23 @@ export default class IndexDatasets extends BaseCommand {
|
||||||
return await query;
|
return await query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async indexDocument(dataset: Dataset, index_name: string, proc: Buffer): Promise<void> {
|
||||||
|
try {
|
||||||
|
const doc = await this.getJsonString(dataset, proc);
|
||||||
|
|
||||||
|
let document = JSON.parse(doc);
|
||||||
|
await client.index({
|
||||||
|
id: dataset.publish_id?.toString(),
|
||||||
|
index: index_name,
|
||||||
|
body: document,
|
||||||
|
refresh: true,
|
||||||
|
});
|
||||||
|
this.logger.info(`dataset with publish_id ${dataset.publish_id} successfully indexed`);
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(`An error occurred while indexing datsaet with publish_id ${dataset.publish_id}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async getJsonString(dataset, proc) {
|
private async getJsonString(dataset, proc) {
|
||||||
let xml = create({ version: '1.0', encoding: 'UTF-8', standalone: true }, '<root></root>');
|
let xml = create({ version: '1.0', encoding: 'UTF-8', standalone: true }, '<root></root>');
|
||||||
const datasetNode = xml.root().ele('Dataset');
|
const datasetNode = xml.root().ele('Dataset');
|
||||||
|
@ -71,29 +89,16 @@ export default class IndexDatasets extends BaseCommand {
|
||||||
});
|
});
|
||||||
return result.principalResult;
|
return result.principalResult;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Logger.error(`An error occurred while creating the user, error: ${error.message},`);
|
this.logger.error(`An error occurred while creating the user, error: ${error.message},`);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async indexDocument(dataset: Dataset, index_name: string, doc: string): Promise<void> {
|
|
||||||
try {
|
|
||||||
let document = JSON.parse(doc);
|
|
||||||
await client.index({
|
|
||||||
id: dataset.publish_id?.toString(),
|
|
||||||
index: index_name,
|
|
||||||
body: document,
|
|
||||||
refresh: true,
|
|
||||||
});
|
|
||||||
Logger.info(`dataset with publish_id ${dataset.publish_id} successfully indexed`);
|
|
||||||
} catch (error) {
|
|
||||||
Logger.error(`An error occurred while indexing datsaet with publish_id ${dataset.publish_id}.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async createXmlRecord(dataset: Dataset, datasetNode: XMLBuilder): Promise<void> {
|
private async createXmlRecord(dataset: Dataset, datasetNode: XMLBuilder): Promise<void> {
|
||||||
const domNode = await this.getDatasetXmlDomNode(dataset);
|
const domNode = await this.getDatasetXmlDomNode(dataset);
|
||||||
if (domNode) {
|
if (domNode) {
|
||||||
|
dataset.publish_id && this.addLandingPageAttribute(domNode, dataset.publish_id.toString());
|
||||||
|
this.addSpecInformation(domNode, 'data-type:' + dataset.type);
|
||||||
datasetNode.import(domNode);
|
datasetNode.import(domNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,4 +118,15 @@ export default class IndexDatasets extends BaseCommand {
|
||||||
const domDocument: XMLBuilder | null = await xmlModel.getDomDocument();
|
const domDocument: XMLBuilder | null = await xmlModel.getDomDocument();
|
||||||
return domDocument;
|
return domDocument;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private addSpecInformation(domNode: XMLBuilder, information: string) {
|
||||||
|
domNode.ele('SetSpec').att('Value', information);
|
||||||
|
}
|
||||||
|
|
||||||
|
private addLandingPageAttribute(domNode: XMLBuilder, dataid: string) {
|
||||||
|
const baseDomain = process.env.OAI_BASE_DOMAIN || 'localhost';
|
||||||
|
const url = 'https://' + getDomain(baseDomain) + '/dataset/' + dataid;
|
||||||
|
// add attribute du dataset xml element
|
||||||
|
domNode.att('landingpage', url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
34
package-lock.json
generated
34
package-lock.json
generated
|
@ -56,7 +56,7 @@
|
||||||
"@japa/preset-adonis": "^1.2.0",
|
"@japa/preset-adonis": "^1.2.0",
|
||||||
"@japa/runner": "^2.5.1",
|
"@japa/runner": "^2.5.1",
|
||||||
"@mdi/js": "^7.1.96",
|
"@mdi/js": "^7.1.96",
|
||||||
"@symfony/webpack-encore": "^4.2.0",
|
"@symfony/webpack-encore": "^4.5.0",
|
||||||
"@tailwindcss/forms": "^0.5.2",
|
"@tailwindcss/forms": "^0.5.2",
|
||||||
"@types/clamscan": "^2.0.4",
|
"@types/clamscan": "^2.0.4",
|
||||||
"@types/leaflet": "^1.9.3",
|
"@types/leaflet": "^1.9.3",
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
"numeral": "^2.0.6",
|
"numeral": "^2.0.6",
|
||||||
"pinia": "^2.0.30",
|
"pinia": "^2.0.30",
|
||||||
"pino-pretty": "^10.0.0",
|
"pino-pretty": "^10.0.0",
|
||||||
"postcss-loader": "^7.0.2",
|
"postcss-loader": "^7.3.0",
|
||||||
"prettier": "^3.0.0",
|
"prettier": "^3.0.0",
|
||||||
"supertest": "^6.3.3",
|
"supertest": "^6.3.3",
|
||||||
"tailwindcss": "^3.2.4",
|
"tailwindcss": "^3.2.4",
|
||||||
|
@ -3304,9 +3304,9 @@
|
||||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
|
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/trace-mapping": {
|
"node_modules/@jridgewell/trace-mapping": {
|
||||||
"version": "0.3.21",
|
"version": "0.3.22",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz",
|
||||||
"integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==",
|
"integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/resolve-uri": "^3.1.0",
|
"@jridgewell/resolve-uri": "^3.1.0",
|
||||||
|
@ -4206,9 +4206,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/luxon": {
|
"node_modules/@types/luxon": {
|
||||||
"version": "3.4.1",
|
"version": "3.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.4.2.tgz",
|
||||||
"integrity": "sha512-m1KQEZZCITtheRhMVq5jDvAl0HwFhunLs7x6tpFFvUTJpKfmewS/Ymg+YA97/s8w1I1nC4pJyi0aAnn+vf3yew=="
|
"integrity": "sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/md5": {
|
"node_modules/@types/md5": {
|
||||||
"version": "2.3.5",
|
"version": "2.3.5",
|
||||||
|
@ -7010,9 +7010,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/core-js-compat": {
|
"node_modules/core-js-compat": {
|
||||||
"version": "3.35.0",
|
"version": "3.35.1",
|
||||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.0.tgz",
|
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.1.tgz",
|
||||||
"integrity": "sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw==",
|
"integrity": "sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"browserslist": "^4.22.2"
|
"browserslist": "^4.22.2"
|
||||||
|
@ -7939,9 +7939,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/dotenv": {
|
"node_modules/dotenv": {
|
||||||
"version": "16.3.1",
|
"version": "16.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz",
|
||||||
"integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
|
"integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
|
@ -8128,9 +8128,9 @@
|
||||||
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.4.639",
|
"version": "1.4.640",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.639.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.640.tgz",
|
||||||
"integrity": "sha512-CkKf3ZUVZchr+zDpAlNLEEy2NJJ9T64ULWaDgy3THXXlPVPkLu3VOs9Bac44nebVtdwl2geSj6AxTtGDOxoXhg==",
|
"integrity": "sha512-z/6oZ/Muqk4BaE7P69bXhUhpJbUM9ZJeka43ZwxsDshKtePns4mhBlh8bU5+yrnOnz3fhG82XLzGUXazOmsWnA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/emittery": {
|
"node_modules/emittery": {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
"dev": "node ace serve --watch",
|
"dev": "node ace serve --watch",
|
||||||
"compress:xslt": "./node_modules/xslt3/xslt3.js -xsl:public/assets2/datasetxml2oai-pmh.xslt -export:public/assets2/datasetxml2oai.sef.json -t -nogo '-ns:##html5'",
|
"compress:xslt": "./node_modules/xslt3/xslt3.js -xsl:public/assets2/datasetxml2oai-pmh.xslt -export:public/assets2/datasetxml2oai.sef.json -t -nogo '-ns:##html5'",
|
||||||
"compress:solr": "./node_modules/xslt3/xslt3.js -xsl:public/assets2/solr.xslt -export:public/assets2/solr.sef.json -t -nogo '-ns:##html5'",
|
"compress:solr": "./node_modules/xslt3/xslt3.js -xsl:public/assets2/solr.xslt -export:public/assets2/solr.sef.json -t -nogo '-ns:##html5'",
|
||||||
|
"compress:doi": "./node_modules/xslt3/xslt3.js -xsl:public/assets2/doi_datacite.xslt -export:public/assets2/doi_datacite.sef.json -t -nogo '-ns:##html5'",
|
||||||
"build": "node ace build --production",
|
"build": "node ace build --production",
|
||||||
"start": "node server.js",
|
"start": "node server.js",
|
||||||
"lint": "eslint . --ext=.ts",
|
"lint": "eslint . --ext=.ts",
|
||||||
|
@ -31,7 +32,7 @@
|
||||||
"@japa/preset-adonis": "^1.2.0",
|
"@japa/preset-adonis": "^1.2.0",
|
||||||
"@japa/runner": "^2.5.1",
|
"@japa/runner": "^2.5.1",
|
||||||
"@mdi/js": "^7.1.96",
|
"@mdi/js": "^7.1.96",
|
||||||
"@symfony/webpack-encore": "^4.2.0",
|
"@symfony/webpack-encore": "^4.5.0",
|
||||||
"@tailwindcss/forms": "^0.5.2",
|
"@tailwindcss/forms": "^0.5.2",
|
||||||
"@types/clamscan": "^2.0.4",
|
"@types/clamscan": "^2.0.4",
|
||||||
"@types/leaflet": "^1.9.3",
|
"@types/leaflet": "^1.9.3",
|
||||||
|
@ -53,7 +54,7 @@
|
||||||
"numeral": "^2.0.6",
|
"numeral": "^2.0.6",
|
||||||
"pinia": "^2.0.30",
|
"pinia": "^2.0.30",
|
||||||
"pino-pretty": "^10.0.0",
|
"pino-pretty": "^10.0.0",
|
||||||
"postcss-loader": "^7.0.2",
|
"postcss-loader": "^7.3.0",
|
||||||
"prettier": "^3.0.0",
|
"prettier": "^3.0.0",
|
||||||
"supertest": "^6.3.3",
|
"supertest": "^6.3.3",
|
||||||
"tailwindcss": "^3.2.4",
|
"tailwindcss": "^3.2.4",
|
||||||
|
|
40
providers/DoiProvider/index.ts
Normal file
40
providers/DoiProvider/index.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import type { ApplicationContract } from '@ioc:Adonis/Core/Application'
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Provider
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Your application is not ready when this file is loaded by the framework.
|
||||||
|
| Hence, the top level imports relying on the IoC container will not work.
|
||||||
|
| You must import them inside the life-cycle methods defined inside
|
||||||
|
| the provider class.
|
||||||
|
|
|
||||||
|
| @example:
|
||||||
|
|
|
||||||
|
| public async ready () {
|
||||||
|
| const Database = this.app.container.resolveBinding('Adonis/Lucid/Database')
|
||||||
|
| const Event = this.app.container.resolveBinding('Adonis/Core/Event')
|
||||||
|
| Event.on('db:query', Database.prettyPrint)
|
||||||
|
| }
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
export default class DoiProvider {
|
||||||
|
constructor(protected app: ApplicationContract) {}
|
||||||
|
|
||||||
|
public register() {
|
||||||
|
// Register your own bindings
|
||||||
|
}
|
||||||
|
|
||||||
|
public async boot() {
|
||||||
|
// All bindings are ready, feel free to use them
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ready() {
|
||||||
|
// App is ready
|
||||||
|
}
|
||||||
|
|
||||||
|
public async shutdown() {
|
||||||
|
// Cleanup, since app is going down
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
1
public/assets2/doi_datacite.sef.json
Normal file
1
public/assets2/doi_datacite.sef.json
Normal file
File diff suppressed because one or more lines are too long
443
public/assets2/doi_datacite.xslt
Normal file
443
public/assets2/doi_datacite.xslt
Normal file
|
@ -0,0 +1,443 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/**
|
||||||
|
* This file is part of TETHYS.
|
||||||
|
*
|
||||||
|
* LICENCE
|
||||||
|
* TETHYS is free software; you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation; either version 2 of the Licence, or any later version.
|
||||||
|
* OPUS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details. You should have received a copy of the GNU General Public License
|
||||||
|
* along with OPUS; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* @category Application
|
||||||
|
* @package Module_Oai
|
||||||
|
* @author Arno Kaimbacher <arno.kaimbacher@geologie.ac.at>
|
||||||
|
* @copyright Copyright (c) 2018-2019, GBA TETHYS development team
|
||||||
|
* @license http://www.gnu.org/licenses/gpl.html General Public License
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
/**
|
||||||
|
* Transforms the xml representation of an TETHYS model dataset to datacite
|
||||||
|
* xml as required by the OAI-PMH protocol.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<xsl:stylesheet version="3.0"
|
||||||
|
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||||
|
xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
|
||||||
|
<xsl:output method="xml" encoding="utf-8" indent="yes" />
|
||||||
|
|
||||||
|
<xsl:param name="unixTimestamp" />
|
||||||
|
<xsl:param name="prefix" />
|
||||||
|
<xsl:param name="repIdentifier" />
|
||||||
|
|
||||||
|
<xsl:template match="Rdr_Dataset">
|
||||||
|
<resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4" xsi:schemaLocation="http://datacite.org/schema/kernel-4 http://schema.datacite.org/meta/kernel-4.3/metadata.xsd">
|
||||||
|
<!-- <isReferenceQuality>true</isReferenceQuality>
|
||||||
|
<schemaVersion>4.3</schemaVersion>
|
||||||
|
<datacentreSymbol>RDR.GBA</datacentreSymbol> -->
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="Identifier">
|
||||||
|
<xsl:apply-templates select="Identifier" mode="oai_datacite" />
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<identifier identifierType="DOI">
|
||||||
|
<xsl:value-of select="$prefix" />
|
||||||
|
<xsl:text>/</xsl:text>
|
||||||
|
<xsl:value-of select="$repIdentifier" />
|
||||||
|
<xsl:text>.</xsl:text>
|
||||||
|
<xsl:value-of select="@PublishId" />
|
||||||
|
</identifier>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
|
||||||
|
<!--<datacite:creator>-->
|
||||||
|
<creators>
|
||||||
|
<xsl:apply-templates select="PersonAuthor" mode="oai_datacite">
|
||||||
|
<xsl:sort select="@SortOrder"/>
|
||||||
|
</xsl:apply-templates>
|
||||||
|
</creators>
|
||||||
|
<titles>
|
||||||
|
<xsl:apply-templates select="TitleMain" mode="oai_datacite" />
|
||||||
|
<xsl:apply-templates select="TitleAdditional" mode="oai_datacite" />
|
||||||
|
</titles>
|
||||||
|
<publisher>
|
||||||
|
<!-- <xsl:value-of select="@PublisherName" /> -->
|
||||||
|
<xsl:value-of select="@CreatingCorporation" />
|
||||||
|
</publisher>
|
||||||
|
<publicationYear>
|
||||||
|
<xsl:value-of select="ServerDatePublished/@Year" />
|
||||||
|
</publicationYear>
|
||||||
|
<subjects>
|
||||||
|
<xsl:apply-templates select="Subject" mode="oai_datacite" />
|
||||||
|
</subjects>
|
||||||
|
<language>
|
||||||
|
<xsl:value-of select="@Language" />
|
||||||
|
</language>
|
||||||
|
<xsl:if test="PersonContributor">
|
||||||
|
<contributors>
|
||||||
|
<xsl:apply-templates select="PersonContributor" mode="oai_datacite">
|
||||||
|
<xsl:sort select="@SortOrder"/>
|
||||||
|
</xsl:apply-templates>
|
||||||
|
</contributors>
|
||||||
|
</xsl:if>
|
||||||
|
<dates>
|
||||||
|
<xsl:call-template name="RdrDate2" />
|
||||||
|
</dates>
|
||||||
|
<version>
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="@Version">
|
||||||
|
<xsl:value-of select="@Version" />
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<xsl:text>1</xsl:text>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
</version>
|
||||||
|
<resourceType resourceTypeGeneral="Dataset">
|
||||||
|
<xsl:text>Dataset</xsl:text>
|
||||||
|
<!-- <xsl:value-of select="@Type" /> -->
|
||||||
|
</resourceType>
|
||||||
|
|
||||||
|
<alternateIdentifiers>
|
||||||
|
<xsl:call-template name="AlternateIdentifier" />
|
||||||
|
</alternateIdentifiers>
|
||||||
|
|
||||||
|
<xsl:if test="Reference">
|
||||||
|
<relatedIdentifiers>
|
||||||
|
<xsl:apply-templates select="Reference" mode="oai_datacite" />
|
||||||
|
</relatedIdentifiers>
|
||||||
|
</xsl:if>
|
||||||
|
<rightsList>
|
||||||
|
<xsl:apply-templates select="Licence" mode="oai_datacite" />
|
||||||
|
</rightsList>
|
||||||
|
<sizes>
|
||||||
|
<size>
|
||||||
|
<xsl:value-of select="count(File)" />
|
||||||
|
<xsl:text> datasets</xsl:text>
|
||||||
|
</size>
|
||||||
|
</sizes>
|
||||||
|
<formats>
|
||||||
|
<xsl:apply-templates select="File/@MimeType" mode="oai_datacite" />
|
||||||
|
</formats>
|
||||||
|
<descriptions>
|
||||||
|
<xsl:apply-templates select="TitleAbstract" mode="oai_datacite" />
|
||||||
|
<xsl:apply-templates select="TitleAbstractAdditional" mode="oai_datacite" />
|
||||||
|
</descriptions>
|
||||||
|
<geoLocations>
|
||||||
|
<xsl:apply-templates select="Coverage" mode="oai_datacite" />
|
||||||
|
<!-- <geoLocation>
|
||||||
|
<geoLocationBox>
|
||||||
|
<westBoundLongitude>6.58987</westBoundLongitude>
|
||||||
|
<eastBoundLongitude>6.83639</eastBoundLongitude>
|
||||||
|
<southBoundLatitude>50.16</southBoundLatitude>
|
||||||
|
<northBoundLatitude>50.18691</northBoundLatitude>
|
||||||
|
</geoLocationBox>
|
||||||
|
</geoLocation> -->
|
||||||
|
</geoLocations>
|
||||||
|
</resource>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template name="RdrDate2"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
|
<xsl:if test="EmbargoDate and ($unixTimestamp < EmbargoDate/@UnixTimestamp)">
|
||||||
|
<date>
|
||||||
|
<xsl:attribute name="dateType">Available</xsl:attribute>
|
||||||
|
<xsl:variable name="embargoDate" select="concat(
|
||||||
|
EmbargoDate/@Year, '-',
|
||||||
|
format-number(number(EmbargoDate/@Month),'00'), '-',
|
||||||
|
format-number(number(EmbargoDate/@Day),'00')
|
||||||
|
)" />
|
||||||
|
<xsl:value-of select="$embargoDate" />
|
||||||
|
</date>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:if test="CreatedAt">
|
||||||
|
<date>
|
||||||
|
<xsl:attribute name="dateType">Created</xsl:attribute>
|
||||||
|
<xsl:variable name="createdAt" select="concat(
|
||||||
|
CreatedAt/@Year, '-',
|
||||||
|
format-number(number(CreatedAt/@Month),'00'), '-',
|
||||||
|
format-number(number(CreatedAt/@Day),'00')
|
||||||
|
)" />
|
||||||
|
<xsl:value-of select="$createdAt" />
|
||||||
|
</date>
|
||||||
|
</xsl:if>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="Coverage" mode="oai_datacite"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
|
<geoLocation>
|
||||||
|
<geoLocationBox>
|
||||||
|
<westBoundLongitude>
|
||||||
|
<xsl:value-of select="@XMin" />
|
||||||
|
</westBoundLongitude>
|
||||||
|
<eastBoundLongitude>
|
||||||
|
<xsl:value-of select="@XMax" />
|
||||||
|
</eastBoundLongitude>
|
||||||
|
<southBoundLatitude>
|
||||||
|
<xsl:value-of select="@YMin" />
|
||||||
|
</southBoundLatitude>
|
||||||
|
<northBoundLatitude>
|
||||||
|
<xsl:value-of select="@YMax" />
|
||||||
|
</northBoundLatitude>
|
||||||
|
</geoLocationBox>
|
||||||
|
</geoLocation>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="TitleAbstract" mode="oai_datacite"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
|
<description>
|
||||||
|
<xsl:attribute name="xml:lang">
|
||||||
|
<xsl:value-of select="@Language" />
|
||||||
|
</xsl:attribute>
|
||||||
|
<xsl:if test="@Type != ''">
|
||||||
|
<xsl:attribute name="descriptionType">
|
||||||
|
<!-- <xsl:value-of select="@Type" /> -->
|
||||||
|
<xsl:text>Abstract</xsl:text>
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:value-of select="@Value" />
|
||||||
|
</description>
|
||||||
|
</xsl:template>
|
||||||
|
<xsl:template match="TitleAbstractAdditional" mode="oai_datacite"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
|
<description>
|
||||||
|
<xsl:attribute name="xml:lang">
|
||||||
|
<xsl:value-of select="@Language" />
|
||||||
|
</xsl:attribute>
|
||||||
|
<xsl:if test="@Type != ''">
|
||||||
|
<xsl:attribute name="descriptionType">
|
||||||
|
<xsl:call-template name="CamelCaseWord">
|
||||||
|
<xsl:with-param name="text" select="@Type" />
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:value-of select="@Value" />
|
||||||
|
</description>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template name="CamelCaseWord">
|
||||||
|
<xsl:param name="text" />
|
||||||
|
<xsl:param name="firstLower" select="true()" />
|
||||||
|
<xsl:variable name="Upper">ABCDEFGHIJKLMNOPQRSTUVQXYZ</xsl:variable>
|
||||||
|
<xsl:variable name="Lower">abcdefghijklmnopqrstuvwxyz</xsl:variable>
|
||||||
|
<xsl:for-each select="tokenize($text,'_')">
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="position()=1 and $firstLower = true()">
|
||||||
|
<xsl:value-of select="substring(.,1,1)" />
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<xsl:value-of select="translate(substring(.,1,1),$Lower,$Upper)" />
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
<xsl:value-of select="substring(.,2,string-length(.))" />
|
||||||
|
</xsl:for-each>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="Identifier" mode="oai_datacite"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
|
<identifier>
|
||||||
|
<xsl:attribute name="identifierType">
|
||||||
|
<xsl:text>DOI</xsl:text>
|
||||||
|
</xsl:attribute>
|
||||||
|
<xsl:value-of select="@Value" />
|
||||||
|
</identifier>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="TitleMain" mode="oai_datacite"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
|
<title>
|
||||||
|
<xsl:if test="@Language != ''">
|
||||||
|
<xsl:attribute name="xml:lang">
|
||||||
|
<xsl:value-of select="@Language" />
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:if test="@Type != '' and @Type != 'Main'">
|
||||||
|
<xsl:attribute name="titleType">
|
||||||
|
<xsl:value-of select="@Type" />
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:value-of select="@Value" />
|
||||||
|
</title>
|
||||||
|
</xsl:template>
|
||||||
|
<xsl:template match="TitleAdditional" mode="oai_datacite"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
|
<title>
|
||||||
|
<xsl:if test="@Language != ''">
|
||||||
|
<xsl:attribute name="xml:lang">
|
||||||
|
<xsl:value-of select="@Language" />
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="@Type != '' and @Type != 'Sub' and @Type != 'Main'">
|
||||||
|
<xsl:attribute name="titleType">
|
||||||
|
<xsl:value-of select="@Type" />
|
||||||
|
<xsl:text>Title</xsl:text>
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:when test="@Type = 'Sub'">
|
||||||
|
<xsl:attribute name="titleType">
|
||||||
|
<xsl:value-of select="@Type" />
|
||||||
|
<xsl:text>title</xsl:text>
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
<xsl:value-of select="@Value" />
|
||||||
|
</title>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="Subject" mode="oai_datacite"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
|
<subject>
|
||||||
|
<xsl:if test="@Language != ''">
|
||||||
|
<xsl:attribute name="xml:lang">
|
||||||
|
<xsl:value-of select="@Language" />
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:value-of select="@Value" />
|
||||||
|
</subject>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template name="AlternateIdentifier" match="AlternateIdentifier" mode="oai_datacite"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
|
<alternateIdentifier>
|
||||||
|
<xsl:attribute name="alternateIdentifierType">
|
||||||
|
<xsl:text>url</xsl:text>
|
||||||
|
</xsl:attribute>
|
||||||
|
<!-- <xsl:variable name="identifier" select="concat($repURL, '/dataset/', @Id)" /> -->
|
||||||
|
<xsl:value-of select="@landingpage" />
|
||||||
|
</alternateIdentifier>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="Reference" mode="oai_datacite"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
|
<relatedIdentifier>
|
||||||
|
<xsl:attribute name="relatedIdentifierType">
|
||||||
|
<xsl:value-of select="@Type" />
|
||||||
|
</xsl:attribute>
|
||||||
|
<xsl:attribute name="relationType">
|
||||||
|
<xsl:value-of select="@Relation" />
|
||||||
|
</xsl:attribute>
|
||||||
|
<xsl:value-of select="@Value" />
|
||||||
|
</relatedIdentifier>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="PersonContributor" mode="oai_datacite"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
|
<contributor>
|
||||||
|
<xsl:if test="@ContributorType != ''">
|
||||||
|
<xsl:attribute name="contributorType">
|
||||||
|
<xsl:value-of select="@ContributorType" />
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:if>
|
||||||
|
<contributorName>
|
||||||
|
<!-- <xsl:if test="@NameType != ''">
|
||||||
|
<xsl:attribute name="nameType">
|
||||||
|
<xsl:value-of select="@NameType" />
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:if> -->
|
||||||
|
<xsl:value-of select="concat(@FirstName, ' ',@LastName)" />
|
||||||
|
</contributorName>
|
||||||
|
</contributor>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="PersonAuthor" mode="oai_datacite"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
|
<creator>
|
||||||
|
<creatorName>
|
||||||
|
<xsl:if test="@NameType != ''">
|
||||||
|
<xsl:attribute name="nameType">
|
||||||
|
<xsl:value-of select="@NameType" />
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:value-of select="@LastName" />
|
||||||
|
<xsl:if test="@FirstName != ''">
|
||||||
|
<xsl:text>, </xsl:text>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:value-of select="@FirstName" />
|
||||||
|
<xsl:if test="@AcademicTitle != ''">
|
||||||
|
<xsl:text> (</xsl:text>
|
||||||
|
<xsl:value-of select="@AcademicTitle" />
|
||||||
|
<xsl:text>)</xsl:text>
|
||||||
|
</xsl:if>
|
||||||
|
</creatorName>
|
||||||
|
|
||||||
|
<xsl:if test="@NameType = 'Personal'">
|
||||||
|
<givenName>
|
||||||
|
<xsl:value-of select="@FirstName" />
|
||||||
|
</givenName>
|
||||||
|
<familyName>
|
||||||
|
<xsl:value-of select="@LastName" />
|
||||||
|
</familyName>
|
||||||
|
<xsl:if test="@IdentifierOrcid != ''">
|
||||||
|
<nameIdentifier schemeURI="http://orcid.org/" nameIdentifierScheme="ORCID">
|
||||||
|
<xsl:value-of select="@IdentifierOrcid" />
|
||||||
|
</nameIdentifier>
|
||||||
|
</xsl:if>
|
||||||
|
<affiliation>GBA</affiliation>
|
||||||
|
</xsl:if>
|
||||||
|
|
||||||
|
<xsl:if test="@NameType = 'Organizational'">
|
||||||
|
<xsl:if test="@IdentifierOrcid != ''">
|
||||||
|
<nameIdentifier schemeURI="http://orcid.org/" nameIdentifierScheme="ORCID">
|
||||||
|
<xsl:value-of select="@IdentifierOrcid" />
|
||||||
|
</nameIdentifier>
|
||||||
|
</xsl:if>
|
||||||
|
</xsl:if>
|
||||||
|
<!--
|
||||||
|
<nameType><xsl:value-of select="@NameType" /></nameType>
|
||||||
|
</xsl:if> -->
|
||||||
|
|
||||||
|
</creator>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="File/@MimeType" mode="oai_datacite"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
|
<format>
|
||||||
|
<xsl:value-of select="." />
|
||||||
|
</format>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
<xsl:template match="Licence" mode="oai_datacite"
|
||||||
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
|
<rights>
|
||||||
|
<xsl:attribute name="xml:lang">
|
||||||
|
<xsl:value-of select="@Language" />
|
||||||
|
</xsl:attribute>
|
||||||
|
<xsl:if test="@LinkLicence != ''">
|
||||||
|
<xsl:attribute name="rightsURI">
|
||||||
|
<xsl:value-of select="@LinkLicence" />
|
||||||
|
</xsl:attribute>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:attribute name="schemeURI">
|
||||||
|
<xsl:text>https://spdx.org/licenses/</xsl:text>
|
||||||
|
</xsl:attribute>
|
||||||
|
<xsl:attribute name="rightsIdentifierScheme">
|
||||||
|
<xsl:text>SPDX</xsl:text>
|
||||||
|
</xsl:attribute>
|
||||||
|
<xsl:attribute name="rightsIdentifier">
|
||||||
|
<xsl:value-of select="@Name" />
|
||||||
|
</xsl:attribute>
|
||||||
|
<xsl:value-of select="@NameLong" />
|
||||||
|
</rights>
|
||||||
|
<xsl:if test="@Name = 'CC-BY-4.0' or @Name = 'CC-BY-SA-4.0'">
|
||||||
|
<rights>
|
||||||
|
<xsl:attribute name="rightsURI">
|
||||||
|
<xsl:text>info:eu-repo/semantics/openAccess</xsl:text>
|
||||||
|
</xsl:attribute>
|
||||||
|
<xsl:text>Open Access</xsl:text>
|
||||||
|
</rights>
|
||||||
|
</xsl:if>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
|
</xsl:stylesheet>
|
|
@ -158,7 +158,7 @@
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
<xsl:if test="CreatedAt">
|
<xsl:if test="CreatedAt">
|
||||||
<date>
|
<date>
|
||||||
<xsl:attribute name="dateType">created</xsl:attribute>
|
<xsl:attribute name="dateType">Created</xsl:attribute>
|
||||||
<xsl:variable name="createdAt" select="concat(
|
<xsl:variable name="createdAt" select="concat(
|
||||||
CreatedAt/@Year, '-',
|
CreatedAt/@Year, '-',
|
||||||
format-number(number(CreatedAt/@Month),'00'), '-',
|
format-number(number(CreatedAt/@Month),'00'), '-',
|
||||||
|
@ -221,7 +221,6 @@
|
||||||
</description>
|
</description>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
<xsl:template name="CamelCaseWord">
|
<xsl:template name="CamelCaseWord">
|
||||||
<xsl:param name="text" />
|
<xsl:param name="text" />
|
||||||
<xsl:param name="firstLower" select="true()" />
|
<xsl:param name="firstLower" select="true()" />
|
||||||
|
@ -240,7 +239,6 @@
|
||||||
</xsl:for-each>
|
</xsl:for-each>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
<xsl:template match="Identifier" mode="oai_datacite"
|
<xsl:template match="Identifier" mode="oai_datacite"
|
||||||
xmlns="http://datacite.org/schema/kernel-4">
|
xmlns="http://datacite.org/schema/kernel-4">
|
||||||
<identifier>
|
<identifier>
|
||||||
|
@ -376,14 +374,21 @@
|
||||||
<familyName>
|
<familyName>
|
||||||
<xsl:value-of select="@LastName" />
|
<xsl:value-of select="@LastName" />
|
||||||
</familyName>
|
</familyName>
|
||||||
<affiliation>GBA</affiliation>
|
|
||||||
</xsl:if>
|
|
||||||
|
|
||||||
<xsl:if test="@IdentifierOrcid != ''">
|
<xsl:if test="@IdentifierOrcid != ''">
|
||||||
<nameIdentifier schemeURI="http://orcid.org/" nameIdentifierScheme="ORCID">
|
<nameIdentifier schemeURI="http://orcid.org/" nameIdentifierScheme="ORCID">
|
||||||
<xsl:value-of select="@IdentifierOrcid" />
|
<xsl:value-of select="@IdentifierOrcid" />
|
||||||
</nameIdentifier>
|
</nameIdentifier>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
|
<affiliation>GBA</affiliation>
|
||||||
|
</xsl:if>
|
||||||
|
|
||||||
|
<xsl:if test="@NameType = 'Organizational'">
|
||||||
|
<xsl:if test="@IdentifierOrcid != ''">
|
||||||
|
<nameIdentifier schemeURI="http://orcid.org/" nameIdentifierScheme="ORCID">
|
||||||
|
<xsl:value-of select="@IdentifierOrcid" />
|
||||||
|
</nameIdentifier>
|
||||||
|
</xsl:if>
|
||||||
|
</xsl:if>
|
||||||
<!--
|
<!--
|
||||||
<nameType><xsl:value-of select="@NameType" /></nameType>
|
<nameType><xsl:value-of select="@NameType" /></nameType>
|
||||||
</xsl:if> -->
|
</xsl:if> -->
|
||||||
|
|
110
resources/js/Pages/Editor/Dataset/Doi.vue
Normal file
110
resources/js/Pages/Editor/Dataset/Doi.vue
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||||
|
import SectionMain from '@/Components/SectionMain.vue';
|
||||||
|
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
||||||
|
import { router, Head, usePage } from '@inertiajs/vue3';
|
||||||
|
import { computed, Ref } from 'vue';
|
||||||
|
import CardBox from '@/Components/CardBox.vue';
|
||||||
|
import BaseButton from '@/Components/BaseButton.vue';
|
||||||
|
import BaseButtons from '@/Components/BaseButtons.vue';
|
||||||
|
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||||
|
import { mdiArrowLeftBoldOutline, mdiIdentifier } from '@mdi/js';
|
||||||
|
import FormValidationErrors from '@/Components/FormValidationErrors.vue';
|
||||||
|
import Notification from '@/utils/toast';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
dataset: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const flash: Ref<any> = computed(() => {
|
||||||
|
return usePage().props.flash;
|
||||||
|
});
|
||||||
|
const errors: Ref<any> = computed(() => {
|
||||||
|
return usePage().props.errors;
|
||||||
|
});
|
||||||
|
|
||||||
|
// const form = useForm({
|
||||||
|
// preferred_reviewer: '',
|
||||||
|
// preferred_reviewer_email: '',
|
||||||
|
// preferation: 'yes_preferation',
|
||||||
|
|
||||||
|
// // preferation: '',
|
||||||
|
// // isPreferationRequired: false,
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const isPreferationRequired = computed(() => form.preferation === 'yes_preferation');
|
||||||
|
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
Notification.showInfo(`doi implementation is in developement. Create DOI for dataset ${props.dataset.publish_id} later on`);
|
||||||
|
|
||||||
|
await router.put(stardust.route('editor.dataset.doiStore', [props.dataset.publish_id]));
|
||||||
|
// await form.put(stardust.route('dataset.releaseUpdate', [props.dataset.id]));
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<LayoutAuthenticated>
|
||||||
|
<Head title="Mint DOI" />
|
||||||
|
<SectionMain>
|
||||||
|
<SectionTitleLineWithButton :icon="mdiIdentifier" title="Mint DOI for dataset" main>
|
||||||
|
<BaseButton
|
||||||
|
:route-name="stardust.route('editor.dataset.list')"
|
||||||
|
:icon="mdiArrowLeftBoldOutline"
|
||||||
|
label="Back"
|
||||||
|
color="white"
|
||||||
|
rounded-full
|
||||||
|
small
|
||||||
|
/>
|
||||||
|
</SectionTitleLineWithButton>
|
||||||
|
<CardBox form @submit.prevent="handleSubmit">
|
||||||
|
<FormValidationErrors v-bind:errors="errors" />
|
||||||
|
|
||||||
|
<!-- <div class="flex flex-col md:flex-row items-center"> -->
|
||||||
|
<!-- <div class="w-full">
|
||||||
|
<label class="block font-bold mb-2" for="owner">Submitter:</label>
|
||||||
|
<div class="w-full p-2 rounded-md">{{ dataset.user.login }}</div>
|
||||||
|
</div> -->
|
||||||
|
<div class="w-full">
|
||||||
|
<label class="block font-bold mb-2" for="title">Tethys Publish ID:</label>
|
||||||
|
<div class="w-full p-2 rounded-md" v-if="dataset.publish_id">
|
||||||
|
{{ dataset.publish_id }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="w-full">
|
||||||
|
<label class="block font-bold mb-2" for="title">Dataset main title:</label>
|
||||||
|
<div class="w-full p-2 rounded-md" v-if="dataset.main_title">
|
||||||
|
{{ dataset.main_title }}
|
||||||
|
</div>
|
||||||
|
<div class="w-full p-2 rounded-md" v-else>No title available</div>
|
||||||
|
</div>
|
||||||
|
<div class="w-full">
|
||||||
|
<label class="block font-bold mb-2" for="title">Dataset abstract:</label>
|
||||||
|
<div class="w-full p-2 rounded-md" v-if="dataset.main_abstract">
|
||||||
|
{{ dataset.main_abstract }}
|
||||||
|
</div>
|
||||||
|
<div class="w-full p-2 rounded-md" v-else>No abstract available</div>
|
||||||
|
</div>
|
||||||
|
<!-- </div> -->
|
||||||
|
|
||||||
|
<div v-if="flash && flash.warning" class="flex flex-col mt-6 animate-fade-in">
|
||||||
|
<div class="bg-yellow-500 border-l-4 border-orange-400 text-white p-4" role="alert">
|
||||||
|
<p class="font-bold">Be Warned</p>
|
||||||
|
<p>{{ flash.warning }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<BaseButtons>
|
||||||
|
<!-- <BaseButton type="submit" color="info" label="Receive"
|
||||||
|
:class="{ 'opacity-25': router.processing }" :disabled="form.processing" /> -->
|
||||||
|
<BaseButton type="submit" color="info" label="Mint DOI" />
|
||||||
|
</BaseButtons>
|
||||||
|
</template>
|
||||||
|
</CardBox>
|
||||||
|
</SectionMain>
|
||||||
|
</LayoutAuthenticated>
|
||||||
|
</template>
|
|
@ -158,6 +158,11 @@ const getRowClass = (dataset) => {
|
||||||
:route-name="stardust.route('editor.dataset.publish', [dataset.id])"
|
:route-name="stardust.route('editor.dataset.publish', [dataset.id])"
|
||||||
color="info" :icon="mdiBookEdit" :label="'Publish'" small />
|
color="info" :icon="mdiBookEdit" :label="'Publish'" small />
|
||||||
|
|
||||||
|
<BaseButton
|
||||||
|
v-if="can.publish && (dataset.server_state == 'published' && !dataset.identifier)"
|
||||||
|
:route-name="stardust.route('editor.dataset.doi', [dataset.id])"
|
||||||
|
color="info" :icon="mdiBookEdit" :label="'Mint DOI'" small />
|
||||||
|
|
||||||
</BaseButtons>
|
</BaseButtons>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -243,6 +243,16 @@ Route.group(() => {
|
||||||
.where('id', Route.matchers.number())
|
.where('id', Route.matchers.number())
|
||||||
.middleware(['auth', 'can:dataset-publish']);
|
.middleware(['auth', 'can:dataset-publish']);
|
||||||
|
|
||||||
|
|
||||||
|
Route.get('dataset/:id/doi', 'DatasetController.doiCreate')
|
||||||
|
.as('editor.dataset.doi')
|
||||||
|
.where('id', Route.matchers.number())
|
||||||
|
.middleware(['auth', 'can:dataset-publish']);
|
||||||
|
Route.put('dataset/:publish_id/doi', 'DatasetController.doiStore')
|
||||||
|
.as('editor.dataset.doiStore')
|
||||||
|
.where('id', Route.matchers.number())
|
||||||
|
.middleware(['auth', 'can:dataset-publish']);
|
||||||
|
|
||||||
Route.put('/dataset/:id/update', 'DatasetController.update')
|
Route.put('/dataset/:id/update', 'DatasetController.update')
|
||||||
.as('editor.dataset.update')
|
.as('editor.dataset.update')
|
||||||
.middleware(['auth', 'can:dataset-editor-edit']);
|
.middleware(['auth', 'can:dataset-editor-edit']);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user