Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F9345717
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
39 KB
Subscribers
None
View Options
diff --git a/cypress/integration/persons.js b/cypress/integration/persons.js
index d32016b..a296afc 100644
--- a/cypress/integration/persons.js
+++ b/cypress/integration/persons.js
@@ -1,264 +1,424 @@
/**
* Copyright (C) 2020 The Software Heritage developers
* See the AUTHORS file at the top-level directory of this distribution
* License: GNU Affero General Public License version 3, or any later version
* See top-level LICENSE file for more information
*/
/*
* Tests the author/contributor dynamic fieldsets
*/
"use strict";
describe('Zero author', function() {
it('can be exported', function() {
cy.get('#name').type('My Test Software');
cy.get('#generateCodemeta').click();
cy.get('#errorMessage').should('have.text', '');
cy.get('#codemetaText').then((elem) => JSON.parse(elem.text()))
.should('deep.equal', {
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
"@type": "SoftwareSourceCode",
"name": "My Test Software",
});
});
it('can be imported from no list', function() {
cy.get('#codemetaText').then((elem) =>
elem.text(JSON.stringify({
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
"@type": "SoftwareSourceCode",
"name": "My Test Software",
}))
);
cy.get('#importCodemeta').click();
cy.get('#author_nb').should('have.value', '0');
cy.get('#author_0').should('not.exist');
cy.get('#author_1').should('not.exist');
});
it('can be imported from empty list', function() {
cy.get('#codemetaText').then((elem) =>
elem.text(JSON.stringify({
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
"@type": "SoftwareSourceCode",
"name": "My Test Software",
"author": [],
}))
);
cy.get('#importCodemeta').click();
cy.get('#author_nb').should('have.value', '0');
cy.get('#author_0').should('not.exist');
cy.get('#author_1').should('not.exist');
});
});
describe('One full author', function() {
it('can be exported', function() {
cy.get('#name').type('My Test Software');
cy.get('#author_nb').should('have.value', '0');
cy.get('#author_0').should('not.exist');
cy.get('#author_1').should('not.exist');
cy.get('#author_1_givenName').should('not.exist');
cy.get('#author_add').click();
cy.get('#author_nb').should('have.value', '1');
cy.get('#author_0').should('not.exist');
cy.get('#author_1').should('exist');
cy.get('#author_2').should('not.exist');
cy.get('#author_1_givenName').should('have.value', '');
cy.get('#author_1_familyName').should('have.value', '');
cy.get('#author_1_email').should('have.value', '');
cy.get('#author_1_id').should('have.value', '');
cy.get('#author_1_affiliation').should('have.value', '');
cy.get('#author_1_givenName').type('Jane');
cy.get('#author_1_familyName').type('Doe');
cy.get('#author_1_email').type('jdoe@example.org');
cy.get('#author_1_id').type('http://example.org/~jdoe');
cy.get('#author_1_affiliation').type('http://example.org/');
cy.get('#generateCodemeta').click();
cy.get('#errorMessage').should('have.text', '');
cy.get('#codemetaText').then((elem) => JSON.parse(elem.text()))
.should('deep.equal', {
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
"@type": "SoftwareSourceCode",
"name": "My Test Software",
"author": [
{
"@type": "Person",
"@id": "http://example.org/~jdoe",
"givenName": "Jane",
"familyName": "Doe",
"email": "jdoe@example.org",
"affiliation": {
"@type": "Organization",
"@id": "http://example.org/",
}
}
],
});
});
it('can be imported', function() {
cy.get('#codemetaText').then((elem) =>
elem.text(JSON.stringify({
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
"@type": "SoftwareSourceCode",
"name": "My Test Software",
"author": [
{
"@type": "Person",
"@id": "http://example.org/~jdoe",
"givenName": "Jane",
"familyName": "Doe",
"email": "jdoe@example.org",
"affiliation": {
"@type": "Organization",
"@id": "http://example.org/",
}
}
],
}))
);
cy.get('#importCodemeta').click();
cy.get('#author_nb').should('have.value', '1');
cy.get('#author_0').should('not.exist');
cy.get('#author_1').should('exist');
cy.get('#author_2').should('not.exist');
cy.get('#author_1_givenName').should('have.value', 'Jane');
cy.get('#author_1_familyName').should('have.value', 'Doe');
cy.get('#author_1_email').should('have.value', 'jdoe@example.org');
cy.get('#author_1_id').should('have.value', 'http://example.org/~jdoe');
cy.get('#author_1_affiliation').should('have.value', 'http://example.org/');
});
});
describe('Affiliation id', function() {
it('can be exported', function() {
cy.get('#name').type('My Test Software');
cy.get('#author_add').click();
cy.get('#author_1_givenName').type('Jane');
cy.get('#author_1_affiliation').type('http://example.org/');
cy.get('#generateCodemeta').click();
cy.get('#errorMessage').should('have.text', '');
cy.get('#codemetaText').then((elem) => JSON.parse(elem.text()))
.should('deep.equal', {
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
"@type": "SoftwareSourceCode",
"name": "My Test Software",
"author": [
{
"@type": "Person",
"givenName": "Jane",
"affiliation": {
"@type": "Organization",
"@id": "http://example.org/",
}
}
],
});
});
it('can be imported', function() {
cy.get('#codemetaText').then((elem) =>
elem.text(JSON.stringify({
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
"@type": "SoftwareSourceCode",
"name": "My Test Software",
"author": [
{
"@type": "Person",
"@id": "http://example.org/~jdoe",
"givenName": "Jane",
"familyName": "Doe",
"email": "jdoe@example.org",
"affiliation": {
"@type": "Organization",
"@id": "http://example.org/",
}
}
],
}))
);
cy.get('#importCodemeta').click();
cy.get('#author_nb').should('have.value', '1');
cy.get('#author_0').should('not.exist');
cy.get('#author_1').should('exist');
cy.get('#author_2').should('not.exist');
cy.get('#author_1_affiliation').should('have.value', 'http://example.org/');
});
});
describe('Affiliation name', function() {
it('can be exported', function() {
cy.get('#name').type('My Test Software');
cy.get('#author_add').click();
cy.get('#author_1_givenName').type('Jane');
cy.get('#author_1_affiliation').type('Example Org');
cy.get('#generateCodemeta').click();
cy.get('#errorMessage').should('have.text', '');
cy.get('#codemetaText').then((elem) => JSON.parse(elem.text()))
.should('deep.equal', {
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
"@type": "SoftwareSourceCode",
"name": "My Test Software",
"author": [
{
"@type": "Person",
"givenName": "Jane",
"affiliation": {
"@type": "Organization",
"name": "Example Org",
}
}
],
});
});
it('can be imported', function() {
cy.get('#codemetaText').then((elem) =>
elem.text(JSON.stringify({
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
"@type": "SoftwareSourceCode",
"name": "My Test Software",
"author": [
{
"@type": "Person",
"@id": "http://example.org/~jdoe",
"givenName": "Jane",
"familyName": "Doe",
"email": "jdoe@example.org",
"affiliation": {
"@type": "Organization",
"name": "Example Org",
}
}
],
}))
);
cy.get('#importCodemeta').click();
cy.get('#author_nb').should('have.value', '1');
cy.get('#author_0').should('not.exist');
cy.get('#author_1').should('exist');
cy.get('#author_2').should('not.exist');
cy.get('#author_1_affiliation').should('have.value', 'Example Org');
});
});
+
+describe('Author order change', function() {
+ it('is a noop with a single author', function() {
+ cy.get('#name').type('My Test Software');
+
+ cy.get('#author_add').click();
+ cy.get('#author_1_givenName').type('Jane');
+ cy.get('#author_1_affiliation').type('Example Org');
+
+ cy.get('#author_1_moveToRight').click()
+
+ cy.get('#author_1_givenName').should('have.value', 'Jane');
+ cy.get('#author_1_affiliation').should('have.value', 'Example Org');
+
+ cy.get('#author_1_moveToLeft').click()
+
+ cy.get('#author_1_givenName').should('have.value', 'Jane');
+ cy.get('#author_1_affiliation').should('have.value', 'Example Org');
+ });
+
+ it('flips two authors', function() {
+ cy.get('#name').type('My Test Software');
+
+ cy.get('#author_add').click();
+ cy.get('#author_add').click();
+ cy.get('#author_add').click();
+ cy.get('#author_1_givenName').type('Jane');
+ cy.get('#author_1_affiliation').type('Example Org');
+ cy.get('#author_2_givenName').type('John');
+ cy.get('#author_2_familyName').type('Doe');
+ cy.get('#author_3_givenName').type('Alex');
+
+ cy.get('#author_1_moveToRight').click()
+
+ cy.get('#author_1_givenName').should('have.value', 'John');
+ cy.get('#author_1_familyName').should('have.value', 'Doe');
+ cy.get('#author_1_affiliation').should('have.value', '');
+
+ cy.get('#author_2_givenName').should('have.value', 'Jane');
+ cy.get('#author_2_familyName').should('have.value', '');
+ cy.get('#author_2_affiliation').should('have.value', 'Example Org');
+
+ cy.get('#author_3_givenName').should('have.value', 'Alex');
+ cy.get('#author_3_familyName').should('have.value', '');
+ cy.get('#author_3_affiliation').should('have.value', '');
+ });
+
+ it('updates generated Codemeta', function() {
+ cy.get('#name').type('My Test Software');
+
+ cy.get('#author_add').click();
+ cy.get('#author_add').click();
+ cy.get('#author_1_givenName').type('Jane');
+ cy.get('#author_1_affiliation').type('Example Org');
+ cy.get('#author_2_givenName').type('John');
+ cy.get('#author_2_familyName').type('Doe');
+
+ cy.get('#generateCodemeta').click();
+
+ cy.get('#codemetaText').then((elem) => JSON.parse(elem.text()))
+ .should('deep.equal', {
+ "@context": "https://doi.org/10.5063/schema/codemeta-2.0",
+ "@type": "SoftwareSourceCode",
+ "name": "My Test Software",
+ "author": [
+ {
+ "@type": "Person",
+ "givenName": "Jane",
+ "affiliation": {
+ "@type": "Organization",
+ "name": "Example Org",
+ }
+ },
+ {
+ "@type": "Person",
+ "givenName": "John",
+ "familyName": "Doe",
+ },
+ ],
+ });
+
+ cy.get('#author_1_moveToRight').click();
+
+ cy.get('#codemetaText').then((elem) => JSON.parse(elem.text()))
+ .should('deep.equal', {
+ "@context": "https://doi.org/10.5063/schema/codemeta-2.0",
+ "@type": "SoftwareSourceCode",
+ "name": "My Test Software",
+ "author": [
+ {
+ "@type": "Person",
+ "givenName": "John",
+ "familyName": "Doe",
+ },
+ {
+ "@type": "Person",
+ "givenName": "Jane",
+ "affiliation": {
+ "@type": "Organization",
+ "name": "Example Org",
+ }
+ },
+ ],
+ });
+ });
+
+ it('wraps around to the right', function() {
+ cy.get('#name').type('My Test Software');
+
+ cy.get('#author_add').click();
+ cy.get('#author_add').click();
+ cy.get('#author_add').click();
+ cy.get('#author_1_givenName').type('Jane');
+ cy.get('#author_1_affiliation').type('Example Org');
+ cy.get('#author_2_givenName').type('John');
+ cy.get('#author_2_familyName').type('Doe');
+ cy.get('#author_3_givenName').type('Alex');
+
+ cy.get('#author_1_moveToLeft').click()
+
+ cy.get('#author_1_givenName').should('have.value', 'Alex');
+ cy.get('#author_1_familyName').should('have.value', '');
+ cy.get('#author_1_affiliation').should('have.value', '');
+
+ cy.get('#author_2_givenName').should('have.value', 'John');
+ cy.get('#author_2_familyName').should('have.value', 'Doe');
+ cy.get('#author_2_affiliation').should('have.value', '');
+
+ cy.get('#author_3_givenName').should('have.value', 'Jane');
+ cy.get('#author_3_familyName').should('have.value', '');
+ cy.get('#author_3_affiliation').should('have.value', 'Example Org');
+ });
+
+ it('wraps around to the left', function() {
+ cy.get('#name').type('My Test Software');
+
+ cy.get('#author_add').click();
+ cy.get('#author_add').click();
+ cy.get('#author_add').click();
+ cy.get('#author_1_givenName').type('Jane');
+ cy.get('#author_1_affiliation').type('Example Org');
+ cy.get('#author_2_givenName').type('John');
+ cy.get('#author_2_familyName').type('Doe');
+ cy.get('#author_3_givenName').type('Alex');
+
+ cy.get('#author_3_moveToRight').click()
+
+ cy.get('#author_1_givenName').should('have.value', 'Alex');
+ cy.get('#author_1_familyName').should('have.value', '');
+ cy.get('#author_1_affiliation').should('have.value', '');
+
+ cy.get('#author_2_givenName').should('have.value', 'John');
+ cy.get('#author_2_familyName').should('have.value', 'Doe');
+ cy.get('#author_2_affiliation').should('have.value', '');
+
+ cy.get('#author_3_givenName').should('have.value', 'Jane');
+ cy.get('#author_3_familyName').should('have.value', '');
+ cy.get('#author_3_affiliation').should('have.value', 'Example Org');
+ });
+})
diff --git a/index.html b/index.html
index 691f4ec..38f7cbe 100644
--- a/index.html
+++ b/index.html
@@ -1,357 +1,355 @@
<!doctype html>
<!--
Copyright (C) 2019-2020 The Software Heritage developers
See the AUTHORS file at the top-level directory of this distribution
License: GNU Affero General Public License version 3, or any later version
See top-level LICENSE file for more information
-->
<html lang="en">
<head>
<meta charset="utf-8">
<title>CodeMeta generator</title>
<script src="./js/utils.js"></script>
<script src="./js/fields_data.js"></script>
<script src="./js/dynamic_form.js"></script>
<script src="./js/codemeta_generation.js"></script>
<script src="./js/validation/primitives.js"></script>
<script src="./js/validation/things.js"></script>
<script src="./js/validation/index.js"></script>
<link rel="stylesheet" type="text/css" href="./main.css">
<link rel="stylesheet" type="text/css" href="./codemeta.css">
</head>
<body>
<header>
<h1>CodeMeta generator</h1>
</header>
<main>
<p>Most fields are optional. Mandatory fields will be highlighted when generating Codemeta.</p>
<noscript>
<p id="noscriptError">
This application requires Javascript to show dynamic fields in the form,
and generate a JSON file; but your browser does not support Javascript.
If you cannot use a browser with Javascript support, you can try
<a href="https://codemeta.github.io/tools/">one of the other available tools</a>
or write the codemeta.json file directly.
</p>
</noscript>
<form id="inputForm">
<fieldset id="fieldsetSoftwareItself" class="leafFieldset">
<legend>The software itself</legend>
<p title="The name of the software">
<label for="name">Name</label>
<input type="text" name="name" id="name" aria-describedby="name_descr"
placeholder="My Software" required="required" />
<span class="field-description" id="name_descr">the software title</span>
</p>
<p title="a brief description of the software">
<label for="description">Description</label>
<textarea rows="4" cols="50"
name="description" id="description"
placeholder="My Software computes ephemerides and orbit propagation. It has been developed from early ´80." ></textarea>
</p>
<p title="The date on which the software was created.">
<label for="dateCreated">Creation date</label>
<input type="text" name="dateCreated" id="dateCreated"
placeholder="YYYY-MM-DD" pattern="\d{4}-\d{2}-\d{2}" />
</p>
<p title="Date of first publication.">
<label for="datePublished">First release date</label>
<input type="text" name="datePublished" id="datePublished"
placeholder="YYYY-MM-DD" pattern="\d{4}-\d{2}-\d{2}" />
</p>
<p>
<label for="license">License</label>
<input list="licenses" name="license" id="license"
aria-describedby="licenses_descr"> <!-- TODO: insert placeholder -->
<datalist id="licenses">
</datalist>
<!-- This datalist is be filled automatically -->
<br />
<span class="field-description" id="licenses_descr">from <a href="https://spdx.org/license-list">SPDX licence list</a></span>
</p>
</fieldset>
<fieldset id="fieldsetDiscoverabilityAndCitation" class="leafFieldset">
<legend>Discoverability and citation</legend>
<p title="Unique identifier">
<label for="identifier">Unique identifier</label>
<input type="text" name="identifier" id="identifier"
placeholder="10.151.xxxxx" aria-describedby="identifier_descr" />
<br />
<span class="field-description" id="identifier_descr">
such as ISBNs, GTIN codes, UUIDs etc.. <a href="http://schema.org/identifier">http://schema.org/identifier</a>
</span>
</p>
<!-- TODO:define better
I looked at the schema.org definition of identifier (https://schema.org/identifier),
it can be text, url or PropertyValue.
Used as follows in data representation with microdata:
<div property="identifier" typeof="PropertyValue">
<span property="propertyID">DOI</span>:
<span property="value">10.151.xxxxx</span>
</div>
we can use that with identifier-type and identifier-value to have a clearer idea
of what needs to be in the input.
-->
<p title="Type of the software application">
<label for="applicationCategory">Application category</label>
<input type="text" name="applicationCategory" id="applicationCategory"
placeholder="Astronomy" />
</p>
<p title="Comma-separated list of keywords">
<label for="keywords">Keywords</label>
<input type="text" name="keywords" id="keywords"
placeholder="ephemerides, orbit, astronomy" />
</p>
<p title="Funding / grant">
<label for="funding">Funding</label>
<input type="text" name="funding" id="funding" aria-describedby="funding_descr"
placeholder="PRA_2018_73"/>
<br />
<span class="field-description" id="funding_descr">grant funding software development</span>
</p>
<p title="Funding / organization">
<label for="funder">Funder</label>
<input type="text" name="funder" id="funder" aria-describedby="funder_descr"
placeholder="Università di Pisa"/>
<br />
<span class="field-description" id="funder_descr">organization funding software development</span>
</p>
Authors and contributors can be added below
</fieldset>
<fieldset id="fieldsetDevelopmentCommunity" class="leafFieldset">
<legend>Development community / tools</legend>
<p title="Link to the repository where the un-compiled, human readable code and related code is located (SVN, Git, GitHub, CodePlex, institutional GitLab instance, etc.).">
<label for="codeRepository">Code repository</label>
<input type="URL" name="codeRepository" id="codeRepository"
placeholder="git+https://github.com/You/RepoName.git" />
</p>
<p title="Link to continuous integration service (Travis-CI, Gitlab CI, etc.).">
<label for="contIntegration">Continuous integration</label>
<input type="URL" name="contIntegration" id="contIntegration"
placeholder="https://travis-ci.org/You/RepoName" />
</p>
<p title="Link to a place for users/developpers to report and manage bugs (JIRA, GitHub issues, etc.).">
<label for="issueTracker">Issue tracker</label>
<input type="URL" name="issueTracker" id="issueTracker"
placeholder="https://github.com/You/RepoName/issues" />
</p>
<p title="Related document, software, tools">
<label for="relatedLink">Related links</label>
<br />
<textarea rows="4" cols="50"
name="relatedLink" id="relatedLink"></textarea>
</fieldset>
<fieldset id="fieldsetRuntime" class="leafFieldset">
<legend>Run-time environment</legend>
<p title="Programming Languages, separated by commas">
<label for="programmingLanguage">Programming Language</label>
<input type="text" name="programmingLanguage" id="programmingLanguage"
placeholder="C#, Java, Python 3" />
</p>
<p title="Runtime Platforms, separated by commas">
<label for="runtimePlatform">Runtime Platform</label>
<input type="text" name="runtimePlatform" id="runtimePlatform"
placeholder=".NET, JVM" />
</p>
<p title="Operating Systems, separated by commas">
<label for="operatingSystem">Operating System</label>
<input type="text" name="operatingSystem" id="operatingSystem"
placeholder="Android 1.6, Linux, Windows, macOS" />
</p>
<p title="Required software to run/use this one.">
<label for="softwareRequirements">Other software requirements</label>
<br />
<textarea rows="4" cols="50"
name="softwareRequirements" id="softwareRequirements"
placeholder=
"Python 3.4
https://github.com/psf/requests"></textarea>
</fieldset>
<fieldset id="fieldsetCurrentVersion" class="leafFieldset">
<legend>Current version of the software</legend>
<p title="Version number of the software">
<label for="version">Version number</label>
<input type="text" name="version" id="version"
placeholder="1.0.0" />
</p>
<p title="The date on which the software was most recently modified.">
<label for="dateModified">Release date</label>
<input type="text" name="dateModified" id="dateModified"
placeholder="YYYY-MM-DD" pattern="\d{4}-\d{2}-\d{2}" />
</p>
<p title="Download link">
<label for="downloadUrl">Download URL</label>
<input type="URL" name="downloadUrl" id="downloadUrl"
placeholder="https://example.org/MySoftware.tar.gz" />
</p>
<p title="a brief description of the software">
<label for="releaseNotes">Release notes</label>
<br />
<textarea rows="4" cols="50"
name="releaseNotes" id="releaseNotes"
placeholder=
"Change log: this and that;
Bugfixes: that and this." ></textarea>
</p>
<!--TODO: referencePublication as ScholarlyArticle array -->
</fieldset>
<fieldset id="fieldsetAdditionalInfo" class="leafFieldset">
<legend>Additional Info</legend>
<p title="Scholarly article describing this software">
<label for="referencePublication">Reference Publication</label>
<input type="URL" name="referencePublication" id="referencePublication"
placeholder="https://doi.org/10.1000/xyz123" />
</p>
<p title="Development Status">
<label for="developmentStatus">Development Status</label>
<datalist id="developmentStatuses">
<option value="concept">
<option value="wip">
<option value="suspended">
<option value="abandoned">
<option value="active">
<option value="inactive">
<option value="unsupported">
<option value="moved">
</datalist>
<input list="developmentStatuses" id="developmentStatus" aria-describedby="developmentStatuses_descr"
pattern="concept|wip|suspended|abandoned|active|inactive|unsupported|moved">
<br />
<span class="field-description" id="developmentStatuses_descr">
see <a href="http://www.repostatus.org">www.repostatus.org</a> for details
</span>
</p>
<p title="Part of">
<label for="isPartOf">Is part of</label>
<input type="URL" name="isPartOf" id="isPartOf"
placeholder="http://The.Bigger.Framework.org" />
</p>
</fieldset>
<div class="dynamicFields">
<fieldset class="persons" id="author_container">
<legend>Authors</legend>
- <p>Order of authors does not matter.</p>
-
<input type="hidden" id="author_nb" value="0" />
<div id="addRemoveAuthor">
<input type="button" id="author_add" value="Add one"
onclick="addPerson('author', 'Author');" />
<input type="button" id="author_remove" value="Remove last"
onclick="removePerson('author');" />
</div>
</fieldset>
<fieldset class="persons" id="contributor_container">
<legend>Contributors</legend>
<p>Order of contributors does not matter.</p>
<input type="hidden" id="contributor_nb" value="0" />
<div id="addRemoveContributor">
<input type="button" id="contributor_add" value="Add one"
onclick="addPerson('contributor', 'Contributor');" />
<input type="button" id="contributor_remove" value="Remove last"
onclick="removePerson('contributor');" />
</div>
</fieldset>
</div>
</form>
<form>
<input type="button" id="generateCodemeta" value="Generate codemeta.json"
title="Creates a codemeta.json file below, from the information provided above." />
<input type="button" id="resetForm" value="Reset form"
title="Erases all fields." />
<input type="button" id="validateCodemeta" value="Validate codemeta.json"
title="Checks the codemeta.json file below is valid, and displays errors." />
<input type="button" id="importCodemeta" value="Import codemeta.json"
title="Fills the fields above based on the codemeta.json file below." />
</form>
<p id="errorMessage">
</p>
<p>codemeta.json:</p>
<pre contentEditable="true" id="codemetaText"></pre>
</main>
<footer>
<p style="text-align:center;">
Do you want to improve this tool ?
Check out the
<a href="https://github.com/codemeta/codemeta-generator">
CodeMeta-generator repository</a>
<br />
Join the
<a href="https://github.com/codemeta/codemeta">CodeMeta community</a>
discussion
<br />
The CodeMeta vocabulary -
<a href="https://doi.org/10.5063/schema/codemeta-2.0">v2.0</a>
</p>
<h2 style="text-align:right;">Contributed by</h2>
<p style="text-align:right;">
<a href="https://www.softwareheritage.org/save-and-reference-research-software/">
<img alt="Software Heritage" src="https://annex.softwareheritage.org/public/logo/software-heritage-logo-title-motto.svg"
width="300">
</a>
</p>
</footer>
<script>
initFieldsData();
initCallbacks();
loadStateFromStorage();
</script>
</body>
</html>
diff --git a/js/dynamic_form.js b/js/dynamic_form.js
index 8fef145..15b2785 100644
--- a/js/dynamic_form.js
+++ b/js/dynamic_form.js
@@ -1,131 +1,186 @@
/**
* Copyright (C) 2019 The Software Heritage developers
* See the AUTHORS file at the top-level directory of this distribution
* License: GNU Affero General Public License version 3, or any later version
* See top-level LICENSE file for more information
*/
"use strict";
+// List of all HTML fields in a Person fieldset.
+const personFields = [
+ 'givenName',
+ 'familyName',
+ 'email',
+ 'id',
+ 'affiliation',
+];
+
function createPersonFieldset(personPrefix, legend) {
// Creates a fieldset containing inputs for informations about a person
var fieldset = document.createElement("fieldset")
+ var moveButtons;
fieldset.classList.add("person");
fieldset.classList.add("leafFieldset");
fieldset.id = personPrefix;
fieldset.innerHTML = `
<legend>${legend}</legend>
+ <div class="moveButtons">
+ <input type="button" id="${personPrefix}_moveToLeft" value="<" class="moveToLeft"
+ title="Moves this person to the left." />
+ <input type="button" id="${personPrefix}_moveToRight" value=">" class="moveToRight"
+ title="Moves this person to the right." />
+ </div>
<p>
<label for="${personPrefix}_givenName">Given name</label>
<input type="text" id="${personPrefix}_givenName" name="${personPrefix}_givenName"
placeholder="Jane" required="true" />
</p>
<p>
<label for="${personPrefix}_familyName">Family name</label>
<input type="text" id="${personPrefix}_familyName" name="${personPrefix}_familyName"
placeholder="Doe" />
</p>
<p>
<label for="${personPrefix}_email">E-mail address</label>
<input type="email" id="${personPrefix}_email" name="${personPrefix}_email"
placeholder="jane.doe@example.org" />
</p>
<p>
<label for="${personPrefix}_id">URI</label>
<input type="url" id="${personPrefix}_id" name="${personPrefix}_id"
placeholder="http://orcid.org/0000-0002-1825-0097" />
</p>
<p>
<label for="${personPrefix}_affiliation">Affiliation</label>
<input type="text" id="${personPrefix}_affiliation" name="${personPrefix}_affiliation"
placeholder="Department of Computer Science, University of Pisa" />
</p>
`;
return fieldset;
}
function addPersonWithId(container, prefix, legend, id) {
- var fieldset = createPersonFieldset(`${prefix}_${id}`, `${legend} #${id}`);
+ var personPrefix = `${prefix}_${id}`;
+ var fieldset = createPersonFieldset(personPrefix, `${legend} #${id}`);
container.appendChild(fieldset);
+
+ document.querySelector(`#${personPrefix}_moveToLeft`)
+ .addEventListener('click', () => movePerson(prefix, id, "left"));
+ document.querySelector(`#${personPrefix}_moveToRight`)
+ .addEventListener('click', () => movePerson(prefix, id, "right"));
+}
+
+function movePerson(prefix, id1, direction) {
+ var nbPersons = getNbPersons(prefix);
+ var id2;
+
+ // Computer id2, the id of the person to flip id1 with (wraps around the
+ // end of the list of persons)
+ if (direction == "left") {
+ id2 = id1 - 1;
+ if (id2 <= 0) {
+ id2 = nbPersons;
+ }
+ }
+ else {
+ id2 = id1 + 1;
+ if (id2 > nbPersons) {
+ id2 = 1;
+ }
+ }
+
+ // Flip the field values, one by one
+ personFields.forEach((fieldName) => {
+ var field1 = document.querySelector(`#${prefix}_${id1}_${fieldName}`);
+ var field2 = document.querySelector(`#${prefix}_${id2}_${fieldName}`);
+ var value1 = field1.value;
+ var value2 = field2.value;
+ field2.value = value1;
+ field1.value = value2;
+ });
+
+ // Form was changed; regenerate
+ generateCodemeta();
}
function addPerson(prefix, legend) {
var container = document.querySelector(`#${prefix}_container`);
var personId = getNbPersons(prefix) + 1;
addPersonWithId(container, prefix, legend, personId);
setNbPersons(prefix, personId);
return personId;
}
function removePerson(prefix) {
var personId = getNbPersons(prefix);
document.querySelector(`#${prefix}_${personId}`).remove();
setNbPersons(prefix, personId-1);
}
// Initialize a group of persons (authors, contributors) on page load.
// Useful if the page is reloaded.
function initPersons(prefix, legend) {
var nbPersons = getNbPersons(prefix);
var personContainer = document.querySelector(`#${prefix}_container`)
for (let personId = 1; personId <= nbPersons; personId++) {
addPersonWithId(personContainer, prefix, legend, personId);
}
}
function removePersons(prefix) {
var nbPersons = getNbPersons(prefix);
var personContainer = document.querySelector(`#${prefix}_container`)
for (let personId = 1; personId <= nbPersons; personId++) {
removePerson(prefix)
}
}
function resetForm() {
removePersons('author');
removePersons('contributor');
// Reset the form after deleting elements, so nbPersons doesn't get
// reset before it's read.
document.querySelector('#inputForm').reset();
}
function fieldToLower(event) {
event.target.value = event.target.value.toLowerCase();
}
function initCallbacks() {
document.querySelector('#license')
.addEventListener('change', validateLicense);
document.querySelector('#generateCodemeta')
.addEventListener('click', generateCodemeta);
document.querySelector('#resetForm')
.addEventListener('click', resetForm);
document.querySelector('#validateCodemeta')
.addEventListener('click', () => parseAndValidateCodemeta(true));
document.querySelector('#importCodemeta')
.addEventListener('click', importCodemeta);
document.querySelector('#inputForm')
.addEventListener('change', generateCodemeta);
document.querySelector('#developmentStatus')
.addEventListener('change', fieldToLower);
initPersons('author', 'Author');
initPersons('contributor', 'Contributor');
}
diff --git a/main.css b/main.css
index 3cdd50f..dfa7c62 100644
--- a/main.css
+++ b/main.css
@@ -1,72 +1,78 @@
/**
* Copyright (C) 2019 The Software Heritage developers
* See the AUTHORS file at the top-level directory of this distribution
* License: GNU Affero General Public License version 3, or any later version
* See top-level LICENSE file for more information
*/
/* This file contains the main CSS to make the form/application usable,
* without being especially pretty.
*/
#noscriptError {
color: red;
}
.person {
display: inline-block;
}
#inputForm {
max-width: 100%;
display: flex;
flex-wrap: wrap;
}
/* A fieldset that contains only label/input pairs */
.leafFieldset {
flex: auto;
}
p input, p textarea {
width: 100%;
box-sizing: border-box;
}
.dynamicFields {
width: 100%;
}
+.dynamicFields .moveButtons {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+}
+
#license {
/* License names are long */
min-width: 20em;
}
#funding {
/* Funding names are long */
min-width: 20em;
}
input[type=URL] {
/* URLs are longer than the other fields */
min-width: 20em;
}
.field-description {
color : rgb(100, 104, 103);
font-size: small;
}
#codemetaText {
width: 100%;
min-height: 10em;
border: 1px solid black;
}
#errorMessage {
color: red;
}
input:invalid {
color: red;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Jul 4, 3:29 PM (1 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3252891
Attached To
rDWCM CodeMeta Generator (mirror)
Event Timeline
Log In to Comment