forked from geolba/tethys.backend
- use latest prettier 3.0 with eslint-plugin-prettier: 5.0.0-alpha.2
- npm normal updates - add all xslt and style asstes in extra folder public/assets2 - linting corrections - delete local .env.test from git tracking: git rm --cached .env.test - add .env.test into .gitignore file - add edit functionality for editing by submitter - npm updates -added xslt3 packeage for builfing sef files - added Language.ts class vor language table - added version to datasetxml2oai-pmh.xslt
This commit is contained in:
parent
f403c3109f
commit
4714dfdd94
70 changed files with 22920 additions and 17407 deletions
|
@ -20,14 +20,14 @@ export default class RoleController {
|
|||
if (request.input('sort')) {
|
||||
type SortOrder = 'asc' | 'desc' | undefined;
|
||||
let attribute = request.input('sort');
|
||||
let sort_order: SortOrder = 'asc';
|
||||
let sortOrder: SortOrder = 'asc';
|
||||
|
||||
if (attribute.substr(0, 1) == '-') {
|
||||
sort_order = 'desc';
|
||||
if (attribute.substr(0, 1) === '-') {
|
||||
sortOrder = 'desc';
|
||||
// attribute = substr(attribute, 1);
|
||||
attribute = attribute.substr(1);
|
||||
}
|
||||
roles.orderBy(attribute, sort_order);
|
||||
roles.orderBy(attribute, sortOrder);
|
||||
} else {
|
||||
// users.orderBy('created_at', 'desc');
|
||||
roles.orderBy('id', 'asc');
|
||||
|
|
|
@ -23,16 +23,16 @@ export default class UsersController {
|
|||
if (request.input('sort')) {
|
||||
type SortOrder = 'asc' | 'desc' | undefined;
|
||||
let attribute = request.input('sort');
|
||||
let sort_order: SortOrder = 'asc';
|
||||
let sortOrder: SortOrder = 'asc';
|
||||
|
||||
// if (strncmp($attribute, '-', 1) === 0) {
|
||||
if (attribute.substr(0, 1) == '-') {
|
||||
sort_order = 'desc';
|
||||
if (attribute.substr(0, 1) === '-') {
|
||||
sortOrder = 'desc';
|
||||
// attribute = substr(attribute, 1);
|
||||
attribute = attribute.substr(1);
|
||||
}
|
||||
// $users->orderBy($attribute, $sort_order);
|
||||
users.orderBy(attribute, sort_order);
|
||||
users.orderBy(attribute, sortOrder);
|
||||
} else {
|
||||
// users.orderBy('created_at', 'desc');
|
||||
users.orderBy('id', 'asc');
|
||||
|
|
189
app/Controllers/Http/Oai/OaiController.ts
Normal file
189
app/Controllers/Http/Oai/OaiController.ts
Normal file
|
@ -0,0 +1,189 @@
|
|||
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
||||
import { RequestContract } from '@ioc:Adonis/Core/Request';
|
||||
import { XMLBuilder } from 'xmlbuilder2/lib/interfaces';
|
||||
import { create } from 'xmlbuilder2';
|
||||
import dayjs, { Dayjs } from 'dayjs';
|
||||
import utc from 'dayjs/plugin/utc';
|
||||
import timezone from 'dayjs/plugin/timezone';
|
||||
import { readFileSync } from 'fs';
|
||||
import { StatusCodes } from 'http-status-codes';
|
||||
import { transform } from 'saxon-js';
|
||||
// import { Xslt, xmlParse } from 'xslt-processor'
|
||||
import { OaiErrorCodes, OaiModelError } from 'App/Exceptions/OaiErrorCodes';
|
||||
import { OaiModelException } from 'App/Exceptions/OaiModelException';
|
||||
|
||||
interface XslTParameter {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
interface Dictionary {
|
||||
[index: string]: string;
|
||||
}
|
||||
|
||||
export default class OaiController {
|
||||
// private deliveringDocumentStates = ["published", "deleted"];
|
||||
// private sampleRegEx = /^[A-Za-zäüÄÜß0-9\-_.!~]+$/;
|
||||
private xsltParameter: XslTParameter;
|
||||
/**
|
||||
* Holds xml representation of document information to be processed.
|
||||
*
|
||||
* @var xmlbuilder.XMLDocument | null Defaults to null.
|
||||
*/
|
||||
private xml: XMLBuilder;
|
||||
private proc;
|
||||
|
||||
constructor() {
|
||||
// Load the XSLT file
|
||||
this.proc = readFileSync('public/assets2/datasetxml2oai.sef.json');
|
||||
// tests
|
||||
// const xslPath = 'assets/datasetxml2oai-pmh.xslt'; // Replace with the actual path to your XSLT file
|
||||
// this.proc = readFileSync(xslPath, 'utf-8');
|
||||
// this.configuration = new Configuration();
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
}
|
||||
|
||||
public async index({ response, request }: HttpContextContract): Promise<void> {
|
||||
this.xml = create({ version: '1.0', encoding: 'UTF-8', standalone: true }, '<root></root>');
|
||||
|
||||
// this.proc = new XSLTProcessor();
|
||||
// const stylesheet = readFileSync(__dirname + "/datasetxml2oai.sef.json");
|
||||
const xsltParameter = (this.xsltParameter = {});
|
||||
|
||||
let oaiRequest: Dictionary = {};
|
||||
if (request.method() === 'POST') {
|
||||
oaiRequest = request.body();
|
||||
} else if (request.method() === 'GET') {
|
||||
oaiRequest = request.qs();
|
||||
} else {
|
||||
xsltParameter['oai_error_code'] = 'unknown';
|
||||
xsltParameter['oai_error_message'] = 'Only POST and GET methods are allowed for OAI-PMH.';
|
||||
}
|
||||
// const oaiRequest: OaiParameter = request.body;
|
||||
try {
|
||||
this.handleRequest(oaiRequest, request);
|
||||
} catch (error) {
|
||||
if (error instanceof OaiModelException) {
|
||||
const code = error.oaiCode;
|
||||
let oaiErrorCode: string | undefined = 'Unknown oai error code ' + code;
|
||||
if (OaiModelError.has(error.oaiCode) && OaiModelError.get(code) !== undefined) {
|
||||
oaiErrorCode = OaiModelError.get(error.oaiCode);
|
||||
}
|
||||
this.xsltParameter['oai_error_code'] = oaiErrorCode;
|
||||
this.xsltParameter['oai_error_message'] = error.message;
|
||||
} else {
|
||||
// // return next(error); // passing to default express middleware error handler
|
||||
this.xsltParameter['oai_error_code'] = 'unknown';
|
||||
this.xsltParameter['oai_error_message'] = 'An internal error occured.';
|
||||
}
|
||||
}
|
||||
|
||||
const xmlString = this.xml.end({ prettyPrint: true });
|
||||
|
||||
let xmlOutput;
|
||||
try {
|
||||
const result = await transform({
|
||||
// stylesheetFileName: `${config.TMP_BASE_DIR}/data-quality/rules/iati.sef.json`,
|
||||
stylesheetText: this.proc,
|
||||
destination: 'serialized',
|
||||
// sourceFileName: sourceFile,
|
||||
sourceText: xmlString,
|
||||
stylesheetParams: xsltParameter,
|
||||
// logLevel: 10,
|
||||
});
|
||||
xmlOutput = result.principalResult;
|
||||
} catch (error) {
|
||||
return response.status(500).json({
|
||||
message: 'An error occurred while creating the user',
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
|
||||
response
|
||||
.header('Content-Type', 'application/xml; charset=utf-8')
|
||||
.header('Access-Control-Allow-Origin', '*')
|
||||
.header('Access-Control-Allow-Methods', 'GET,POST');
|
||||
response.status(StatusCodes.OK).send(xmlOutput);
|
||||
}
|
||||
|
||||
protected handleRequest(oaiRequest: Dictionary, request: RequestContract) {
|
||||
// Setup stylesheet
|
||||
// $this->loadStyleSheet('datasetxml2oai-pmh.xslt');
|
||||
|
||||
// Set response time
|
||||
const now: Dayjs = dayjs();
|
||||
this.xsltParameter['responseDate'] = now.format('YYYY-MM-DDTHH:mm:ss[Z]');
|
||||
this.xsltParameter['unixTimestamp'] = now.unix();
|
||||
|
||||
// set OAI base url
|
||||
const baseDomain = process.env.BASE_DOMAIN || 'localhost';
|
||||
this.xsltParameter['baseURL'] = baseDomain + '/oai';
|
||||
this.xsltParameter['repURL'] = request.protocol() + '://' + request.hostname();
|
||||
this.xsltParameter['downloadLink'] = request.protocol() + '://' + request.hostname() + '/file/download/';
|
||||
this.xsltParameter['doiLink'] = 'https://doi.org/';
|
||||
this.xsltParameter['doiPrefix'] = 'info:eu-repo/semantics/altIdentifier/doi/';
|
||||
|
||||
if (oaiRequest['verb']) {
|
||||
const verb = oaiRequest['verb'];
|
||||
this.xsltParameter['oai_verb'] = verb;
|
||||
if (verb === 'Identify') {
|
||||
this.handleIdentify();
|
||||
} else if (verb === 'ListMetadataFormats') {
|
||||
this.handleListMetadataFormats();
|
||||
}
|
||||
// else if (verb == "GetRecord") {
|
||||
// await this.handleGetRecord(oaiRequest);
|
||||
// } else if (verb == "ListRecords") {
|
||||
// await this.handleListRecords(oaiRequest);
|
||||
// } else if (verb == "ListIdentifiers") {
|
||||
// await this.handleListIdentifiers(oaiRequest);
|
||||
// } else if (verb == "ListSets") {
|
||||
// await this.handleListSets();
|
||||
// }
|
||||
else {
|
||||
this.handleIllegalVerb();
|
||||
}
|
||||
} else {
|
||||
// // try {
|
||||
// // console.log("Async code example.")
|
||||
// const err = new PageNotFoundException("verb not found");
|
||||
// throw err;
|
||||
// // } catch (error) { // manually catching
|
||||
// // next(error); // passing to default middleware error handler
|
||||
// // }
|
||||
throw new OaiModelException(
|
||||
StatusCodes.INTERNAL_SERVER_ERROR,
|
||||
'The verb provided in the request is illegal.',
|
||||
OaiErrorCodes.BADVERB,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected handleIdentify() {
|
||||
const email = process.env.OAI_EMAIL || 'repository@geosphere.at';
|
||||
const repositoryName = 'Tethys RDR';
|
||||
const repIdentifier = 'tethys.at';
|
||||
const sampleIdentifier = 'oai:' + repIdentifier + ':1'; //$this->_configuration->getSampleIdentifier();
|
||||
|
||||
// Dataset::earliestPublicationDate()->server_date_published->format('Y-m-d\TH:i:s\Z') : null;
|
||||
// earliestDateFromDb!= null && (this.xsltParameter['earliestDatestamp'] = earliestDateFromDb?.server_date_published);
|
||||
|
||||
// set parameters for oai-pmh.xslt
|
||||
this.xsltParameter['email'] = email;
|
||||
this.xsltParameter['repositoryName'] = repositoryName;
|
||||
this.xsltParameter['repIdentifier'] = repIdentifier;
|
||||
this.xsltParameter['sampleIdentifier'] = sampleIdentifier;
|
||||
// $this->proc->setParameter('', 'earliestDatestamp', $earliestDateFromDb);
|
||||
|
||||
this.xml.root().ele('Datasets');
|
||||
}
|
||||
|
||||
protected handleListMetadataFormats() {
|
||||
this.xml.root().ele('Datasets');
|
||||
}
|
||||
|
||||
private handleIllegalVerb() {
|
||||
this.xsltParameter['oai_error_code'] = 'badVerb';
|
||||
this.xsltParameter['oai_error_message'] = 'The verb provided in the request is illegal.';
|
||||
}
|
||||
}
|
|
@ -1,12 +1,11 @@
|
|||
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
||||
import User from 'App/Models/User';
|
||||
import Dataset from 'App/Models/Dataset';
|
||||
// import Role from 'App/Models/Role';
|
||||
// import Database from '@ioc:Adonis/Lucid/Database';
|
||||
import License from 'App/Models/License';
|
||||
import Project from 'App/Models/Project';
|
||||
import Title from 'App/Models/Title';
|
||||
import Description from 'App/Models/Description';
|
||||
import Language from 'App/Models/Language';
|
||||
// import CreateUserValidator from 'App/Validators/CreateUserValidator';
|
||||
// import UpdateUserValidator from 'App/Validators/UpdateUserValidator';
|
||||
import { schema, CustomMessages, rules } from '@ioc:Adonis/Core/Validator';
|
||||
|
@ -16,7 +15,7 @@ import Database from '@ioc:Adonis/Lucid/Database';
|
|||
import { TransactionClientContract } from '@ioc:Adonis/Lucid/Database';
|
||||
import Subject from 'App/Models/Subject';
|
||||
import CreateDatasetValidator from 'App/Validators/CreateDatasetValidator';
|
||||
import { TitleTypes, DescriptionTypes } from 'Contracts/enums';
|
||||
import { TitleTypes, DescriptionTypes, ContributorTypes, PersonNameTypes } from 'Contracts/enums';
|
||||
import type { ModelQueryBuilderContract } from '@ioc:Adonis/Lucid/Orm';
|
||||
|
||||
export default class DatasetController {
|
||||
|
@ -34,14 +33,14 @@ export default class DatasetController {
|
|||
if (request.input('sort')) {
|
||||
type SortOrder = 'asc' | 'desc' | undefined;
|
||||
let attribute = request.input('sort');
|
||||
let sort_order: SortOrder = 'asc';
|
||||
let sortOrder: SortOrder = 'asc';
|
||||
|
||||
if (attribute.substr(0, 1) == '-') {
|
||||
sort_order = 'desc';
|
||||
if (attribute.substr(0, 1) === '-') {
|
||||
sortOrder = 'desc';
|
||||
// attribute = substr(attribute, 1);
|
||||
attribute = attribute.substr(1);
|
||||
}
|
||||
datasets.orderBy(attribute, sort_order);
|
||||
datasets.orderBy(attribute, sortOrder);
|
||||
} else {
|
||||
// users.orderBy('created_at', 'desc');
|
||||
datasets.orderBy('id', 'asc');
|
||||
|
@ -73,7 +72,7 @@ export default class DatasetController {
|
|||
datasets: myDatasets.serialize(),
|
||||
filters: request.all(),
|
||||
can: {
|
||||
// create: await auth.user?.can(['user-create']),
|
||||
// create: await auth.user?.can(['dataset-submit']),
|
||||
edit: await auth.user?.can(['dataset-edit']),
|
||||
delete: await auth.user?.can(['dataset-delete']),
|
||||
},
|
||||
|
@ -391,7 +390,7 @@ export default class DatasetController {
|
|||
// $dataKeyword = new Subject($keyword);
|
||||
// $dataset->subjects()->save($dataKeyword);
|
||||
const keyword = await Subject.firstOrNew({ value: keywordData.value, type: keywordData.type }, keywordData);
|
||||
if (keyword.$isNew == true) {
|
||||
if (keyword.$isNew === true) {
|
||||
await dataset.useTransaction(trx).related('subjects').save(keyword);
|
||||
} else {
|
||||
await dataset.useTransaction(trx).related('subjects').attach([keyword.id]);
|
||||
|
@ -485,7 +484,7 @@ export default class DatasetController {
|
|||
};
|
||||
|
||||
// public async release({ params, view }) {
|
||||
public async release({ request, inertia }: HttpContextContract) {
|
||||
public async release({ request, inertia, response }: HttpContextContract) {
|
||||
const id = request.param('id');
|
||||
|
||||
const dataset = await Dataset.query()
|
||||
|
@ -495,11 +494,17 @@ export default class DatasetController {
|
|||
.where('id', id)
|
||||
.firstOrFail();
|
||||
|
||||
// const editors = await User.query()
|
||||
// .whereHas('roles', (builder) => {
|
||||
// builder.where('name', 'editor');
|
||||
// })
|
||||
// .pluck('login', 'id');
|
||||
const validStates = ['inprogress', 'rejected_editor'];
|
||||
if (!validStates.includes(dataset.server_state)) {
|
||||
// session.flash('errors', 'Invalid server state!');
|
||||
return response
|
||||
.flash(
|
||||
'warning',
|
||||
`Invalid server state. Dataset with id ${id} cannot be released to editor. Datset has server state ${dataset.server_state}.`,
|
||||
)
|
||||
.redirect()
|
||||
.back();
|
||||
}
|
||||
|
||||
return inertia.render('Submitter/Dataset/Release', {
|
||||
dataset,
|
||||
|
@ -509,8 +514,16 @@ export default class DatasetController {
|
|||
public async releaseUpdate({ request, response }: HttpContextContract) {
|
||||
const id = request.param('id');
|
||||
const dataset = await Dataset.query().preload('files').where('id', id).firstOrFail();
|
||||
|
||||
const validStates = ['inprogress', 'rejected_editor'];
|
||||
if (!validStates.includes(dataset.server_state)) {
|
||||
// throw new Error('Invalid server state!');
|
||||
// return response.flash('warning', 'Invalid server state. Dataset cannot be released to editor').redirect().back();
|
||||
return dataset.serialize();
|
||||
}
|
||||
|
||||
if (dataset.files.length === 0) {
|
||||
return response.flash('message', 'At least minimum one file is required.').redirect('back');
|
||||
return response.flash('warning', 'At least minimum one file is required.').redirect('back');
|
||||
}
|
||||
|
||||
const preferation = request.input('preferation', '');
|
||||
|
@ -561,11 +574,106 @@ export default class DatasetController {
|
|||
input.reject_reviewer_note = null;
|
||||
}
|
||||
|
||||
// if (await dataset.merge(input).save()) {
|
||||
// return response.redirect().route('publish.workflow.submit.index').flash('flash_message', 'You have released your dataset!');
|
||||
// }
|
||||
return response.toRoute('dataset.list').flash('message', 'You have released your dataset');
|
||||
|
||||
if (await dataset.merge(input).save()) {
|
||||
return response.toRoute('dataset.list').flash('message', 'You have released your dataset!');
|
||||
}
|
||||
// throw new GeneralException(trans('exceptions.publish.release.update_error'));
|
||||
}
|
||||
|
||||
public async edit({ params, inertia }) {
|
||||
const dataset = await Dataset.query().where('id', params.id).preload('titles').firstOrFail();
|
||||
|
||||
// await dataset.loadMany([
|
||||
// 'licenses',
|
||||
// 'authors',
|
||||
// 'contributors',
|
||||
// 'titles',
|
||||
// 'abstracts',
|
||||
// 'files',
|
||||
// 'coverage',
|
||||
// 'subjects',
|
||||
// 'references',
|
||||
// ]);
|
||||
|
||||
const titleTypes = Object.entries(TitleTypes)
|
||||
// .filter(([value]) => value !== 'Main')
|
||||
.map(([key, value]) => ({ value: key, label: value }));
|
||||
|
||||
const descriptionTypes = Object.entries(DescriptionTypes)
|
||||
// .filter(([value]) => value !== 'Abstract')
|
||||
.map(([key, value]) => ({ value: key, label: value }));
|
||||
|
||||
const languages = await Language.query().where('active', true).pluck('part1', 'part1');
|
||||
|
||||
// const contributorTypes = Config.get('enums.contributor_types');
|
||||
const contributorTypes = Object.entries(ContributorTypes).map(([key, value]) => ({ value: key, label: value }));
|
||||
|
||||
// const nameTypes = Config.get('enums.name_types');
|
||||
const nameTypes = Object.entries(PersonNameTypes).map(([key, value]) => ({ value: key, label: value }));
|
||||
|
||||
// const messages = await Database.table('messages')
|
||||
// .pluck('help_text', 'metadata_element');
|
||||
|
||||
const projects = await Project.query().pluck('label', 'id');
|
||||
|
||||
const currentDate = new Date();
|
||||
const currentYear = currentDate.getFullYear();
|
||||
const years = Array.from({ length: currentYear - 1990 + 1 }, (_, index) => 1990 + index);
|
||||
|
||||
// const licenses = await License.query()
|
||||
// .select('id', 'name_long', 'link_licence')
|
||||
// .orderBy('sort_order')
|
||||
// .fetch();
|
||||
const licenses = await License.query().select('id', 'name_long', 'link_licence').orderBy('sort_order');
|
||||
|
||||
// const checkeds = dataset.licenses.first().id;
|
||||
|
||||
const keywordTypes = {
|
||||
uncontrolled: 'uncontrolled',
|
||||
swd: 'swd',
|
||||
};
|
||||
|
||||
const referenceTypes = ['DOI', 'Handle', 'ISBN', 'ISSN', 'URL', 'URN'];
|
||||
|
||||
const relationTypes = [
|
||||
'IsSupplementTo',
|
||||
'IsSupplementedBy',
|
||||
'IsContinuedBy',
|
||||
'Continues',
|
||||
'IsNewVersionOf',
|
||||
'IsPartOf',
|
||||
'HasPart',
|
||||
'Compiles',
|
||||
'IsVariantFormOf',
|
||||
];
|
||||
|
||||
const doctypes = {
|
||||
analysisdata: { label: 'Analysis', value: 'analysisdata' },
|
||||
measurementdata: { label: 'Measurements', value: 'measurementdata' },
|
||||
monitoring: 'Monitoring',
|
||||
remotesensing: 'Remote Sensing',
|
||||
gis: 'GIS',
|
||||
models: 'Models',
|
||||
mixedtype: 'Mixed Type',
|
||||
};
|
||||
|
||||
return inertia.render('Submitter/Dataset/Edit', {
|
||||
dataset,
|
||||
titletypes : titleTypes,
|
||||
descriptionTypes,
|
||||
contributorTypes,
|
||||
nameTypes,
|
||||
languages,
|
||||
// messages,
|
||||
projects,
|
||||
licenses,
|
||||
// checkeds,
|
||||
years,
|
||||
// languages,
|
||||
keywordTypes,
|
||||
referenceTypes,
|
||||
relationTypes,
|
||||
doctypes,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue