Commit 8a61183a authored by Laurent Wouters's avatar Laurent Wouters
Browse files

Added a view for books

parent 66d7268f7a90
......@@ -238,7 +238,11 @@ export class RdfEntityStore {
* @param store The underlying store
* @param aliases The series of known aliases
*/
constructor(store: $rdf.Formula, aliases?: string[][]) {
constructor(
store: $rdf.Formula,
aliases?: string[][],
inverses?: { [uri: string]: string }
) {
this.store = store;
this.nodes = {};
this.entities = {};
......@@ -252,6 +256,11 @@ export class RdfEntityStore {
}
}
}
if (inverses != null && inverses != undefined) {
Object.keys(inverses).forEach((uri: string) => {
this.inverses[uri] = inverses[uri];
});
}
}
/**
......
<template>
<div>
<h1>{{book.title}}</h1>
<table class="table table-bordered table-hover">
<tbody>
<tr>
<td><b>Authors</b></td>
<td>
<div v-for="uri in book.authors" v-bind:key="uri" class="card">
<div className="card-body">
<span>Author: </span>
<a v-on:click="(event) => {event.preventDefault(); context.event.onRequestNavigateTo(uri);}" :href=uri>{{uri}}</a>
</div>
</div>
</td>
</tr>
<tr>
<td><b>Publisher</b></td>
<td>{{book.publisher}}</td>
</tr>
<tr>
<td><b>Release date</b></td>
<td>{{book.releaseDate}}</td>
</tr>
<tr>
<td><b>Abstract</b></td>
<td>{{book.abstract}}</td>
</tr>
<tr>
<td><b>Comment</b></td>
<td>{{book.comment}}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
props: ["context", "book"]
};
</script>
<style>
.view-header {
width: 75%;
margin-left: 12.5%;
margin-top: 2vh;
margin-bottom: 2vh;
}
</style>
\ No newline at end of file
/*******************************************************************************
* Copyright 2003-2018 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
* contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
*
* This file is part of CubicWeb.
*
* CubicWeb is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 2.1 of the License, or (at your option)
* any later version.
*
* CubicWeb is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import { RdfEntity } from "@logilab/librdf";
import { application, definition, implementation } from "@logilab/libview";
import * as $rdf from "rdflib";
import Vue from "vue";
/// <reference path="../common/vue.d.ts" />
import BookImpl from "./BookImpl.vue";
import {
MetaClass,
MetaProperty,
getMainEntity,
loadEntity
} from "../common/utils";
/**
* The descritptor for the default book view
*/
const DESCRIPTOR_BOOK: definition.ViewDescriptor = {
identifier: "::Logilab::Book",
name: "Logilab: Book View",
description: "Renders a book from a dataset",
entrypoint: "VIEW_BOOK_ENTRYPOINT",
resourceCss: [
{
location: "remote",
uri:
"https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
} as definition.ViewResourceRemote
],
resourceJs: [],
resourceMain: {
location: "remote",
uri: "http://localhost:8080/view_book.js"
} as definition.ViewResourceRemote
};
/**
* The data for a book
*/
interface Book {
authors: string;
title: string;
abstract: string;
comment: string;
publisher: string;
releaseDate: string;
}
/**
* The metaclass for Book
*/
const BOOK_METACLASS = new MetaClass<Book>([
new MetaProperty("authors", "http://purl.org/dc/terms/creator", true, true),
new MetaProperty("title", "http://www.w3.org/2000/01/rdf-schema#label"),
new MetaProperty("abstract", "http://dbpedia.org/ontology/abstract"),
new MetaProperty("comment", "http://www.w3.org/2000/01/rdf-schema#comment"),
new MetaProperty("publisher", "http://purl.org/dc/elements/1.1/publisher"),
new MetaProperty("releaseDate", "http://dbpedia.org/property/releaseDate")
]);
class BookRendering implements implementation.ViewImplementation {
descriptor: definition.ViewDescriptor;
constructor() {
this.descriptor = DESCRIPTOR_BOOK;
this.priorityFor = this.priorityFor.bind(this);
this.render = this.render.bind(this);
}
priorityFor(store: $rdf.Formula, target: string): number {
if (target == null) return -1;
let entityTarget = getMainEntity(store, target);
let entityTypes = entityTarget.getEntitiesForS(
"http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
);
if (entityTypes.length > 0) {
let x = entityTypes.find(
(entity: RdfEntity) =>
entity.uris.indexOf("http://purl.org/ontology/bibo/Book") >= 0
);
if (x != null && x != undefined)
// The entity is a Book
return 10;
}
return implementation.VIEW_PRIORITY_INAPPROPRIATE;
}
render(
renderer: application.ViewRenderer,
context: application.RenderingContext,
target: string
): HTMLElement {
let book = loadEntity(renderer, context, target, BOOK_METACLASS);
let result = document.createElement("div");
let vm = new Vue({
data: {
descriptor: this.descriptor,
book: book
},
components: { BookImpl },
render: function(createElement) {
return createElement(
"BookImpl",
{
props: {
context: context,
book: book
}
},
[]
);
}
});
vm.$mount(result);
vm.$forceUpdate();
return vm.$el;
}
}
/**
* Export the view
*/
export const VIEW_BOOK_ENTRYPOINT: BookRendering = new BookRendering();
/*******************************************************************************
* Copyright 2003-2018 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
* contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
*
* This file is part of CubicWeb.
*
* CubicWeb is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 2.1 of the License, or (at your option)
* any later version.
*
* CubicWeb is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import { RdfEntity, RdfEntityStore } from "@logilab/librdf";
import { application } from "@logilab/libview";
import * as $rdf from "rdflib";
/**
* Gets the literal value for a property
* @param entity The RDF entity
* @param property The property
* @param language The required language
*/
export function getLiteralValue(
entity: RdfEntity,
property: string,
languages: application.Language[]
): string {
let literals = entity.getValuesForS(property);
if (literals.length == 0) return null;
for (var l = 0; l != languages.length; l++) {
for (var i = 0; i != literals.length; i++) {
if (literals[i].termType != $rdf.Literal.termType) continue;
let lit = literals[i] as $rdf.Literal;
if (
lit.lang == languages[l].iso639_1 ||
lit.lang == languages[l].iso639_2
)
return literals[i].value;
}
}
return literals[0].value;
}
/**
* Get the URIs of related entities
* @param entity The RDF entity
* @param property The property
*/
export function getRelatedEntities(
entity: RdfEntity,
property: string
): string[] {
return entity
.getEntitiesForS(property)
.map((e: RdfEntity) => e.uris)
.reduce((acc: string[], uris: string[]) => acc.concat(uris), []);
}
/**
* Represents some ontological knowledge about a domain
*/
export interface Ontology {
/**
* The known aliases
*/
aliases: string[][];
/**
* The known inverse relations
*/
inverses: { [uri: string]: string };
}
/**
* Represents the data about a property
*/
export class MetaProperty {
/**
* The property's name
*/
public readonly name: string;
/**
* Whether the property is an object
*/
public readonly isObject: boolean;
/**
* Whether the property is a vector property
*/
public readonly isVector: boolean;
/**
* The associated property's URI
*/
public readonly uri: string;
/**
* Initialies this property
* @param name The property's name
* @param uri The associated property's URI
* @param isObject Whether the property is an object
* @param isVector Whether the property is a vector property
*/
constructor(
name: string,
uri: string,
isObject: boolean = false,
isVector: boolean = false
) {
this.name = name;
this.uri = uri;
this.isObject = isObject;
this.isVector = isVector;
}
}
/**
* A metaclass that can be loaded from a dataset
*/
export class MetaClass<T> {
/**
* The class's meta properties
*/
public readonly properties: MetaProperty[];
/**
* Initializes this class
* @param properties The properties
*/
constructor(properties: MetaProperty[]) {
this.properties = properties;
}
/**
* Loads an instance of this metaclass from the specified entity
* @param entity An entity
* @param languages The selected languages
*/
public loadFrom(entity: RdfEntity, languages: application.Language[]): T {
let result: any = {};
this.properties.forEach((property: MetaProperty) => {
if (property.isObject) {
if (property.isVector) {
result[property.name] = getRelatedEntities(entity, property.uri);
} else {
let values = getRelatedEntities(entity, property.uri);
result[property.name] = values.length == 0 ? null : values[0];
}
} else {
result[property.name] = getLiteralValue(
entity,
property.uri,
languages
);
}
});
return result as T;
}
}
/**
* The main ontology for the views
*/
export const ONTOLOGY: Ontology = {
aliases: [
[
"http://xmlns.com/foaf/0.1/Person",
"http://dbpedia.org/ontology/Person",
"http://purl.org/dc/terms/Agent"
],
["http://xmlns.com/foaf/0.1/title"],
["http://xmlns.com/foaf/0.1/gender"],
["http://xmlns.com/foaf/0.1/nick"],
[
"http://xmlns.com/foaf/0.1/name",
"http://www.w3.org/2000/01/rdf-schema#label"
],
[
"http://xmlns.com/foaf/0.1/firstName",
"http://xmlns.com/foaf/0.1/givenName",
"http://xmlns.com/foaf/0.1/givenName"
],
[
"http://xmlns.com/foaf/0.1/lastName",
"http://xmlns.com/foaf/0.1/familyName"
],
["http://xmlns.com/foaf/0.1/phone"],
[
"http://xmlns.com/foaf/0.1/homepage",
"http://dbpedia.org/ontology/wikiPageExternalLink",
" http://xmlns.com/foaf/0.1/isPrimaryTopicOf"
],
["http://xmlns.com/foaf/0.1/weblog"],
["http://xmlns.com/foaf/0.1/openid"],
[
"http://xmlns.com/foaf/0.1/made",
"http://dbpedia.org/ontology/soundRecording"
],
["http://xmlns.com/foaf/0.1/maker"],
["http://xmlns.com/foaf/0.1/img", "http://xmlns.com/foaf/0.1/depiction"],
[
"http://xmlns.com/foaf/0.1/thumbnail",
"http://dbpedia.org/ontology/thumbnail"
],
["http://xmlns.com/foaf/0.1/knows"],
["http://xmlns.com/foaf/0.1/interest"],
["http://xmlns.com/foaf/0.1/topic_interest"],
["http://xmlns.com/foaf/0.1/publications"],
["http://xmlns.com/foaf/0.1/currentProject"],
["http://xmlns.com/foaf/0.1/birthday"],
["http://xmlns.com/foaf/0.1/age"],
["http://xmlns.com/foaf/0.1/status"],
[
"http://rdvocab.info/ElementsGr2/biographicalInformation",
"http://www.w3.org/2000/01/rdf-schema#comment",
"http://purl.org/dc/terms/abstract",
"http://purl.org/dc/terms/description",
"http://dbpedia.org/ontology/abstract"
],
["http://dbpedia.org/ontology/birthDate", "http://vocab.org/bio/0.1/birth"],
["http://dbpedia.org/ontology/birthPlace"],
["http://dbpedia.org/ontology/deathDate", "http://vocab.org/bio/0.1/death"],
["http://dbpedia.org/ontology/deathPlace"],
["http://dbpedia.org/ontology/influenced"],
["http://dbpedia.org/ontology/influencedBy"],
[
"http://dbpedia.org/ontology/notableWork",
"http://data.bnf.fr/vocabulary/roles/r70",
"http://id.loc.gov/vocabulary/relators/aut",
"http://purl.org/dc/terms/contributor"
],
[
"http://purl.org/dc/terms/creator",
"http://purl.org/dc/terms/contributor",
"http://dbpedia.org/ontology/author",
"http://dbpedia.org/ontology/writer",
"http://id.loc.gov/vocabulary/relators/aut"
],
[
"http://purl.org/ontology/bibo/Book",
"http://schema.org/Book",
"http://umbel.org/umbel/rc/Book_CW",
"http://dbpedia.org/ontology/Book",
"http://dbpedia.org/ontology/WrittenWork"
],
[
"http://www.w3.org/2000/01/rdf-schema#label",
"http://dbpedia.org/property/title",
"http://dbpedia.org/property/name"
],
["http://dbpedia.org/ontology/abstract"],
["http://www.w3.org/2000/01/rdf-schema#comment"],
[
"http://dbpedia.org/ontology/publisher",
"http://purl.org/dc/elements/1.1/publisher"
],
["http://dbpedia.org/property/releaseDate"]
],
inverses: {
"http://dbpedia.org/ontology/influenced":
"http://dbpedia.org/ontology/influencedBy",
"http://dbpedia.org/ontology/notableWork":
"http://purl.org/dc/terms/creator"
}
};
/**
* Get the main entity
* @param store Teh RDF store
* @param target The current RDF entity to be rendered
*/
export function getMainEntity(store: $rdf.Formula, target: string): RdfEntity {
let entityStore = new RdfEntityStore(
store,
ONTOLOGY.aliases,
ONTOLOGY.inverses
);
let entityTarget = entityStore.entityForUri(target);
let entityFocus = entityTarget.getEntityForS(
"http://xmlns.com/foaf/0.1/focus"
);
if (entityFocus != null) entityTarget = entityFocus;
return entityTarget;
}
/**
* Loads the data for the entity of interest
* @param renderer The current renderer
* @param context The current rendering context
* @param target The current RDF entity to be rendered
*/
export function loadEntity<T>(
renderer: application.ViewRenderer,
context: application.RenderingContext,
target: string,
metaClass: MetaClass<T>
): T {
let entityTarget = getMainEntity(context.store, target);
let languages = renderer.getLanguagesFor(context, target);
return metaClass.loadFrom(entityTarget, languages);
}
......@@ -7,8 +7,7 @@
"resourceCss": [
{
"location": "remote",
"uri":
"https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
"uri": "https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
}
],
"resourceJs": [],
......@@ -16,5 +15,22 @@
"location": "remote",
"uri": "http://localhost:8080/view_person.js"
}
},
{
"identifier": "::Logilab::Book",
"name": "Logilab: Book View",
"description": "Renders a book from a dataset",
"entrypoint": "VIEW_BOOK_ENTRYPOINT",
"resourceCss": [
{
"location": "remote",
"uri": "https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
}
],
"resourceJs": [],
"resourceMain": {
"location": "remote",
"uri": "http://localhost:8080/view_book.js"
}
}
]
......@@ -18,12 +18,18 @@
* with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import { RdfEntity, RdfEntityStore } from "@logilab/librdf";
import { RdfEntity } from "@logilab/librdf";
import { application, definition, implementation } from "@logilab/libview";
import * as $rdf from "rdflib";
import Vue from "vue";
/// <reference path="../common/vue.d.ts" />
import PersonImpl from "./PersonImpl.vue";
import {
MetaClass,
MetaProperty,
getMainEntity,
loadEntity
} from "../common/utils";
/**
* The descritptor for the default Dbpedia person view
......@@ -47,78 +53,6 @@ const DESCRIPTOR_PERSON: definition.ViewDescriptor = {
} as definition.ViewResourceRemote
};
/**
* The known aliases
*/
const ALIAS = [
[
"http://xmlns.com/foaf/0.1/Person",
"http://dbpedia.org/ontology/Person",
"http://purl.org/dc/terms/Agent"
],
["http://xmlns.com/foaf/0.1/title"],
["http://xmlns.com/foaf/0.1/gender"],
["http://xmlns.com/foaf/0.1/nick"],
[
"http://xmlns.com/foaf/0.1/name",
"http://www.w3.org/2000/01/rdf-schema#label"
],
[
"http://xmlns.com/foaf/0.1/firstName",
"http://xmlns.com/foaf/0.1/givenName",
"http://xmlns.com/foaf/0.1/givenName"
],
[
"http://xmlns.com/foaf/0.1/lastName",
"http://xmlns.com/foaf/0.1/familyName"
],
["http://xmlns.com/foaf/0.1/phone"],
[
"http://xmlns.com/foaf/0.1/homepage",
"http://dbpedia.org/ontology/wikiPageExternalLink",
" http://xmlns.com/foaf/0.1/isPrimaryTopicOf"
],
["http://xmlns.com/foaf/0.1/weblog"],