Skip to content
Snippets Groups Projects
Commit 5694b42b authored by Martin Weise's avatar Martin Weise
Browse files

Resolve "Provide schema.org metadata for google SEO"

parent e2eb7dc6
No related branches found
No related tags found
4 merge requests!231CI: Remove build for log-service,!228Better error message handling in the frontend,!225Resolve "Provide schema.org metadata for google SEO",!223Release of version 1.4.0
......@@ -33,7 +33,7 @@ public class MariaDbContainerConfig {
public static synchronized CustomMariaDBContainer getInstance() {
if (instance == null) {
instance = new CustomMariaDBContainer("mariadb:11.2.2-debian-11-r0");
instance = new CustomMariaDBContainer("mariadb:11.2.2");
instance.withImagePullPolicy(PullPolicy.alwaysPull());
instance.addFixedExposedPort(BaseTest.CONTAINER_1_PORT, BaseTest.IMAGE_1_PORT);
instance.withUsername(BaseTest.CONTAINER_1_PRIVILEGED_USERNAME);
......
......@@ -34,7 +34,7 @@ public class MariaDbContainerConfig {
public static synchronized CustomMariaDBContainer getInstance() {
if (instance == null) {
instance = new CustomMariaDBContainer("mariadb:11.2.2-debian-11-r0");
instance = new CustomMariaDBContainer("mariadb:11.2.2");
instance.withImagePullPolicy(PullPolicy.alwaysPull());
instance.addFixedExposedPort(BaseTest.CONTAINER_1_PORT, BaseTest.IMAGE_1_PORT);
instance.withUsername(BaseTest.CONTAINER_1_PRIVILEGED_USERNAME);
......
import UserMapper from '@/api/user.mapper'
const baseUrl = `${location.protocol}//${location.host}`
class DatabaseMapper {
databaseToOwner (database) {
......@@ -14,6 +15,31 @@ class DatabaseMapper {
}
return UserMapper.userToFullName(database.contact)
}
databaseToJsonLd (database) {
const jsonLd = {
'@context': 'https://schema.org/',
'@type': 'Dataset',
name: database.name,
description: 'Relational database hosted by the database repository.',
url: `${baseUrl}/database/${database.id}/info`,
isAccessibleForFree: database.is_public,
creator: {
'@type': 'Person'
}
}
jsonLd.creator.name = database.owner.name ? database.owner.name : database.owner.username
if (database.owner.given_name) {
jsonLd.creator.givenName = database.owner.given_name
}
if (database.owner.family_name) {
jsonLd.creator.familyName = database.owner.family_name
}
if (database.owner.attributes.orcid) {
jsonLd.creator.sameAs = database.owner.attributes.orcid
}
return jsonLd
}
}
export default new DatabaseMapper()
import store from '@/store'
const baseUrl = `${location.protocol}//${location.host}`
class IdentifierMapper {
identifierToCreators (identifier) {
......@@ -102,6 +103,13 @@ class IdentifierMapper {
return null
}
identifierToPreferFirstLicenseUri (identifier) {
if (!identifier || !identifier.licenses || identifier.licenses.length === 0) {
return null
}
return identifier.licenses[0].uri
}
identifierPreferEnglishDescription (identifier) {
if (!identifier || !identifier.descriptions || identifier.descriptions.length === 0) {
return null
......@@ -148,7 +156,7 @@ class IdentifierMapper {
}
return `${store().state.doiUrl}/${identifier.doi}`
}
return `/pid/${identifier.id}`
return `${baseUrl}/pid/${identifier.id}`
}
identifierToDisplayName (identifier) {
......@@ -161,7 +169,7 @@ class IdentifierMapper {
}
return identifier.doi
}
return `/pid/${identifier.id}`
return `${baseUrl}/pid/${identifier.id}`
}
identifierToDisplayAcronym (identifier) {
......@@ -170,6 +178,71 @@ class IdentifierMapper {
}
return identifier.doi !== null ? 'DOI' : 'URI'
}
creatorToCreatorJsonLd (creator) {
const jsonLd = {
name: creator.creator_name
}
if (creator.name_type === 'Personal') {
jsonLd['@type'] = 'Person'
if (creator.name_identifier) {
jsonLd.sameAs = creator.name_identifier
}
if (creator.firstname) {
jsonLd.givenName = creator.firstname
}
if (creator.lastname) {
jsonLd.familyName = creator.lastname
}
} else {
jsonLd['@type'] = 'Organization'
if (creator.affiliation_identifier) {
jsonLd.sameAs = creator.affiliation_identifier
}
}
return jsonLd
}
identifierToHasPartJsonLd (identifier) {
return {
'@type': 'Dataset',
name: this.identifierPreferEnglishTitle(identifier),
description: this.identifierPreferEnglishDescription(identifier),
identifier: this.identifierToUrl(identifier),
citation: this.identifierToUrl(identifier),
temporalCoverage: identifier.publication_year,
version: identifier.created
}
}
identifiersToJsonLd (database) {
const identifier = database.identifiers[0]
const partIdentifiers = []
if (database.subsets.length > 0) {
database.subsets.forEach((s) => { if (s.identifiers.length > 0) { s.identifiers.forEach(i => partIdentifiers.push(i)) } })
}
if (database.tables.length > 0) {
database.tables.forEach((t) => { if (t.identifiers.length > 0) { t.identifiers.forEach(i => partIdentifiers.push(i)) } })
}
if (database.views.length > 0) {
database.views.forEach((v) => { if (v.identifiers.length > 0) { v.identifiers.forEach(i => partIdentifiers.push(i)) } })
}
return {
'@context': 'https://schema.org/',
'@type': 'Dataset',
name: this.identifierPreferEnglishTitle(identifier),
description: this.identifierPreferEnglishDescription(identifier),
url: `${baseUrl}/database/${identifier.database_id}/info`,
identifier: database.identifiers.map(i => this.identifierToUrl(i)),
license: this.identifierToPreferFirstLicenseUri(identifier),
isAccessibleForFree: database.is_public,
creator: identifier.creators.map(c => this.creatorToCreatorJsonLd(c)),
citation: this.identifierToUrl(identifier),
hasPart: partIdentifiers.map(i => this.identifierToHasPartJsonLd(i)),
temporalCoverage: identifier.publication_year,
version: identifier.created
}
}
}
export default new IdentifierMapper()
......@@ -125,6 +125,7 @@
<nuxt />
</v-container>
</v-main>
<script v-if="hasDataset" type="application/ld+json" v-text="datasetJsonLd" />
</v-app>
</template>
......@@ -133,6 +134,8 @@ import DatabaseService from '@/api/database.service'
import TableService from '@/api/table.service'
import AuthenticationService from '@/api/authentication.service'
import AuthenticationMapper from '@/api/authentication.mapper'
import DatabaseMapper from '@/api/database.mapper'
import IdentifierMapper from '@/api/identifier.mapper'
export default {
data () {
......@@ -182,6 +185,18 @@ export default {
},
logo () {
return this.$config.logo
},
hasDataset () {
return this.$route.path.startsWith('/database')
},
datasetJsonLd () {
if (!this.hasDataset || !this.database) {
return {}
}
if (!('identifiers' in this.database) || this.database.identifiers.length === 0) {
return DatabaseMapper.databaseToJsonLd(this.database)
}
return IdentifierMapper.identifiersToJsonLd(this.database)
}
},
watch: {
......
......@@ -25,9 +25,14 @@
</v-list-item-title>
<v-list-item-content v-if="!loading" v-text="internal_name" />
<v-list-item-title class="mt-2">
Database Creator
Database Owner
</v-list-item-title>
<v-list-item-content v-if="!loading" v-text="creator" />
<v-list-item-content v-if="!loading">
<p class="mb-0">
<OrcidIcon v-if="database.owner.attributes.orcid" :orcid="database.owner.attributes.orcid" />
<span v-text="owner" />
</p>
</v-list-item-content>
<v-list-item-title class="mt-2">
Database Creation
</v-list-item-title>
......@@ -53,7 +58,10 @@
Database Contact
</v-list-item-title>
<v-list-item-content v-if="contact">
<span v-if="!loading" v-text="contact" />
<p class="mb-0">
<OrcidIcon v-if="database.contact.attributes.orcid" :orcid="database.contact.attributes.orcid" />
<span v-text="contact" />
</p>
</v-list-item-content>
</v-list-item-content>
</v-list-item>
......@@ -100,9 +108,11 @@ import { formatTimestampUTCLabel } from '@/utils'
import DatabaseMapper from '@/api/database.mapper'
import Summary from '@/components/identifier/Summary'
import Select from '@/components/identifier/Select'
import OrcidIcon from '@/components/icons/OrcidIcon.vue'
export default {
components: {
OrcidIcon,
DatabaseToolbar,
Summary,
Select
......@@ -190,12 +200,9 @@ export default {
contact () {
return DatabaseMapper.databaseToContact(this.database)
},
creator () {
owner () {
return DatabaseMapper.databaseToOwner(this.database)
},
creatorVerified () {
return this.database.creator.email_verified
},
hasIdentifier () {
return this.identifiers.length > 0
},
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment