Skip to content

Commit

Permalink
Merge pull request #1162 from research-software-directory/1033-licenses
Browse files Browse the repository at this point in the history
Add more info to software licenses
  • Loading branch information
dmijatovic committed Apr 22, 2024
2 parents b9d3753 + d597b8d commit ecb83ac
Show file tree
Hide file tree
Showing 38 changed files with 748 additions and 367 deletions.
20 changes: 11 additions & 9 deletions data-generation/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// SPDX-FileCopyrightText: 2022 - 2023 dv4all
// SPDX-FileCopyrightText: 2022 - 2024 Ewan Cahen (Netherlands eScience Center) <e.cahen@esciencecenter.nl>
// SPDX-FileCopyrightText: 2022 - 2024 Netherlands eScience Center
// SPDX-FileCopyrightText: 2023 Dusan Mijatovic (Netherlands eScience Center)
// SPDX-FileCopyrightText: 2023 - 2024 Dusan Mijatovic (Netherlands eScience Center)
//
// SPDX-License-Identifier: Apache-2.0

Expand Down Expand Up @@ -202,12 +202,12 @@ function generatePackageManagers(softwareIds) {

function generateLincensesForSoftware(ids) {
const licenses = [
'Apache-2.0',
'MIT',
'GPL-2.0-or-later',
'LGPL-2.0-or-later',
'CC-BY-4.0',
'CC-BY-NC-ND-3.0',
{license:'Apache-2.0',name:'Apache License 2.0',reference:'https://spdx.org/licenses/Apache-2.0.html'},
{license:'MIT',name:'MIT License',reference:'https://spdx.org/licenses/MIT.html'},
{license:'GPL-2.0-or-later',name:'GNU General Public License v2.0 or later',reference:'https://spdx.org/licenses/GPL-2.0-or-later.html'},
{license:'LGPL-2.0-or-later',name:'GNU Library General Public License v2 or later',reference:'https://spdx.org/licenses/LGPL-2.0-or-later.html'},
{license:'CC-BY-4.0',name:'Creative Commons Attribution 4.0 International',reference:'https://spdx.org/licenses/CC-BY-4.0.html'},
{license:'CC-BY-NC-ND-3.0',name:'Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported',reference:'https://spdx.org/licenses/CC-BY-NC-ND-3.0.html'}
];

const result = [];
Expand All @@ -217,10 +217,12 @@ function generateLincensesForSoftware(ids) {
if (nummerOfLicenses === 0) continue;

const licensesToAdd = faker.helpers.arrayElements(licenses, nummerOfLicenses);
for (const license of licensesToAdd) {
for (const item of licensesToAdd) {
result.push({
software: id,
license: license,
license: item.license,
name: item.name,
reference: item.reference
});
}
}
Expand Down
3 changes: 3 additions & 0 deletions database/004-create-relations-for-software.sql
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ CREATE TABLE license_for_software (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
software UUID references software (id) NOT NULL,
license VARCHAR(100) NOT NULL,
name VARCHAR(200) NULL,
reference VARCHAR(200) NULL CHECK (reference ~ '^https?://'),
open_source BOOLEAN NOT NULL DEFAULT TRUE,
UNIQUE(software, license),
created_at TIMESTAMPTZ NOT NULL,
updated_at TIMESTAMPTZ NOT NULL
Expand Down
47 changes: 31 additions & 16 deletions frontend/components/software/AboutLicense.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,47 @@
// SPDX-FileCopyrightText: 2022 Dusan Mijatovic (dv4all)
// SPDX-FileCopyrightText: 2022 dv4all
// SPDX-FileCopyrightText: 2024 Dusan Mijatovic (Netherlands eScience Center)
// SPDX-FileCopyrightText: 2024 Netherlands eScience Center
//
// SPDX-License-Identifier: Apache-2.0

import AttachFileIcon from '@mui/icons-material/AttachFile'
import LaunchIcon from '@mui/icons-material/Launch'
import {LicenseForSoftware} from '~/types/SoftwareTypes'

export default function AboutLicense({license}:{license:string[]}) {

function renderLicenses() {
if (license.length === 0) {
return (<i>Not specified</i>)
}
return (
<ul className="py-1">
{license.map((item, pos) => {
return <li key={pos}>{ item }</li>
})}
</ul>
)
}

export default function AboutLicense({licenses}:{licenses:LicenseForSoftware[]}) {
// console.log('AboutLicense...', licenses)
return (
<>
<div className="pt-8 pb-2">
<AttachFileIcon color="primary" sx={{transform:'rotate(45deg)'}} />
<span className="text-primary pl-2">License</span>
</div>
{renderLicenses()}
{licenses.length === 0 ?
<i>Not specified</i>
:
<ul className="py-1">
{licenses.map((item) => {
return (
<li key={item.license} title={item.name ?? item.license}>
{ item.reference ?
<a href={item.reference} target='_blank' className="flex items-center">
{item.license}
<LaunchIcon
sx={{
width:'1rem',
height:'1rem',
marginLeft: '0.5rem'
}}
/>
</a>
: <span>{item.license}</span>
}
</li>
)
})}
</ul>
}
</>
)
}
15 changes: 8 additions & 7 deletions frontend/components/software/AboutSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
// SPDX-FileCopyrightText: 2021 - 2023 dv4all
// SPDX-FileCopyrightText: 2022 - 2023 Helmholtz Centre Potsdam - GFZ German Research Centre for Geosciences
// SPDX-FileCopyrightText: 2022 Christian Meeßen (GFZ) <christian.meessen@gfz-potsdam.de>
// SPDX-FileCopyrightText: 2023 Dusan Mijatovic (Netherlands eScience Center)
// SPDX-FileCopyrightText: 2023 - 2024 Dusan Mijatovic (Netherlands eScience Center)
// SPDX-FileCopyrightText: 2023 - 2024 Netherlands eScience Center
// SPDX-FileCopyrightText: 2023 Felix Mühlbauer (GFZ) <felix.muehlbauer@gfz-potsdam.de>
// SPDX-FileCopyrightText: 2023 Netherlands eScience Center
//
// SPDX-License-Identifier: Apache-2.0

import {
License, ProgramingLanguages,
ProgramingLanguages,
CodePlatform, KeywordForSoftware,
CategoriesForSoftware} from '~/types/SoftwareTypes'
CategoriesForSoftware,
LicenseForSoftware} from '~/types/SoftwareTypes'
import {CategoriesWithHeadlines} from '~/components/category/CategoriesWithHeadlines'
import PageContainer from '~/components/layout/PageContainer'
import {PackageManager} from './edit/package-managers/apiPackageManager'
Expand All @@ -29,7 +30,7 @@ type AboutSectionType = {
description_type: 'link' | 'markdown'
keywords: KeywordForSoftware[]
categories: CategoriesForSoftware
licenses: License[]
licenses: LicenseForSoftware[]
repository: string | null
platform: CodePlatform
languages: ProgramingLanguages
Expand All @@ -46,7 +47,7 @@ export default function AboutSection(props:AboutSectionType) {
if (brand_name==='') return null

// extract only license text
const license = licenses?.map(item => item.license)
// const license = licenses?.map(item => item.license)

function getSoftwareLogo() {
if (image_id !== null) {
Expand All @@ -71,7 +72,7 @@ export default function AboutSection(props:AboutSectionType) {
<CategoriesWithHeadlines categories={categories} />
<SoftwareKeywords keywords={keywords || []} />
<AboutLanguages languages={languages} platform={platform} />
<AboutLicense license={license || []} />
<AboutLicense licenses={licenses || []} />
<AboutSourceCode
repository={repository ?? null}
platform={platform}
Expand Down
5 changes: 3 additions & 2 deletions frontend/components/software/add/addConfig.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// SPDX-FileCopyrightText: 2022 - 2023 Dusan Mijatovic (dv4all)
// SPDX-FileCopyrightText: 2022 - 2023 dv4all
// SPDX-FileCopyrightText: 2022 - 2024 Netherlands eScience Center
// SPDX-FileCopyrightText: 2022 Ewan Cahen (Netherlands eScience Center) <e.cahen@esciencecenter.nl>
// SPDX-FileCopyrightText: 2022 Netherlands eScience Center
// SPDX-FileCopyrightText: 2024 Dusan Mijatovic (Netherlands eScience Center)
//
// SPDX-License-Identifier: Apache-2.0

Expand Down Expand Up @@ -36,7 +37,7 @@ export const addConfig = {
maxLength: {value: 200, message: 'Maximum length is 200'},
pattern: {
value: /^[a-z0-9]+(-[a-z0-9]+)*$/,
message: 'Restricted input violiation. Use letters, numbers and dashes "-" only between other input.'
message: 'Restricted input violation. Use letters, numbers and dashes "-" only between other input.'
}
}
}
Expand Down
98 changes: 0 additions & 98 deletions frontend/components/software/edit/editSoftwareConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,44 +44,6 @@ export const softwareInformation = {
maxLength: {value: 300, message: 'Maximum length is 300'},
}
},
get_started_url: {
label: 'Get Started URL',
help: '',
validation: {
maxLength: {value: 200, message: 'Maximum length is 200'},
pattern: {
value: /^https?:\/\/.+\..+/,
message: 'URL should start with http(s):// and use at least one dot (.)'
}
}
},
repository_url: {
label: 'Repository URL',
help: (repoUrl: string | null) => repoUrl ? verifyGithubUrl(repoUrl) : '',
validation: {
maxLength: {value: 200, message: 'Maximum length is 200'},
pattern: {
value: /^https?:\/\/.+\..+/,
message: 'URL should start with http(s)://, have at least one dot (.) and at least one slash (/).'
}
}
},
repository_platform: {
label: 'Platform',
help: 'To scrape repository information',
options: [
{label: 'GitHub', value: 'github'},
{label: 'GitLab', value: 'gitlab'},
{label: 'Bitbucket', value: 'bitbucket'},
{label: 'Other', value: 'other'},
]
},
repository_disabled_scraping_reason: {
label: 'Reason why scraping is disabled',
validation: {
maxLength: {value: 200, message: 'Maximum length is 200'}
}
},
// field for markdown
description: {
label: (brand_name: string) => `What ${brand_name} can do for you`,
Expand Down Expand Up @@ -115,62 +77,12 @@ export const softwareInformation = {
}
}
},
concept_doi: {
title: 'Software DOI',
subtitle: 'Provide the DOI of your software. This DOI will be used to import metadata about the software.',
label: 'Software DOI',
help: '',
infoLink: '/documentation/users/adding-software/#software-doi',
validation: {
minLength: {value: 7, message: 'Minimum length is 7'},
maxLength: {value: 100, message: 'Maximum length is 100'},
pattern: {
value: /^10(\.\w+)+\/\S+$/,
message: 'Invalid DOI pattern. Maybe you provided a complete URL?'
}
}
},
validateConceptDoi: {
label: 'Validate'
},
pageStatus: {
title: 'Status',
subtitle: 'A published software is visible to others.'
},
is_published: {
label: 'Published',
},
categories: {
title: 'Categories',
subtitle: 'Tell us more about your software.',
},
keywords: {
title: 'Keywords',
subtitle: 'Add keywords to your software, or import them using the Software DOI.',
label: 'Find or add keyword',
help: 'Select from top 30 list or start typing for the suggestions',
validation: {
//custom validation rule, not in used by react-hook-form
minLength: 1,
}
},
importKeywords: {
label: 'Import keywords',
message: (doi: string) => `Import keywords from datacite.org using DOI ${doi}`
},
licenses: {
title: 'Licenses',
subtitle: 'What licenses do apply to your software?',
label: 'Find or add a license',
help: 'Start typing for the suggestions',
validation: {
//custom validation rule, not in used by react-hook-form
minLength: 1,
}
},
importLicenses: {
label: 'Import licenses',
message: (doi: string) => `Import licenses from datacite.org using DOI ${doi}`
}
}

Expand Down Expand Up @@ -407,13 +319,3 @@ export const relatedSoftwareInformation = {
subtitle: (brand_name: string) => `Mention software often used together with ${brand_name}`,
help: 'Select related RSD software'
}

function verifyGithubUrl(repoUrl: string) {
if ((repoUrl.startsWith('https://github.com/') || repoUrl.startsWith('http://github.com/'))
&& !repoUrl.match('^https?://github\\.com/([^\\s/]+)/([^\\s/]+)/?$')) {
return <span className="text-warning">This does not seem to be the root of a single GitHub repository, are you
sure?</span>
}

return ''
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ export default function AutosaveSoftwareMarkdown() {
helperTextCnt: `${description_url?.length || 0}/${config.description_url.validation.maxLength.value}`,
}}
control={control}
rules={config.repository_url.validation}
rules={config.description_url.validation}
onSaveField={saveSoftwareInfo}
/>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import {useController, useFormContext} from 'react-hook-form'
import {useSession} from '~/auth'
import useSnackbar from '~/components/snackbar/useSnackbar'
import EditSectionTitle from '~/components/layout/EditSectionTitle'
import {softwareInformation as config} from '~/components/software/edit/editSoftwareConfig'
import AutosaveSoftwareTextField from '~/components/software/edit/information/AutosaveSoftwareTextField'
import {patchSoftwareTable} from '~/components/software/edit/information/patchSoftwareTable'
import ValidateConceptDoi from './ValidateConceptDoi'
import {config} from './config'

export default function AutosaveConceptDoi() {
const {token} = useSession()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import Select from '@mui/material/Select'
import FormHelperText from '@mui/material/FormHelperText'

import {CodePlatform} from '~/types/SoftwareTypes'
import {softwareInformation as config} from '~/components/software/edit/editSoftwareConfig'
import {config} from './config'

type AutosaveRepositoryPlatformProps = {
value: CodePlatform | null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ import {WithFormContext} from '~/utils/jest/WithFormContext'
import {WithSoftwareContext} from '~/utils/jest/WithSoftwareContext'

import AutosaveRepositoryUrl from './AutosaveRepositoryUrl'
import {softwareInformation as config} from '~/components/software/edit/editSoftwareConfig'
import {config} from './config'

// MOCK patchSoftwareTable

const mockAddToRepositoryTable = jest.fn(props => Promise.resolve('OK'))
jest.mock('~/utils/editSoftware', () => ({
addToRepositoryTable: jest.fn(props=>mockAddToRepositoryTable(props))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import {getBaseUrl} from '~/utils/fetchHelpers'
import {CodePlatform, EditSoftwareItem, RepositoryUrl} from '~/types/SoftwareTypes'
import useSnackbar from '~/components/snackbar/useSnackbar'
import AutosaveControlledTextField, {OnSaveProps} from '~/components/form/AutosaveControlledTextField'
import {softwareInformation as config} from '~/components/software/edit/editSoftwareConfig'
import AutosaveRepositoryPlatform from './AutosaveRepositoryPlatform'
import {config} from './config'

async function suggestPlatform(repositoryUrl: string | null) {
// console.log('repositoryUrl...',repositoryUrl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {CategoryID, CategoryPath, CategoryTree} from '~/types/Category'
import useSnackbar from '~/components/snackbar/useSnackbar'
import EditSectionTitle from '~/components/layout/EditSectionTitle'
import {CategoriesWithHeadlines} from '~/components/category/CategoriesWithHeadlines'
import {softwareInformation as config} from '~/components/software/edit/editSoftwareConfig'
import {config} from './config'

export type SoftwareCategoriesProps = {
softwareId: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ import {EditSoftwareItem, KeywordForSoftware} from '~/types/SoftwareTypes'
import useSnackbar from '~/components/snackbar/useSnackbar'
import EditSectionTitle from '~/components/layout/EditSectionTitle'
import FindKeyword, {Keyword} from '~/components/keyword/FindKeyword'
import {softwareInformation as config} from '~/components/software/edit/editSoftwareConfig'
import {searchForSoftwareKeyword} from './searchForSoftwareKeyword'
import ImportKeywordsFromDoi from './ImportKeywordsFromDoi'
import {config} from './config'

export type SoftwareKeywordsProps={
software_id:string,
Expand Down

0 comments on commit ecb83ac

Please sign in to comment.