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 { ...@@ -33,7 +33,7 @@ public class MariaDbContainerConfig {
public static synchronized CustomMariaDBContainer getInstance() { public static synchronized CustomMariaDBContainer getInstance() {
if (instance == null) { 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.withImagePullPolicy(PullPolicy.alwaysPull());
instance.addFixedExposedPort(BaseTest.CONTAINER_1_PORT, BaseTest.IMAGE_1_PORT); instance.addFixedExposedPort(BaseTest.CONTAINER_1_PORT, BaseTest.IMAGE_1_PORT);
instance.withUsername(BaseTest.CONTAINER_1_PRIVILEGED_USERNAME); instance.withUsername(BaseTest.CONTAINER_1_PRIVILEGED_USERNAME);
......
...@@ -34,7 +34,7 @@ public class MariaDbContainerConfig { ...@@ -34,7 +34,7 @@ public class MariaDbContainerConfig {
public static synchronized CustomMariaDBContainer getInstance() { public static synchronized CustomMariaDBContainer getInstance() {
if (instance == null) { 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.withImagePullPolicy(PullPolicy.alwaysPull());
instance.addFixedExposedPort(BaseTest.CONTAINER_1_PORT, BaseTest.IMAGE_1_PORT); instance.addFixedExposedPort(BaseTest.CONTAINER_1_PORT, BaseTest.IMAGE_1_PORT);
instance.withUsername(BaseTest.CONTAINER_1_PRIVILEGED_USERNAME); instance.withUsername(BaseTest.CONTAINER_1_PRIVILEGED_USERNAME);
......
import UserMapper from '@/api/user.mapper' import UserMapper from '@/api/user.mapper'
const baseUrl = `${location.protocol}//${location.host}`
class DatabaseMapper { class DatabaseMapper {
databaseToOwner (database) { databaseToOwner (database) {
...@@ -14,6 +15,31 @@ class DatabaseMapper { ...@@ -14,6 +15,31 @@ class DatabaseMapper {
} }
return UserMapper.userToFullName(database.contact) 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() export default new DatabaseMapper()
import store from '@/store' import store from '@/store'
const baseUrl = `${location.protocol}//${location.host}`
class IdentifierMapper { class IdentifierMapper {
identifierToCreators (identifier) { identifierToCreators (identifier) {
...@@ -102,6 +103,13 @@ class IdentifierMapper { ...@@ -102,6 +103,13 @@ class IdentifierMapper {
return null return null
} }
identifierToPreferFirstLicenseUri (identifier) {
if (!identifier || !identifier.licenses || identifier.licenses.length === 0) {
return null
}
return identifier.licenses[0].uri
}
identifierPreferEnglishDescription (identifier) { identifierPreferEnglishDescription (identifier) {
if (!identifier || !identifier.descriptions || identifier.descriptions.length === 0) { if (!identifier || !identifier.descriptions || identifier.descriptions.length === 0) {
return null return null
...@@ -148,7 +156,7 @@ class IdentifierMapper { ...@@ -148,7 +156,7 @@ class IdentifierMapper {
} }
return `${store().state.doiUrl}/${identifier.doi}` return `${store().state.doiUrl}/${identifier.doi}`
} }
return `/pid/${identifier.id}` return `${baseUrl}/pid/${identifier.id}`
} }
identifierToDisplayName (identifier) { identifierToDisplayName (identifier) {
...@@ -161,7 +169,7 @@ class IdentifierMapper { ...@@ -161,7 +169,7 @@ class IdentifierMapper {
} }
return identifier.doi return identifier.doi
} }
return `/pid/${identifier.id}` return `${baseUrl}/pid/${identifier.id}`
} }
identifierToDisplayAcronym (identifier) { identifierToDisplayAcronym (identifier) {
...@@ -170,6 +178,71 @@ class IdentifierMapper { ...@@ -170,6 +178,71 @@ class IdentifierMapper {
} }
return identifier.doi !== null ? 'DOI' : 'URI' 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() export default new IdentifierMapper()
...@@ -125,6 +125,7 @@ ...@@ -125,6 +125,7 @@
<nuxt /> <nuxt />
</v-container> </v-container>
</v-main> </v-main>
<script v-if="hasDataset" type="application/ld+json" v-text="datasetJsonLd" />
</v-app> </v-app>
</template> </template>
...@@ -133,6 +134,8 @@ import DatabaseService from '@/api/database.service' ...@@ -133,6 +134,8 @@ import DatabaseService from '@/api/database.service'
import TableService from '@/api/table.service' import TableService from '@/api/table.service'
import AuthenticationService from '@/api/authentication.service' import AuthenticationService from '@/api/authentication.service'
import AuthenticationMapper from '@/api/authentication.mapper' import AuthenticationMapper from '@/api/authentication.mapper'
import DatabaseMapper from '@/api/database.mapper'
import IdentifierMapper from '@/api/identifier.mapper'
export default { export default {
data () { data () {
...@@ -182,6 +185,18 @@ export default { ...@@ -182,6 +185,18 @@ export default {
}, },
logo () { logo () {
return this.$config.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: { watch: {
......
...@@ -25,9 +25,14 @@ ...@@ -25,9 +25,14 @@
</v-list-item-title> </v-list-item-title>
<v-list-item-content v-if="!loading" v-text="internal_name" /> <v-list-item-content v-if="!loading" v-text="internal_name" />
<v-list-item-title class="mt-2"> <v-list-item-title class="mt-2">
Database Creator Database Owner
</v-list-item-title> </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"> <v-list-item-title class="mt-2">
Database Creation Database Creation
</v-list-item-title> </v-list-item-title>
...@@ -53,7 +58,10 @@ ...@@ -53,7 +58,10 @@
Database Contact Database Contact
</v-list-item-title> </v-list-item-title>
<v-list-item-content v-if="contact"> <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-content> </v-list-item-content>
</v-list-item> </v-list-item>
...@@ -100,9 +108,11 @@ import { formatTimestampUTCLabel } from '@/utils' ...@@ -100,9 +108,11 @@ import { formatTimestampUTCLabel } from '@/utils'
import DatabaseMapper from '@/api/database.mapper' import DatabaseMapper from '@/api/database.mapper'
import Summary from '@/components/identifier/Summary' import Summary from '@/components/identifier/Summary'
import Select from '@/components/identifier/Select' import Select from '@/components/identifier/Select'
import OrcidIcon from '@/components/icons/OrcidIcon.vue'
export default { export default {
components: { components: {
OrcidIcon,
DatabaseToolbar, DatabaseToolbar,
Summary, Summary,
Select Select
...@@ -190,12 +200,9 @@ export default { ...@@ -190,12 +200,9 @@ export default {
contact () { contact () {
return DatabaseMapper.databaseToContact(this.database) return DatabaseMapper.databaseToContact(this.database)
}, },
creator () { owner () {
return DatabaseMapper.databaseToOwner(this.database) return DatabaseMapper.databaseToOwner(this.database)
}, },
creatorVerified () {
return this.database.creator.email_verified
},
hasIdentifier () { hasIdentifier () {
return this.identifiers.length > 0 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