Compare commits

67 Commits

Author SHA1 Message Date
e56ae1f366 Add ISSN literature fields 2025-05-28 18:09:44 +02:00
e5e64335a1 Fix incorrect dependency between weight unit and width value fields 2025-05-06 17:37:12 +02:00
eb6add3d29 Add missing / new literature fields
Close #45
2025-05-02 15:15:51 +02:00
f0ce5a9a58 Add fields for actors' year of birth and death for events
Close #44
2025-04-03 17:40:55 +02:00
01d958cdc2 Update MDAllowedValueSets 2025-03-20 17:32:26 +01:00
7b3f67ed15 Simplify code for forming event fields, enforce following schema
suggested by MDEventsSet
2025-03-15 04:32:58 +01:00
22195b2263 Also add description fields for was_depicted_who 2025-03-14 13:03:38 +01:00
dba2ba182e Add note/description fields for actors and places in events (was_used_who_description, was_used_where_description)
Close #43
2025-03-14 11:41:28 +01:00
dcb06a4b60 Update MDAllowedValueSets 2025-03-14 03:31:04 +01:00
57cae5314f Remove related_place_sure etc
Close #42
2025-03-12 12:17:51 +01:00
02b8fdb15e Add field for tag GND IDs
Close #41
2025-02-27 13:34:40 +01:00
ac6665ce00 Cover markings in selectable fields
Close #39
2025-02-24 16:41:03 +01:00
6e01abc74f Use named parameters for more legible code
Close #40
2025-02-24 16:28:36 +01:00
8f67d9b04d Update git submodules 2025-02-13 23:11:21 +01:00
6e41153a82 Update git submodules 2025-01-22 15:39:37 +01:00
f8656d4178 Update git submodules 2025-01-04 23:02:18 +01:00
0381f349d6 Update translation files 2024-12-10 22:12:47 +01:00
cf0c7d75da Update git submodules 2024-11-28 09:35:51 +01:00
1415884ebc Update git submodules 2024-10-21 01:30:00 +02:00
99fb3f6afb Update git submodules 2024-09-15 16:13:18 +02:00
818cb7dab6 Add fields for new event types 2024-08-07 23:37:39 +02:00
5677cc051a Upgrade papa parse to v5.4.1
Close #38
2024-07-01 17:50:36 +02:00
fa4b563532 Update MD_STD 2024-07-01 00:46:21 +02:00
af65bd99da Update git submodules 2024-06-19 23:19:07 +02:00
66a94fcf9f Add symlink to phpcs 2024-06-11 13:31:17 +02:00
6eba06808a Add new fields for place and actor wikidata IDs 2024-06-06 12:30:24 +02:00
34c2b5618b Update git submodules 2024-06-06 12:30:06 +02:00
47f52c4a10 Update git submodules 2024-03-26 01:23:50 +01:00
35843ee590 Remove dependency of event actor to actor certainty
Close #36
2024-02-19 18:04:47 +01:00
e62e36a68c Update git submodules 2024-02-19 14:38:19 +01:00
36457a6d0c Update MDErrorReporter 2023-10-27 09:12:50 +02:00
fa53ec387a Update git submodules 2023-10-19 17:26:23 +02:00
0873302e5e Add missing event types 2023-10-19 01:02:48 +02:00
e7887ac1c7 Cover musdb's acquisitions
Close #35
2023-09-10 03:10:21 +02:00
befe228396 Cover new fields: form, color, sex 2023-09-01 13:02:11 +02:00
d13972229f Update phpstan baseline 2023-08-16 22:49:56 +02:00
91186de676 Update git submodules 2023-08-16 22:49:08 +02:00
54f146831f Make separated measurement types (length, width) usable independent of each other
Close #33
2023-08-14 22:52:41 +02:00
80785406bb Recompile app after update of translation files 2023-08-04 13:43:25 +02:00
726146eb2a Add some explanations in tooltips missing thus far 2023-08-04 13:38:03 +02:00
86e9ab66e9 Update git submodules 2023-06-25 02:53:17 +02:00
b938059875 Update git submodules 2023-06-24 17:07:41 +02:00
4f8f041133 Add missing note on deployment in README 2023-06-24 00:58:10 +02:00
de322fb41f Extend README 2023-06-24 00:55:45 +02:00
495bb4b670 Add new fields for importing linked exhibition for objects
Close #30
2023-06-07 18:27:34 +02:00
8a9f51bf9d Update git submodules 2023-06-07 18:22:28 +02:00
cc39f204d1 Improve message for invalid headers in validation 2023-05-16 14:44:21 +02:00
b9f83b7dcc Update cached translations / validation values 2023-05-14 17:33:55 +02:00
ddf26e7e52 Add field to cover tag relations (tag_relation_type)
Close #29
2023-05-14 17:06:49 +02:00
3ee4174863 Display line number when validation files because of field dependencies 2023-05-10 16:45:39 +02:00
6337291a9d Add section for content language
Close #28
2023-05-07 02:14:50 +02:00
65fa859490 Display current line value for non-empty field in case of dependency
issues
2023-05-07 02:03:02 +02:00
50f682dbc2 Use px-based values over em-based ones for media queries 2023-03-08 13:41:57 +01:00
063a330f74 Update git submodules 2023-03-07 01:50:00 +01:00
d528321219 Remove duplicate array indexes 2023-02-15 21:09:25 +01:00
49fee443c8 Update git submodules 2023-02-15 21:08:49 +01:00
139933fa9a Add missing notes fields: negative_id, handling_recommendations, ... 2023-01-25 15:45:36 +01:00
977e7511ec Set hard-coded delimiter (;) and escape char (") and better display
parsing errors
2023-01-18 01:31:36 +01:00
543a80413c Add new field: owner
Close #27
2022-12-19 22:02:57 +01:00
7192b03ead Enable Russian and Ukrainian translations
Close #26
2022-12-16 22:55:53 +01:00
c04d63e026 Warn against invalid column headers being used, fail gracefully if ones
are present
2022-11-29 18:41:41 +01:00
5146305caf Add refresh button and license statement
Close #25, close #24
2022-11-28 15:55:05 +01:00
20810aa850 Add primitive check for file encoding when a file is uploaded and warn
if it's not UTF-8

Close #8
2022-11-28 14:27:46 +01:00
f5ea1f850a Improve warnings in case of missing dependent column contents 2022-11-28 14:25:11 +01:00
f81089ac79 Update git submodules 2022-11-18 02:44:46 +01:00
10012db20d Move csvxml translations to a separate git submodule and add help texts
Close #22
2022-11-18 02:07:03 +01:00
34fcc4905a Add phpstan baseline 2022-11-17 19:13:13 +01:00
37 changed files with 1189 additions and 1365 deletions

6
.gitmodules vendored
View File

@ -16,9 +16,9 @@
[submodule "l10n/musdb"]
path = l10n/musdb
url = gitea:museum-digital/translation-musdb.git
[submodule "l10n/importer"]
path = l10n/importer
url = gitea:museum-digital/translations-importer.git
[submodule "classes/MD_QA"]
path = classes/MD_QA
url = gitea:museum-digital/MD_QA.git
[submodule "l10n/translation-csvxml"]
path = l10n/translation-csvxml
url = gitea:museum-digital/translation-csvxml.git

View File

@ -1,10 +1,38 @@
# Validator for the standard csv format for imports to museum-digital
# Validator for the standard CSV format for imports to museum-digital
# Development
The validation and transformation service for import CSV files to an instance of museum-digital is centrally hosted at <https://csvxml.imports.museum-digital.org/>. This repository contains
To update, run `scripts/compile.php`.
a) The statically generated progressive web app that is being served
b) The simple static page generator for generating it
## Dependencies
## CSVXML as a "Format" / Purpose of This Tool
Many smaller museums still do not use a dedicated application for managing their collections. This often leads to the need to import Excel or CSV tables. The format described and validated by the present tool helps museums and administrators who want to import data from such sources to pre-prepare their import data. If the data is not yet recorded, this tool allows the generation of a CSV file with the expected table headings. If an existing CSV file is to be imported, users can rename their table headings to the ones listed in CSVXML and then validate their import data using this application.
Finally, this tool will return a ZIP file containing one XML file per object in the validated CSV file. The application works completely on the client side, meaning that no data is uploaded to the server as the import data is validated. This also allows for offline use.
## To-Do
- [ ] Add missing translation files for explanations
- Translations and explanations for most fields exist in the musdb translation files. They now only need to be entered at the relevant positions in [`CsvxmlAvailableFields.php`](./src/CsvxmlAvailableFields.php).
## Deployment
1. Clone this repository and set up git subrepositories
- Before doing this, ensure that an alias `gitea` is available in your SSH config (`~/.ssh/config`)
2. Point a web server to serve the [`/public`](./public) subdirectory
## Development
To update, run [`scripts/compile.php`](./scripts/compile.php).
All relevant development files can be found in [`/src`](./src). [`CsvxmlAvailableFields.php`](./src/CsvxmlAvailableFields.php) is the central file used for generating one large array defining the allowed table headings / fields and their relevant accompanying data (e.g. explanations).
### Dependencies
- [JSZip](https://github.com/Stuk/jszip), dual-licensed under MIT & GPLv3
- [PapaParse](https://github.com/mholt/PapaParse), licensed under the MIT license
## License
This project is licensed under the AGPL License. See the [LICENSE](./LICENSE) file for the full license text.

View File

@ -1,13 +1,13 @@
{
"require": {
"phpmailer/phpmailer": "^6.1",
"phpunit/phpunit": "^9.4",
"phpstan/phpstan": "^1.9",
"phpstan/phpstan-strict-rules": "^1.4",
"ergebnis/phpstan-rules": "^1.0",
"phpstan/phpstan-deprecation-rules": "^1.0",
"spaze/phpstan-disallowed-calls": "^2.9",
"thecodingmachine/phpstan-strict-rules": "^1.0",
"phpstan/phpstan-phpunit": "^1.2"
"phpmailer/phpmailer": "*",
"phpunit/phpunit": "*",
"phpstan/phpstan": "*",
"phpstan/phpstan-strict-rules": "*",
"ergebnis/phpstan-rules": "*",
"phpstan/phpstan-deprecation-rules": "*",
"spaze/phpstan-disallowed-calls": "*",
"thecodingmachine/phpstan-strict-rules": "*",
"phpstan/phpstan-phpunit": "*"
}
}

View File

@ -10,11 +10,11 @@ declare(strict_types = 1);
const CACHE_DIR_PERMS = 0775;
const ALLOWED_LANGS = ['de', 'en', 'hu'];
const ALLOWED_LANGS = ['de', 'en', 'hu', 'ru', 'uk'];
const TL_FILE_DIRS = [
__DIR__ . "/../l10n/musdb/",
__DIR__ . "/../l10n/importer/",
__DIR__ . "/../l10n/translation-csvxml/",
__DIR__ . "/../classes/MDAllowedValueSets/l18n/",
];
@ -23,6 +23,7 @@ const AUTOLOAD_DIRS = [
__DIR__ . "/../classes/MDTlLoader/src",
__DIR__ . "/../classes/MD_STD/src",
__DIR__ . "/../classes/MDAllowedValueSets/src",
__DIR__ . "/../classes/MDAllowedValueSets/src/enums",
__DIR__ . "/../classes/MDExportFormats/src",
__DIR__ . "/../classes/MDErrorReporter",
__DIR__ . "/../classes/MDMailer/src",

Submodule l10n/importer deleted from 3bfb6f9ac2

1
phpcs.xml Symbolic link
View File

@ -0,0 +1 @@
classes/MD_QA/rules/md_phpcs_rules.xml

156
phpstan-baseline.neon Normal file
View File

@ -0,0 +1,156 @@
parameters:
ignoreErrors:
-
message: "#^Class MDInvalidNodaLinkException is neither abstract nor final\\.$#"
count: 1
path: classes/MDAllowedValueSets/exceptions/MDInvalidNodaLinkException.php
-
message: "#^Class \"MDInvalidNodaLinkLcshIdIsGeneralLoc\" is not allowed to extend \"MDInvalidNodaLinkException\"\\.$#"
count: 1
path: classes/MDAllowedValueSets/exceptions/MDInvalidNodaLinkLcshIdIsGeneralLoc.php
-
message: "#^Class \"MDInvalidNodaLinkLocIdIsSh\" is not allowed to extend \"MDInvalidNodaLinkException\"\\.$#"
count: 1
path: classes/MDAllowedValueSets/exceptions/MDInvalidNodaLinkLocIdIsSh.php
-
message: "#^Match arm comparison between \\$this\\(MDCopyrightCollective\\)&MDCopyrightCollective\\:\\:vg_bildkunst and MDCopyrightCollective\\:\\:vg_bildkunst is always true\\.$#"
count: 3
path: classes/MDAllowedValueSets/src/enums/MDCopyrightCollective.php
-
message: "#^Match expression does not handle remaining values\\: MDMeasurementType\\:\\:height_frame\\|MDMeasurementType\\:\\:height_image_size\\|MDMeasurementType\\:\\:height_sheet_size\\|MDMeasurementType\\:\\:height_socle\\|MDMeasurementType\\:\\:length_frame\\|MDMeasurementType\\:\\:length_image_size\\|MDMeasurementType\\:\\:length_sheet_size\\|MDMeasurementType\\:\\:length_socle\\|MDMeasurementType\\:\\:width_frame\\|MDMeasurementType\\:\\:width_image_size\\|MDMeasurementType\\:\\:width_sheet_size\\|MDMeasurementType\\:\\:width_socle$#"
count: 1
path: classes/MDAllowedValueSets/src/enums/MDMeasurementType.php
-
message: "#^Class MDInvalidNodaLink is neither abstract nor final\\.$#"
count: 1
path: classes/MDErrorReporter/exceptions/updates/MDInvalidNodaLink.php
-
message: "#^Strict comparison using \\=\\=\\= between '35CA0E31F6F44FB5' and null will always evaluate to false\\.$#"
count: 1
path: classes/MDMailer/src/MDMailerHelper.php
-
message: "#^Calling file_get_contents\\(\\) is forbidden, use MD_STD\\:\\:file_get_contents\\(\\) instead\\.$#"
count: 1
path: classes/MDTlLoader/src/MDTlLoader.php
-
message: "#^Calling json_encode\\(\\) is forbidden, use MD_STD\\:\\:json_encode\\(\\) instead\\.$#"
count: 1
path: classes/MDTlLoader/src/MDTlLoader.php
-
message: "#^Calling mkdir\\(\\) is forbidden, use MD_STD\\:\\:mkdir\\(\\) instead\\.$#"
count: 1
path: classes/MDTlLoader/src/MDTlLoader.php
-
message: "#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#"
count: 3
path: classes/MDTlLoader/src/MDTlLoader.php
-
message: "#^Variable variables are not allowed\\.$#"
count: 3
path: classes/MDTlLoader/src/MDTlLoader.php
-
message: "#^Calling file_get_contents\\(\\) is forbidden, use MD_STD\\:\\:file_get_contents\\(\\) instead\\.$#"
count: 1
path: classes/MD_STD/src/MD_STD.php
-
message: "#^Calling json_encode\\(\\) is forbidden, use MD_STD\\:\\:json_encode\\(\\) instead\\.$#"
count: 2
path: classes/MD_STD/src/MD_STD.php
-
message: "#^Calling levenshtein\\(\\) is forbidden, use MD_STD\\:\\:levenshtein\\(\\) instead\\.$#"
count: 1
path: classes/MD_STD/src/MD_STD.php
-
message: "#^Calling mkdir\\(\\) is forbidden, use MD_STD\\:\\:mkdir\\(\\) instead\\.$#"
count: 1
path: classes/MD_STD/src/MD_STD.php
-
message: "#^Calling realpath\\(\\) is forbidden, use MD_STD\\:\\:realpath\\(\\) instead\\.$#"
count: 1
path: classes/MD_STD/src/MD_STD.php
-
message: "#^Calling scandir\\(\\) is forbidden, use MD_STD\\:\\:scandir\\(\\) instead\\.$#"
count: 1
path: classes/MD_STD/src/MD_STD.php
-
message: "#^Calling unlink\\(\\) is forbidden, use MD_STD\\:\\:unlink\\(\\) instead\\.$#"
count: 1
path: classes/MD_STD/src/MD_STD.php
-
message: "#^Method MD_STD\\:\\:scandir\\(\\) should return array\\<non\\-empty\\-string\\> but returns list\\<string\\>\\.$#"
count: 1
path: classes/MD_STD/src/MD_STD.php
-
message: "#^Parameter \\#3 \\$value of function curl_setopt expects resource, resource\\|false given\\.$#"
count: 1
path: classes/MD_STD/src/MD_STD.php
-
message: "#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#"
count: 1
path: classes/MD_STD/src/MD_STD.php
-
message: "#^Calling move_uploaded_file\\(\\) is forbidden, use MD_STD_IN\\:\\:move_uploaded_file\\(\\) instead\\.$#"
count: 1
path: classes/MD_STD/src/MD_STD_IN.php
-
message: "#^Variable \\$output in empty\\(\\) always exists and is not falsy\\.$#"
count: 1
path: classes/MD_STD/src/MD_STD_IN.php
-
message: "#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#"
count: 2
path: classes/MD_STD/src/MD_STD_SEC.php
-
message: "#^Unreachable statement \\- code above always terminates\\.$#"
count: 1
path: classes/MD_STD/tests/MD_STD_IN_Test.php
-
message: "#^Calling scandir\\(\\) is forbidden, use MD_STD\\:\\:scandir\\(\\) instead\\.$#"
count: 1
path: classes/MD_STD/tests/MD_STD_Test.php
-
message: "#^Access to undefined constant MDErrorReporter\\:\\:MD_ERROR_KNOWN\\.$#"
count: 1
path: functions/functions.php
-
message: "#^Cannot access constant MD_ERROR_KNOWN on MDErrorReporter\\.$#"
count: 2
path: functions/functions.php
-
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertTrue\\(\\) with true and non\\-falsy\\-string will always evaluate to true\\.$#"
count: 1
path: tests/CsvxmlAvailableFieldsTest.php
-
message: "#^Instanceof between FieldEntry and FieldEntry will always evaluate to true\\.$#"
count: 1
path: tests/CsvxmlAvailableFieldsTest.php

View File

@ -6,14 +6,15 @@ parameters:
- functions
- inc
- public
- src
- tests
ignoreErrors:
- '#Class MDDBConnectionImpossible not found.#'
- '#Class MDMysqliExpectedError not found.#'
excludePaths:
- classes/MDAllowedValueSets/l18n
bootstrapFiles:
- inc/constants.php
excludes_analyse:
- classes/MDAllowedValueSets/l18n
disallowedFunctionCalls:
-
function: 'ini_alter()'
@ -63,3 +64,4 @@ parameters:
includes:
- classes/MD_QA/rules/phpstan-rules.neon
- vendor/spaze/phpstan-disallowed-calls/extension.neon
- phpstan-baseline.neon

View File

@ -65,11 +65,21 @@ h1 img:hover { opacity: 1; }
main,
body > div,
body > footer,
body > form { display: block; max-width: 90vw; margin: 0 auto 3em auto; padding-bottom: 3em; }
form > div { margin-bottom: 1em; }
label { display: block; font-weight: bold; margin-bottom: .5em; }
body > footer { border-top: .1em solid var(--color-borders); }
body > footer > div { display: block; }
body > footer > div a,
body > footer > div span { display: block; font-weight: bold; cursor: pointer;
color: var(--color-fg-less); transition: color .4s; }
body > footer > div a:hover,
body > footer > div span:hover { color: var(--color-accent-hover); }
.invisible { display: none !important; opacity: 0; }
.buttonLike,
@ -127,11 +137,11 @@ td { padding: .3em .5em; border-bottom: 1px solid var(--color-borders); }
background: var(--color-borders); border-radius: .2em;
color: var(--color-borders-dark); }
@media screen and (min-width: 75em) {
@media screen and (min-width: 768px) {
#helpSection > div { display: grid; grid-template-columns: 1fr 1fr; }
#helpSection > div > div { display: inline-block; grid-column: auto; }
}
@media screen and (min-width: 95em) {
@media screen and (min-width: 1366px) {
#helpSection > div { grid-template-columns: 1fr 1fr 1fr; }
}
@ -181,7 +191,7 @@ header { display: block; width: 100%; padding: 0 2em; font-size: 1rem; z-ind
header#mainHeader { margin-bottom: 2em;
background: var(--color-fg-less); color: var(--color-bg-raised2); display: table; }
header#mainHeader > * { display: table-cell; }
@media screen and (max-width: 70em) {
@media screen and (max-width: 768px) {
header#mainHeader > * { min-width: 20%; }
}
header#mainHeader > *:last-child { text-align: right; }
@ -205,7 +215,7 @@ header#mainHeader h2 { display: inline-block; vertical-align: middle; font-weigh
header#mainHeader > a:focus > img,
header#mainHeader > a:hover > img { opacity: .7; }
@media screen and (min-width: 75em) {
@media screen and (min-width: 768px) {
header nav > div > div { display: none; position: absolute; right: 0; top: 100%; width: 300px;
background: var(--color-fg-less); text-align: left; }
@ -222,7 +232,7 @@ header#mainHeader > a:hover > img { opacity: .7; }
header { padding: 0 10em; }
}
@media screen and (max-width: 75em) {
@media screen and (max-width: 768px) {
body { font-size: 1.08em; }
h1 img { display: none; }
header .branding { padding: .7rem; }

File diff suppressed because one or more lines are too long

View File

@ -10,7 +10,7 @@
box-shadow: 0px 4px 2px -2px var(--color-borders-dark); }
#newToolTipMain > * { padding: .5rem 1rem !important; }
#newToolTipMain > table td { padding: .5rem 1em; vertical-align: top; }
@media screen and (min-width:75em) {
@media screen and (min-width: 768px) {
#newToolTipMain.visible { display: block !important; }
}

View File

@ -24,10 +24,22 @@ class CsvxmlValidator {
this.fieldList = Object.freeze(fieldList);
const data = Papa.parse(csvRaw.trim(), {header: true});
const data = Papa.parse(csvRaw.trim(), {
delimiter: ";", // auto-detect
escapeChar: '"',
skipEmptyLines: true,
header: true,
});
if (data.errors.length !== 0) {
window.alert(data.errors);
console.log("Errors encountered: ");
console.error(data.errors);
let msg = '';
for (let err of data.errors) {
msg += err.type + ': ' + err.message + "\n";
}
window.alert(msg);
}
let toValidate = data.data;
@ -44,6 +56,7 @@ class CsvxmlValidator {
validate() {
this.validateMandatoryTagsPresent();
this.validateInvalidTagsPresent();
this.checkDuplicateInvNos();
this.checkDependentColumns();
this.checkControlledLists();
@ -73,6 +86,18 @@ class CsvxmlValidator {
}
validateInvalidTagsPresent() {
const headers = Object.keys(this.toValidate[0]);
for (let header of headers) {
if (this.fieldList[header] === undefined) {
this.errors.parsing.push("Invalid column \"" + header + "\" detected! Please remove this column or use the appropriate name!");
}
}
}
checkDuplicateInvNos() {
let invNoEncountered = [];
@ -97,11 +122,34 @@ class CsvxmlValidator {
let dependencies = this.fieldList[header].dependsOn;
for (let dep of dependencies) {
if (headers.includes(dep) === false) {
console.error("Dependency issue at column " + header + ": Corresponding column " + dep + " is missing");
console.log(headers);
this.errors.dependentColumns.push("Dependency issue at column " + header + ": Corresponding column " + dep + " is missing");
}
}
}
let lineCounter = 1;
for (let line of this.toValidate) {
for (let fieldName in line) {
if (line[fieldName] === '') continue;
if (this.fieldList[fieldName] === undefined) continue; // This may be the case if invalid fields are present
const dependencies = this.fieldList[fieldName].dependsOn;
if (dependencies === undefined) continue;
for (let dependency of dependencies) {
if (line[dependency] === '') {
console.error("Dependency issue at column " + fieldName + ": Corresponding column " + dependency + " is missing [on line " + lineCounter + "]");
console.log(line);
this.errors.dependentColumns.push("Dependency issue at column " + fieldName + " (current value: " + line[fieldName] + "): Corresponding column " + dependency + " is empty [on line " + lineCounter + "]");
}
}
}
lineCounter++;
}
}
checkControlledLists() {
@ -115,7 +163,7 @@ class CsvxmlValidator {
continue;
}
let allowedValues = this.fieldList[fieldName].allowedValues;
const allowedValues = this.fieldList[fieldName].allowedValues;
// No error if the field doesn't have a controlled list
if (allowedValues === undefined || allowedValues === null) continue;
@ -124,6 +172,7 @@ class CsvxmlValidator {
continue;
}
if (line[fieldName] === '') continue;
this.errors.controlledLists.push("Disallowed value used for column " + fieldName + " at line " + lineCounter + " (Allowed values are: " + Object.values(allowedValues).join(", ") + "; current value is " + line[fieldName] + ")");
}
lineCounter++;
@ -385,7 +434,9 @@ class CsvxmlPage {
if (field.allowedValues !== undefined) {
// Join for object
let values = [];
for (let key in field.allowedValues) values.push(field.allowedValues[key]);
for (let key in field.allowedValues) {
values.push(field.allowedValues[key]);
}
line3.push(values.join(","));
}
else line3.push("");
@ -532,7 +583,8 @@ class CsvxmlPage {
uploadFileForValidation(file) {
const reader = new FileReader();
reader.readAsText(file);
let utf8 = true;
reader.readAsText(file, utf8 ? 'UTF-8' : 'CP1251');
let app = this;
@ -542,6 +594,13 @@ class CsvxmlPage {
function handleValidation() {
(async function() {
const result = reader.result;
if (utf8 && result.includes('<27>')) {
window.alert('The file encoding appears to not be UTF-8!\n\nTry exporting the file using the format "CSV (UTF-8)" if you use MS Excel or set the encoding to UTF-8 when exporting through LibreOffice!');
}
})();
// On loading success, check if the upload is valid JSON
console.log("Read file");
// Validate the file
@ -703,6 +762,8 @@ class CsvxmlPage {
const div = document.createElement("div");
div.appendChild(appendQA(app.tls.help_where_am_i, app.tls.help_where_am_i_content));
div.appendChild(appendQA(app.tls.help_what_is_csv, app.tls.help_what_is_csv_content));
div.appendChild(appendQA(app.tls.help_how_to_format_csv, app.tls.help_how_to_format_csv_content));
app.domHelpWrapper.appendChild(div);
@ -987,6 +1048,45 @@ class CsvxmlPage {
}
renderFooter() {
const footer = document.createElement("footer");
const licenseStatement = document.createElement("p");
licenseStatement.textContent = "This work is licensed under the GNU Affero Public License Version 3.";
footer.appendChild(licenseStatement);
const footerOptions = document.createElement("div");
const codeLink = document.createElement("a");
codeLink.textContent = "Source code";
codeLink.href = "https://gitea.armuli.eu/museum-digital/csvxml";
footerOptions.appendChild(codeLink);
if ('serviceWorker' in navigator) {
const refreshB = document.createElement("span");
refreshB.textContent = "Reload application";
refreshB.setAttribute("tabindex", 1);
refreshB.addEventListener('click', function(e) {
Promise.all(['csvxml-cache-v1'].map(function(cache) {
caches.has(cache).then(function(hasCache) {
if (hasCache === true) {
caches.delete(cache).then(function(deletionStatus) {});
}
})
}))
location.reload()
}, {passive: true, once: true});
footerOptions.appendChild(refreshB);
}
footer.appendChild(footerOptions);
document.body.appendChild(footer);
}
}
(async function() {
@ -1025,6 +1125,7 @@ class CsvxmlPage {
page.renderHelpTexts();
page.renderUploader();
page.renderMain();
page.renderFooter();
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
Last update: 2024-07-01
v5.4.1

View File

@ -1,10 +1,10 @@
<!DOCTYPE HTML>
<html data-allowed-langs="de,en,hu">
<html data-allowed-langs="de,en,hu,ru,uk">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="assets/css/csvxml.min.css?v000005" />
<link rel="stylesheet" type="text/css" href="assets/css/csvxml.min.css?68373532391e5" />
<link rel="manifest" href="/manifest.json" />
<meta name="theme-color" content="#aa4400" />
@ -27,7 +27,7 @@
</head>
<body class="loading">
<script src="assets/js/csvxmlV2.min.js?v000005" type="text/javascript" async></script>
<script src="assets/js/csvxmlV2.min.js?68373532391e7" type="text/javascript" async></script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{"remarks":"Notizen","download":"Download","upload":"Hochladen","select_csv_file_for_upload":"Bitte w\u00e4hlen Sie eine CSV Datei als Basis zum Erstellen von XML Dateien","currently_approved_tags":"Derzeit zum Import verf\u00fcgbare Tags \/ Felder","download_csv_all":"CSV-Vorlage mit allen Feldern runterladen","download_csv_by_selection":"CSV-Vorlage auf Basis der Auswahl herunterladen","select_required_fields":"Pflichtfelder ausw\u00e4hlen","select_all_fields":"Alle Felder ausw\u00e4hlen","unset_selection":"Auswahl entfernen","file_format":"Dateiformat","validation_errors":"Validierungsfehler","errors_parsing":"Parsing-Fehler","errors_mandatoryTags":"Fehlende Pflichtfelder","errors_duplicateInvNos":"Doppelte Inventarnummern","errors_dependentColumns":"Spaltenabh\u00e4ngigkeiten nicht ber\u00fccksichtigt","errors_controlledLists":"Kontrollierte Werte","errors_mainImageResource":"Fehlende Haupt-Bilder oder Ressourcen","allowed_values":"Zugelassene Werte","privacy_policy":"Datenschutzerkl\u00e4rung","contact":"Kontakt","news":"Neuigkeiten","imprint":"Impressum","about":"\u00dcber","help_where_am_i":"What is this page for?","help_where_am_i_content":" CSVXML helps validate import object data for museum-digital following museum-digital's standard import format."}
{"remarks":"Notizen","download":"Download","upload":"Hochladen","select_csv_file_for_upload":"Bitte w\u00e4hlen Sie eine CSV Datei als Basis zum Erstellen von XML Dateien","currently_approved_tags":"Derzeit zum Import verf\u00fcgbare Tags \/ Felder","download_csv_all":"CSV-Vorlage mit allen Feldern runterladen","download_csv_by_selection":"CSV-Vorlage auf Basis der Auswahl herunterladen","select_required_fields":"Pflichtfelder ausw\u00e4hlen","select_all_fields":"Alle Felder ausw\u00e4hlen","unset_selection":"Auswahl entfernen","file_format":"Dateiformat","validation_errors":"Validierungsfehler","errors_parsing":"Parsing-Fehler","errors_mandatoryTags":"Fehlende Pflichtfelder","errors_duplicateInvNos":"Doppelte Inventarnummern","errors_dependentColumns":"Spaltenabh\u00e4ngigkeiten nicht ber\u00fccksichtigt","errors_controlledLists":"Kontrollierte Werte","errors_mainImageResource":"Fehlende Haupt-Bilder oder Ressourcen","allowed_values":"Zugelassene Werte","privacy_policy":"Datenschutzerkl\u00e4rung","contact":"Kontakt","news":"Neuigkeiten","imprint":"Impressum","about":"\u00dcber","help_where_am_i":"Wo bin ich hier?","help_where_am_i_content":"CSVXML ist ein Werkzeug um Objektdaten, die im sogenannten CSV-Format vorliegen in ein XML-Format zu \u00fcbertragen. Mehr noch: Es ist ein Pr\u00fcfprogramm, mit welchem das Vorhandensein von f\u00fcr den Import bei museum-digital verpflichtenden Informationen und die Ber\u00fccksichtigung von Abh\u00e4ngigkeiten getestet werden kann. Nach jeder Pr\u00fcfung gibt das Programm Auskunft, wo Nachbesserungen n\u00f6tig sind. Werden diese ber\u00fccksichtigt, so kann am Ende des Pr\u00fcfprozesses eine ZIP-Datei vom Programm erstellt werden, die zu jedem Objekt eine XML-Datei enth\u00e4lt, die jeweils in einer Form und Vollst\u00e4ndigkeit vorliegt, dass ein direkter Import nach museum-digital m\u00f6glich wird.\r\n\r\nEine CSV-Datei mit den f\u00fcr den Import erlaubten Datenfeldern kann unten generiert werden.","help_what_is_csv":"Was hei\u00dft CSV?","help_what_is_csv_content":"CSV steht f\u00fcr Comma Separated Value. Es handelt sich dabei um ein Dateiformat, mit dem tabellarische Informationen in einer reinen Textdatei ausgedr\u00fcckt werden k\u00f6nnen, und wird auch von den meisten Tabellenkalkulationsprogrammen wie Excel und LibreOffice Calc unterst\u00fctzt. W\u00e4hrend nach der urspr\u00fcnglichen Definition des Standards nur eine ASCii-Kodierung der Daten erlaubt war, zeigte sich im Laufe der Jahre, dass die Benutzung breiterer Kodierungen wie UTF-8 in der Praxis n\u00f6tig ist. Ebenso lassen sich in den meisten Kalkulationsprogrammen Semikola oder andere Trennzeichen statt eines Kommas setzen. CSV ist keinesfalls identisch mit Standard-Excel-Dateien. Jedoch kann jede Excel-Datei \u2013 \u00fcber \u201eSpeichern unter \u2026\u201c als CSV-Datei gespeichert werden.","help_how_to_format_csv":"Wie muss das CSV geformt sein?","help_how_to_format_csv_content":"Damit CSVXML mit einer CSV-Datei umgehen kann und importierbare Daten generieren kann, muss die CSV-Datei in passender Form heraufgeladen werden. Dazu geh\u00f6rt vor allem, dass Semikola als Trennzeichen und doppelte Anf\u00fchrungsstriche als Delimiter ausgew\u00e4hlt sein m\u00fcssen. Die enthaltenen Daten m\u00fcssen in der Kodierung UTF-8 vorliegen, sonst erscheinen z.B. im XML statt Umlauten unerwartete Zeichen. Neuere Excel-Versionen erlauben im Dialog \u201eSpeichern unter\u201c die Auswahl \u201eCSV UTF-8 (durch Trennzeichen getrennt) (*.csv)\u201c. Hier\u00fcber k\u00f6nnen Sie ihre urspr\u00fcngliche Excel-Datei im f\u00fcr CSVXML passenden Format speichern. LibreOffice Calc bietet eine \u00e4quivalente Option.","file_encoding_is_not_utf8":"Die Datei scheint nicht UTF-8-kodiert zu sein!","non_utf8_file_instruction":"Versuchen Sie die Datei als \"CSV (UTF-8)\" zu speichern, falls sie MS Excel verwenden, oder die Dateikodierung beim Speichern auf \"UTF-8\" einzustellen, falls Sie LibreOffice Calc verwenden."}

View File

@ -1 +1 @@
{"remarks":"Remarks","download":"Download","upload":"Upload","select_csv_file_for_upload":"Please select a CSV file to create XML files","currently_approved_tags":"Currently approved tags (column names) for md:import","download_csv_all":"Download CSV template with all fields","download_csv_by_selection":"Download CSV template based on selection","select_required_fields":"Select required fields","select_all_fields":"Select all fields","unset_selection":"Unset selection","file_format":"File format","validation_errors":"Validation errors","errors_parsing":"Parse errors","errors_mandatoryTags":"Missing mandatory tags","errors_duplicateInvNos":"Duplicate inventory numbers","errors_dependentColumns":"Column dependencies unresolved","errors_controlledLists":"Controlled lists","errors_mainImageResource":"Missing main images or resources","allowed_values":"Allowed values","privacy_policy":"Privacy policy","contact":"Contact","news":"News","imprint":"Imprint","about":"About","help_where_am_i":"What is this page for?","help_where_am_i_content":" CSVXML helps validate import object data for museum-digital following museum-digital's standard import format."}
{"remarks":"Remarks","download":"Download","upload":"Upload","select_csv_file_for_upload":"Please select a CSV file to create XML files","currently_approved_tags":"Currently approved tags (column names) for md:import","download_csv_all":"Download CSV template with all fields","download_csv_by_selection":"Download CSV template based on selection","select_required_fields":"Select required fields","select_all_fields":"Select all fields","unset_selection":"Unset selection","file_format":"File format","validation_errors":"Validation errors","errors_parsing":"Parse errors","errors_mandatoryTags":"Missing mandatory tags","errors_duplicateInvNos":"Duplicate inventory numbers","errors_dependentColumns":"Column dependencies unresolved","errors_controlledLists":"Controlled lists","errors_mainImageResource":"Missing main images or resources","allowed_values":"Allowed values","privacy_policy":"Privacy policy","contact":"Contact","news":"News","imprint":"Imprint","about":"About","help_where_am_i":"What is this page for?","help_where_am_i_content":"In its most simple usage, CSVXML is a tool for generating XML files from a given CSV table. It comes with a validation tool for checking the validity of the data against the standard import format at museum-digital, e.g. in terms of the availability of required fields and dependencies between fields. After the validation, a ZIP file containing one XML file per object is generated. If the validation proceeded without errors, these XML files can be imported to museum-digital without any further issues. A sample CSV file formatted according to the standard format for imports at museum-digital can be generated below.","help_what_is_csv":"What is CSV?","help_what_is_csv_content":"CSV is the abbreviation for \u201eComma Separated Value\u201c. It describes a file format for expressing tabular information in plain text files, that is supported by most table calculation programms such as MS Excel and LibreOffice Calc. It is thus a useful choice for quickly generating and sharing semi-structured data that can be further processed by other programms.","help_how_to_format_csv":"How to format CSV files for CSVXML?","help_how_to_format_csv_content":"CSVXML first of all requires CSV file using semicolons as a separator and double quotation marks as a delimiter. For generating actually importable data, it is advisable to save the CSV file in UTF-8 rather than the standard-conformant ASCII. Both current versions of MS Excel and LibreOffice Calc support export options for exporting CSV files using UTF-8 encoding.","file_encoding_is_not_utf8":"The file encoding appears to not be UTF-8!","non_utf8_file_instruction":"Try exporting the file using the format \"CSV (UTF-8)\" if you use MS Excel or set the encoding to UTF-8 when exporting through LibreOffice!"}

View File

@ -1 +1 @@
{"remarks":"Megjegyz\u00e9sek","download":"Let\u00f6lt\u00e9s","upload":"Felt\u00f6lt\u00e9s","select_csv_file_for_upload":"Please select a CSV file to create XML files","currently_approved_tags":"Jelenleg j\u00f3v\u00e1hagyott c\u00edmk\u00e9k (oszlopnevek) az md:importhoz","download_csv_all":"Download CSV template with all fields","download_csv_by_selection":"Download CSV template based on selection","select_required_fields":"K\u00f6telez\u0151 mez\u0151k kijel\u00f6l\u00e9se","select_all_fields":"\u00d6sszes mez\u0151 kijel\u00f6l\u00e9s","unset_selection":"Kijel\u00f6l\u00e9s megsz\u00fcntet\u00e9se","file_format":"Kiterjeszt\u00e9s","validation_errors":"Validation errors","errors_parsing":"Parse errors","errors_mandatoryTags":"Missing mandatory tags","errors_duplicateInvNos":"Duplicate inventory numbers","errors_dependentColumns":"Column dependencies unresolved","errors_controlledLists":"Controlled lists","errors_mainImageResource":"Missing main images or resources","allowed_values":"Allowed values","privacy_policy":"Privacy policy","contact":"Contact","news":"News","imprint":"Imprint","about":"About","help_where_am_i":"What is this page for?","help_where_am_i_content":" CSVXML helps validate import object data for museum-digital following museum-digital's standard import format."}
{"remarks":"Megjegyz\u00e9sek","download":"Let\u00f6lt\u00e9s","upload":"Felt\u00f6lt\u00e9s","select_csv_file_for_upload":"Please select a CSV file to create XML files","currently_approved_tags":"Jelenleg j\u00f3v\u00e1hagyott c\u00edmk\u00e9k (oszlopnevek) az md:importhoz","download_csv_all":"Download CSV template with all fields","download_csv_by_selection":"Download CSV template based on selection","select_required_fields":"K\u00f6telez\u0151 mez\u0151k kijel\u00f6l\u00e9se","select_all_fields":"\u00d6sszes mez\u0151 kijel\u00f6l\u00e9s","unset_selection":"Kijel\u00f6l\u00e9s megsz\u00fcntet\u00e9se","file_format":"Kiterjeszt\u00e9s","validation_errors":"Validation errors","errors_parsing":"Parse errors","errors_mandatoryTags":"Missing mandatory tags","errors_duplicateInvNos":"Duplicate inventory numbers","errors_dependentColumns":"Column dependencies unresolved","errors_controlledLists":"Controlled lists","errors_mainImageResource":"Missing main images or resources","allowed_values":"Allowed values","privacy_policy":"Privacy policy","contact":"Contact","news":"News","imprint":"Imprint","about":"About","help_where_am_i":"What is this page for?","help_where_am_i_content":"In its most simple usage, CSVXML is a tool for generating XML files from a given CSV table. It comes with a validation tool for checking the validity of the data against the standard import format at museum-digital, e.g. in terms of the availability of required fields and dependencies between fields. After the validation, a ZIP file containing one XML file per object is generated. If the validation proceeded without errors, these XML files can be imported to museum-digital without any further issues. A sample CSV file formatted according to the standard format for imports at museum-digital can be generated below.","help_what_is_csv":"What is CSV?","help_what_is_csv_content":"CSV is the abbreviation for \u201eComma Separated Value\u201c. It describes a file format for expressing tabular information in plain text files, that is supported by most table calculation programms such as MS Excel and LibreOffice Calc. It is thus a useful choice for quickly generating and sharing semi-structured data that can be further processed by other programms.","help_how_to_format_csv":"How to format CSV files for CSVXML?","help_how_to_format_csv_content":"CSVXML first of all requires CSV file using semicolons as a separator and double quotation marks as a delimiter. For generating actually importable data, it is advisable to save the CSV file in UTF-8 rather than the standard-conformant ASCII. Both current versions of MS Excel and LibreOffice Calc support export options for exporting CSV files using UTF-8 encoding.","file_encoding_is_not_utf8":"The file encoding appears to not be UTF-8!","non_utf8_file_instruction":"Try exporting the file using the format \"CSV (UTF-8)\" if you use MS Excel or set the encoding to UTF-8 when exporting through LibreOffice!"}

1
public/json/tls.ru.json Normal file

File diff suppressed because one or more lines are too long

1
public/json/tls.uk.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -62,6 +62,14 @@ function generateTranslationFile(string $lang):string {
'help_where_am_i' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'help_where_am_i'),
'help_where_am_i_content' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'help_where_am_i_content'),
'help_what_is_csv' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'help_what_is_csv'),
'help_what_is_csv_content' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'help_what_is_csv_content'),
'help_how_to_format_csv' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'help_how_to_format_csv'),
'help_how_to_format_csv_content' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'help_how_to_format_csv_content'),
'file_encoding_is_not_utf8' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'file_encoding_is_not_utf8'),
'non_utf8_file_instruction' => $tlLoader->tl("csvxml-overview", "csvxml_overview", 'non_utf8_file_instruction'),
]);
}
@ -79,7 +87,7 @@ function generateAppShell():string {
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="assets/css/csvxml.min.css?v000005" />
<link rel="stylesheet" type="text/css" href="assets/css/csvxml.min.css?' . uniqid() . '" />
<link rel="manifest" href="/manifest.json" />
<meta name="theme-color" content="#aa4400" />
@ -102,7 +110,7 @@ function generateAppShell():string {
</head>
<body class="loading">
<script src="assets/js/csvxmlV2.min.js?v000005" type="text/javascript" async></script>
<script src="assets/js/csvxmlV2.min.js?' . uniqid() . '" type="text/javascript" async></script>
</body>
</html>';

File diff suppressed because it is too large Load Diff

View File

@ -32,9 +32,9 @@ final class FieldEntry {
* @param string $explica Explanation.
*/
public function __construct(
bool $required, array $allowedValues,
array $dependsOn, string $remark,
string $name_human_readable, string $explica
bool $required = false, array $allowedValues = [],
array $dependsOn = [], string $remark = "",
string $name_human_readable = "", string $explica = ""
) {
$this->required = $required;
$this->allowedValues = $allowedValues;