Commit 89986f12 authored by Laurent Wouters's avatar Laurent Wouters
Browse files

Implementing the embedded application

parent 0879692c4927
......@@ -23,14 +23,17 @@
*/
declare module "rdflib" {
export interface RdfIriNode {
termType: string;
uri: string;
}
export interface RdfBlankNode {
termType: string;
id: string;
}
export interface RdfLiteralNode {
termType: string;
value: string;
language: string;
datatype: RdfIriNode;
......@@ -42,32 +45,34 @@ declare module "rdflib" {
export interface RdfTriple {
subject: RdfSubjectNode;
property: RdfIriNode;
predicate: RdfIriNode;
object: RdfNode;
why: RdfIriNode;
}
export interface RdfStore {
statements: RdfTriple[];
add(
subject: RdfSubjectNode,
property: RdfIriNode,
predicate: RdfIriNode,
object: RdfNode,
why: RdfIriNode
): void;
any(
subject: RdfSubjectNode,
property: RdfIriNode,
predicate: RdfIriNode,
object: RdfNode,
why: RdfIriNode
): RdfTriple;
each(
subject: RdfSubjectNode,
property: RdfIriNode,
predicate: RdfIriNode,
object: RdfNode,
why: RdfIriNode
): RdfTriple[];
): RdfNode[];
}
export type Namespace = (fragment: string) => RdfIriNode;
......
/*******************************************************************************
* 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 {
ViewImplementation,
ViewDescriptor,
ViewRenderer,
REGISTRY
} from "../framework/registry";
/// <reference path="../../common/rdflib-interface.d.ts"/>
import {
RdfStore,
RdfTriple,
RdfNode,
RdfIriNode,
RdfBlankNode,
RdfLiteralNode
} from "rdflib";
import * as React from "react";
export class NTripleRendering implements ViewImplementation {
constructor() {
this.descriptor = {
identifier: "::Defaults::NTripleRendering",
name: "N-Triples default rendering",
description: "Renders a complete RDF dataset using the N-Triples syntax",
origin: null
};
this.priorityFor = this.priorityFor.bind(this);
this.render = this.render.bind(this);
}
descriptor: ViewDescriptor;
priorityFor(store: RdfStore, target: string): number {
return Number.MIN_SAFE_INTEGER;
}
render(
renderer: ViewRenderer,
store: RdfStore,
root: string,
target: string
): React.ReactNode {
return (
<table className="table-striped table-condensed">
<thead>
<tr>
<td>Subject</td>
<td>Property</td>
<td>Object</td>
</tr>
</thead>
<tbody>
{store.statements.map((triple: RdfTriple) => {
return renderRdfTriple(triple);
})}
</tbody>
</table>
);
}
}
function renderRdfTriple(triple: RdfTriple): React.ReactNode {
return (
<tr>
<td>{renderRdfNode(triple.subject)}</td>
<td>{renderRdfNode(triple.predicate)}</td>
<td>{renderRdfNode(triple.object)}</td>
</tr>
);
}
function renderRdfNode(node: RdfNode): React.ReactNode {
if (node == undefined || node == null) {
return <span>?</span>;
} else if (node.termType == "NamedNode") {
let nodeIRI = node as RdfIriNode;
return <a href={nodeIRI.uri}>{nodeIRI.uri}</a>;
} else if (node.termType == "BlankNode") {
let nodeBlank = node as RdfBlankNode;
return <span>_:{nodeBlank.id}</span>;
} else if (node.termType == "Literal") {
let nodeLiteral = node as RdfLiteralNode;
return <span>\"{nodeLiteral.value}\"</span>;
}
return null;
}
export function register(): void {
REGISTRY.register(new NTripleRendering());
}
......@@ -22,7 +22,10 @@ import * as React from "react";
/// <reference path="../../common/rdflib-interface.d.ts"/>
import { RdfStore } from "rdflib";
import { Application } from "./interface";
import { Application } from "../framework/interface";
import { REGISTRY, ViewRenderer } from "../framework/registry";
import { register } from "./Defaults";
register();
enum StateType {
Loading,
......@@ -92,9 +95,14 @@ export class Viewer extends React.Component<any, State> implements Application {
</div>
);
} else if (this.state.stateType == StateType.Displaying) {
let renderer = new ViewRenderer(this, REGISTRY);
let result = renderer.render(this.state.content, null); // TODO: pass root here
if (result != null) return result;
return (
<div style={{ width: "90%", marginLeft: "5%", marginTop: "10vh" }}>
<div>{this.state.content.toString()}</div>
<div className="alert alert-danger" role="alert">
Rendering failed!
</div>
</div>
);
} else {
......
......@@ -19,7 +19,7 @@
******************************************************************************/
/// <reference path="../../common/rdflib-interface.d.ts"/>
import { Application } from "./interface";
import { Application } from "../framework/interface";
import * as React from "react";
import * as ReactDOM from "react-dom";
......
/*******************************************************************************
* 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/>.
******************************************************************************/
/// <reference path="../../common/rdflib-interface.d.ts"/>
import { RdfStore } from "rdflib";
import { ReactNode } from "react";
import { Application } from "./interface";
/**
* The metadata of a view
*/
export interface ViewDescriptor {
/**
* The unique identifier for this view
*/
identifier: string;
/**
* The human readable name
*/
name: string;
/**
* A longer description for the view
*/
description: string;
/**
* The views's origin, most likely a URL used to fetch its definition
*/
origin: string;
}
/**
* The implementation of a view
*/
export interface ViewImplementation {
/**
* The descriptor (meta-data)
*/
descriptor: ViewDescriptor;
/**
* Gets the view's priority (greater number indicate greater priority)
* @param store The RDF store holding the data to be rendered
* @param target The target resource to be rendered
*/
priorityFor(store: RdfStore, target: string): number;
/**
* Renders a resource belonging to an RDF store
* @param renderer The parent renderer
* @param store The RDF store holding the data to be rendered
* @param root The root resource
* @param target The target resource for this view
*/
render(
renderer: ViewRenderer,
store: RdfStore,
root: string,
target: string
): ReactNode;
}
/**
* A prioritized view implementation
*/
interface PrioritizedViewImplementation {
implementation: ViewImplementation;
priority: number;
}
/**
* A registry of views
*/
export class ViewRegistry {
/**
* Creates an empty registry
*/
constructor() {
this.descriptors = {};
this.implementations = {};
this.resolveViewFor = this.resolveViewFor.bind(this);
}
/**
* The registry of descriptors
*/
descriptors: { [id: string]: ViewDescriptor };
/**
* The registry of implementations
*/
implementations: { [id: string]: ViewImplementation };
/**
* Registers a view implementation
* @param implementation The implementation to register
*/
register(implementation: ViewImplementation): void {
this.descriptors[implementation.descriptor.identifier] =
implementation.descriptor;
this.implementations[implementation.descriptor.identifier] = implementation;
}
/**
* Resoles a view for an RDF datastore and a resource in it
* @param store The RDF store holding the data to be rendered
* @param target The target RDF resource to render
*/
resolveViewFor(store: RdfStore, target: string): ViewImplementation {
let implementations = this.implementations;
let sorted: PrioritizedViewImplementation[] = Object.keys(
this.implementations
).map((id: string) => {
let impl = implementations[id];
return {
implementation: impl,
priority: impl.priorityFor(store, target)
};
});
sorted = sorted.sort(
(x: PrioritizedViewImplementation, y: PrioritizedViewImplementation) => {
return x.priority - y.priority;
}
);
if (sorted.length == 0) return null;
return sorted[sorted.length - 1].implementation;
}
}
/**
* A renderer for an application
*/
export class ViewRenderer {
/**
* Initializes a renderer
* @param application The parent application
* @param registry The registry to use
*/
constructor(application: Application, registry: ViewRegistry) {
this.application = application;
this.registry = registry;
this.render = this.render.bind(this);
}
/**
* The parent application
*/
application: Application;
/**
* The registry to use
*/
registry: ViewRegistry;
/**
* Renders a resource belonging to an RDF store
* @param store The RDF store holding the data to be rendered
* @param root The root resource
* @param target The target resource for this view
*/
render(store: RdfStore, root: string, target: string = root): ReactNode {
let view = this.registry.resolveViewFor(store, target);
if (view == null) return null;
return view.render(this, store, root, target);
}
}
/**
* The global registry of views
*/
export var REGISTRY = new ViewRegistry();
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment