diff --git a/docs/components/canvas.md b/docs/components/canvas.md index e5b17aaa..3155a40a 100644 --- a/docs/components/canvas.md +++ b/docs/components/canvas.md @@ -2,17 +2,49 @@ title: Canvas --- -# Canvas Components +# Canvas and widgets [Canvas](/docs/api/workspace/functions/Canvas) is a main component to display a scrollable canvas for the diagram with [elements](/docs/concepts/graph-model.md), [links](/docs/concepts/graph-model.md) and additional widgets. -## Hooks +## Getting the canvas instance -[useCanvas()](/docs/api/workspace/functions/useCanvas) hook called from a canvas widget, [SharedCanvasState.findAnyCanvas()](/docs/api/workspace/classes/SharedCanvasState.md#findanycanvas) or [SharedCanvasState.findAllCanvases()](/docs/api/workspace/classes/SharedCanvasState.md#findallcanvases) methods can be used to get the [CanvasApi](/docs/api/workspace/interfaces/CanvasApi) instance to read or subscribe to the canvas state or perform viewport-related effects. +[useCanvas()](/docs/api/workspace/functions/useCanvas) hook called from a canvas widget can be used to get the [CanvasApi](/docs/api/workspace/interfaces/CanvasApi) instance from a context to read or subscribe to the canvas state or perform viewport-related effects: + +```ts +function MyWidget() { + const {canvas} = Reactodia.useCanvas(); + // Use canvas here +} +``` + +Alternatively, with [SharedCanvasState.findAnyCanvas()](/docs/api/workspace/classes/SharedCanvasState.md#findanycanvas) or [SharedCanvasState.findAllCanvases()](/docs/api/workspace/classes/SharedCanvasState.md#findallcanvases) methods it is possible to get canvas instance outside the canvas component: + +```ts +function NonWidgetComponent { + const {view} = React.useWorkspace(); + + const canvas = view.findAnyCanvas(); + if (canvas) { + // Use canvas here (could be any if there are several of them) + } + + for (const canvas of view.findAllCanvases()) { + // Use each canvas mounted in the workspace + } +} +``` ## Canvas widgets -To define a custom canvas widget, the target React component should be marked by [defineCanvasWidget()](/docs/api/workspace/functions/defineCanvasWidget) function to define its attachment layer. +Canvas widget is an instance of any React component type which is marked by [defineCanvasWidget()](/docs/api/workspace/functions/defineCanvasWidget) function with metadata such as its attachment layer i.e. where the component should be displayed in relation to other canvas content. + +There are multiple canvas layers to place widgets on, from top one to the bottom: + +| Layer name | [Coordinate type](/docs/concepts/canvas-coordinates.md) | Description | +|----------------|-------------------|-------------| +| `viewport` | client (viewport) | Topmost layer, does not scale or scroll with the diagram. | +| `overElements` | paper | Displayed over both elements and links, scales and scrolls with the diagram. | +| `overLinks` | paper | Displayed under elements but over links, scales and scrolls with the diagram. | ### Example: custom viewport widget @@ -20,13 +52,13 @@ To define a custom canvas widget, the target React component should be marked by function CustomSelectAllWidget() { const {model} = Reactodia.useWorkspace(); return ( -
+ -
+ ); } @@ -40,10 +72,14 @@ function Example() { const {onMount} = Reactodia.useLoadedWorkspace(async ({context, signal}) => { const {model, view, performLayout} = context; - const dataProvider = new Reactodia.EmptyDataProvider(); - await model.createNewDiagram({dataProvider, signal}); model.createElement('http://example.com/entity1'); model.createElement('http://example.com/entity2'); + model.createLinks({ + sourceId: 'http://example.com/entity1', + targetId: 'http://example.com/entity2', + linkTypeId: 'http://example.com/connectedTo', + properties: {}, + }); await performLayout({signal}); }, []); @@ -62,3 +98,16 @@ function Example() { render(); ``` + +## Styles + +The component look can be customized using the following CSS properties (see [design system](/docs/concepts/design-system.mdx) for more information): + +| Property | Description | +|----------|-------------| +| `--reactodia-canvas-background-color` | Background color for the canvas. | +| `--reactodia-canvas-box-shadow` | Box shadow for the UI components layered on top of the canvas. | +| `--reactodia-canvas-overlay-color` | Semi-transparent color to place over canvas content when displaying a modal on top. | +| `--reactodia-canvas-underlay-color` | Semi-transparent color to place under components for improved readability when they are placed on the canvas. | +| `--reactodia-element-background-color` | Default background color for the graph elements displayed on the canvas. | +| `--reactodia-link-stroke-color` | Default stroke color for the graph links displayed on the canvas. | diff --git a/docs/components/class-tree.md b/docs/components/class-tree.md index 92cd1711..28f71cda 100644 --- a/docs/components/class-tree.md +++ b/docs/components/class-tree.md @@ -7,16 +7,12 @@ Element type graph is loaded from [data provider](/docs/concepts/data-provider.m In [graph authoring](/docs/concepts/graph-authoring.md) mode, the class tree can be used to create entity elements that are instances of the displayed types. :::tip - The same functionality is also available as `SearchSectionElementTypes` [unified search section](/docs/components/unified-search.md). - ::: ```tsx live function Example() { - const GRAPH_DATA = - 'https://raw.githubusercontent.com/reactodia/reactodia-workspace/' + - 'master/examples/resources/orgOntology.ttl'; + const GRAPH_DATA = 'https://reactodia.github.io/resources/orgOntology.ttl'; const {defaultLayout} = Reactodia.useWorker(Layouts); @@ -41,3 +37,14 @@ function Example() { ); } ``` + +## Styles + +The component look can be customized using the following CSS properties (see [design system](/docs/concepts/design-system.mdx) for more information): + +| Property | Description | +|----------|-------------| +| `--reactodia-tree-background-color-active` | Background color for a selected tree item. | +| `--reactodia-tree-background-color-focus` | Background color for a hovered over tree item. | +| `--reactodia-tree-border-color-active` | Border color for a selected tree item. | +| `--reactodia-tree-border-color-focus` | Border color for a hovered over tree item. | diff --git a/docs/components/connections-menu.md b/docs/components/connections-menu.md index 407dde6a..1ec2c6d1 100644 --- a/docs/components/connections-menu.md +++ b/docs/components/connections-menu.md @@ -1,3 +1,44 @@ # Connections Menu [ConnectionsMenu](/docs/api/workspace/functions/ConnectionsMenu) component is a [canvas widget](/docs/components/canvas.md) to explore and navigate the graph by adding connected entities to the diagram. + +### Example: opening a connections menu on load + +```tsx live +function Example() { + const GRAPH_DATA = 'https://reactodia.github.io/resources/orgOntology.ttl'; + + const {defaultLayout} = Reactodia.useWorker(Layouts); + + const [connectionsMenuCommands] = React.useState(() => + new Reactodia.EventSource() + ); + + const {onMount} = Reactodia.useLoadedWorkspace(async ({context, signal}) => { + const {model, view, performLayout} = context; + + const response = await fetch(GRAPH_DATA, {signal}); + const graphData = new N3.Parser().parse(await response.text()); + const dataProvider = new Reactodia.RdfDataProvider({acceptBlankNodes: false}); + dataProvider.addGraph(graphData); + await model.importLayout({dataProvider, signal}); + + const target = model.createElement('http://www.w3.org/ns/org#Organization'); + await model.requestElementData([target.iri]); + + connectionsMenuCommands.trigger('show', {targets: [target]}); + }, []); + + return ( +
+ + + +
+ ); +} +``` diff --git a/docs/components/dialog.md b/docs/components/dialog.md index b8f2e5df..c621b4ee 100644 --- a/docs/components/dialog.md +++ b/docs/components/dialog.md @@ -6,6 +6,8 @@ title: Dialog It is possible to show a dialog either attached to target [element](/docs/concepts/graph-model.md), [link](/docs/concepts/graph-model.md) or as a modal over the canvas viewport itself. +## Showing a dialog + The following methods and properties from [OverlayController](/docs/api/workspace/classes/OverlayController) (accessible from [workspace context](/docs/concepts/workspace-context.md)) provide means to interact with the dialogs: | Method or property | Description | @@ -53,3 +55,13 @@ function Example() { ); } ``` + +## Styles + +The component look can be customized using the following CSS properties (see [design system](/docs/concepts/design-system.mdx) for more information): + +| Property | Description | +|----------|-------------| +| `--reactodia-dialog-border-color` | Border color for the dialog (uses the base border color if not set). | +| `--reactodia-dialog-border-radius` | Border radius for the dialog (uses the base border radius if not set). | +| `--reactodia-dialog-border-width` | Border width for the dialog (uses the base border width if not set). | diff --git a/docs/components/drop-on-canvas.md b/docs/components/drop-on-canvas.md index b4a33fd9..df1177f8 100644 --- a/docs/components/drop-on-canvas.md +++ b/docs/components/drop-on-canvas.md @@ -1,3 +1,3 @@ # Drop on Canvas -[DropOnCanvas](/docs/api/workspace/functions/DropOnCanvas) component is a [canvas widget](/docs/components/canvas.md) to allow creating entity elements on the diagram by dragging then dropping a URL (IRI) to the canvas. +[DropOnCanvas](/docs/api/workspace/functions/DropOnCanvas) component is a [canvas widget](/docs/components/canvas.md) to allow creating entity elements on the diagram by dragging then dropping a [URL (IRI)](/docs/concepts/data-provider.md#iri-and-rdf) to the canvas. diff --git a/docs/components/instances-search.md b/docs/components/instances-search.md index 221890e6..0d3ea588 100644 --- a/docs/components/instances-search.md +++ b/docs/components/instances-search.md @@ -3,7 +3,45 @@ [InstancesSearch](/docs/api/workspace/functions/InstancesSearch.md) is a component to search for entities by various filter criteria using [data provider lookup](/docs/concepts/data-provider.md) and add them as elements to the diagram. :::tip - The same functionality is also available as `SearchSectionEntities` [unified search section](/docs/components/unified-search.md). - ::: + +```tsx live +function Example() { + const GRAPH_DATA = 'https://reactodia.github.io/resources/orgOntology.ttl'; + + const {defaultLayout} = Reactodia.useWorker(Layouts); + + const [instancesSearchCommands] = React.useState(() => + new Reactodia.EventSource() + ); + + const {onMount} = Reactodia.useLoadedWorkspace(async ({context, signal}) => { + const {model, performLayout} = context; + + const response = await fetch(GRAPH_DATA, {signal}); + const graphData = new N3.Parser().parse(await response.text()); + const dataProvider = new Reactodia.RdfDataProvider({acceptBlankNodes: false}); + dataProvider.addGraph(graphData); + await model.createNewDiagram({dataProvider, signal}); + + instancesSearchCommands.trigger('setCriteria', { + criteria: { + refElement: 'http://www.w3.org/ns/org#Organization', + refElementLink: 'http://www.w3.org/2000/01/rdf-schema#domain', + } + }); + }, []); + + return ( +
+ + + + + +
+ ); +} +``` diff --git a/docs/components/layout-panels.md b/docs/components/layout-panels.md index 334cd71c..ead1db35 100644 --- a/docs/components/layout-panels.md +++ b/docs/components/layout-panels.md @@ -17,7 +17,7 @@ Reactodia provides layout panel components to display a row or a column of resiz ```tsx live function SomeLayout() { return ( -
+ @@ -39,7 +39,7 @@ function SomeLayout() { -
+ ) } ``` diff --git a/docs/components/link-types-toolbox.md b/docs/components/link-types-toolbox.md index 5b3b26bc..f925d967 100644 --- a/docs/components/link-types-toolbox.md +++ b/docs/components/link-types-toolbox.md @@ -3,7 +3,5 @@ [LinkTypesToolbox](/docs/api/workspace/functions/LinkTypesToolbox.md) is a component to display incoming and outgoing [link types](/docs/api/workspace/type-aliases/LinkTypeIri.md) from selected elements, toggle their visibility and initiate the [lookup](/docs/components/instances-search.md) for connected entities. :::tip - The same functionality is also available as `SearchSectionLinkTypes` [unified search section](/docs/components/unified-search.md). - ::: diff --git a/docs/components/navigator.md b/docs/components/navigator.md index 4049a0b7..035c0a88 100644 --- a/docs/components/navigator.md +++ b/docs/components/navigator.md @@ -1,3 +1,63 @@ # Navigator [Navigator](/docs/api/workspace/functions/Navigator) component is a [canvas widget](/docs/components/canvas.md) to display a minimap of the diagram contents. + +```tsx live +function Example() { + const GRAPH_DATA = 'https://reactodia.github.io/resources/orgOntology.ttl'; + + const {defaultLayout} = Reactodia.useWorker(Layouts); + + const {onMount} = Reactodia.useLoadedWorkspace(async ({context, signal}) => { + const {model, view, performLayout} = context; + + const response = await fetch(GRAPH_DATA, {signal}); + const graphData = new N3.Parser().parse(await response.text()); + const dataProvider = new Reactodia.RdfDataProvider({acceptBlankNodes: false}); + dataProvider.addGraph(graphData); + await model.importLayout({dataProvider, signal}); + + const first = model.createElement('http://www.w3.org/ns/org#Organization'); + const second = model.createElement('http://www.w3.org/ns/org#FormalOrganization'); + await Promise.all([ + model.requestElementData([first.iri, second.iri]), + model.requestLinks(), + ]); + await performLayout({signal}); + }, []); + + return ( +
+ + + +
+ ); +} +``` + +## Styles + +The component look can be customized using the following CSS properties (see [design system](/docs/concepts/design-system.mdx) for more information): + +| Property | Description | +|----------|-------------| +| `--reactodia-navigator-background-fill` | Background color on the minimap outside the scrollable pane area. | +| `--reactodia-navigator-scrollable-pane-fill` | Background color on the minimap for the scrollable pane area. | +| `--reactodia-navigator-viewport-fill` | Background color on the minimap for the viewport area. | +| `--reactodia-navigator-viewport-stroke-color` | Stroke color for the viewport area border. | +| `--reactodia-navigator-viewport-stroke-width` | Stroke width for the viewport area border. | +| `--reactodia-navigator-viewport-stroke-dash` | Stroke dash for the viewport area border. | +| `--reactodia-navigator-overflow-stroke-color` | Stroke color for the viewport area overflow border (displayed when the viewport is cutoff at the minimap border). | +| `--reactodia-navigator-overflow-stroke-width` | Stroke width for the viewport area overflow border (displayed when the viewport is cutoff at the minimap border). | +| `--reactodia-navigator-overflow-stroke-dash` | Stroke dash for the viewport area overflow border (displayed when the viewport is cutoff at the minimap border). | diff --git a/docs/components/selection.md b/docs/components/selection.md index 1b8b14ff..65a533cc 100644 --- a/docs/components/selection.md +++ b/docs/components/selection.md @@ -36,3 +36,13 @@ There are several built-in link actions that can be used: | [LinkActionDelete](/docs/api/workspace/functions/LinkActionDelete.md) | Deletes [the relation](/docs/concepts/graph-authoring.md). | | [LinkActionMoveEndpoint](/docs/api/workspace/functions/LinkActionMoveEndpoint.md) | Displays a handle which allows to [change the relation](/docs/concepts/graph-authoring.md) by moving its endpoint (source or target) to another entity. | | [LinkActionRename](/docs/api/workspace/functions/LinkActionRename.md) | Starts [renaming a link](/docs/api/workspace/interfaces/RenameLinkProvider.md) (change the label on the diagram only). | + +## Styles + +The component look can be customized using the following CSS properties (see [design system](/docs/concepts/design-system.mdx) for more information): + +| Property | Description | +|----------|-------------| +| `--reactodia-selection-icon-filter` | [CSS filter](https://developer.mozilla.org/en-US/docs/Web/CSS/filter) for the element selection action icons. | +| `--reactodia-selection-multiple-box-shadow` | Box shadow for the selection rectangle with multiple elements. | +| `--reactodia-selection-single-box-shadow` | Box shadow for the selection rectangle with a single element. | diff --git a/docs/components/toolbar.md b/docs/components/toolbar.md index 9c94ef3b..bc1493c8 100644 --- a/docs/components/toolbar.md +++ b/docs/components/toolbar.md @@ -2,6 +2,8 @@ [Toolbar](/docs/api/workspace/functions/Toolbar) component is a [canvas widget](/docs/components/canvas.md) to display a simple toolbar with a an optional dropdown menu. +## Toolbar actions + There are several built-in toolbar actions that can be displayed as menu items or quick action buttons: | Action component | Description | |------------------|-------------| @@ -14,3 +16,11 @@ There are several built-in toolbar actions that can be displayed as menu items o | [ToolbarActionRedo](/docs/api/workspace/functions/ToolbarActionRedo.md) | Performs a [redo](/docs/api/workspace/interfaces/CommandHistory.md#redo) for a command from the [command history](/docs/concepts/command-history.md). | | [ToolbarActionLayout](/docs/api/workspace/functions/ToolbarActionLayout.md) | Performs the default [graph layout algorithm](/docs/concepts/layout-workers.md) on the diagram content. | | [ToolbarLanguageSelector](/docs/api/workspace/functions/ToolbarLanguageSelector.md) | Displays a [data language](/docs/api/workspace/classes/DiagramModel.md#language) selector for the workspace. | + +## Styles + +The component look can be customized using the following CSS properties (see [design system](/docs/concepts/design-system.mdx) for more information): + +| Property | Description | +|----------|-------------| +| `--reactodia-toolbar-height` | Default height for the toolbar and the menu toggle. | diff --git a/docs/components/unified-search.md b/docs/components/unified-search.md index 70ac5108..ced6138c 100644 --- a/docs/components/unified-search.md +++ b/docs/components/unified-search.md @@ -2,10 +2,6 @@ [UnifiedSearch](/docs/api/workspace/functions/UnifiedSearch.md) is a component to display a search input with a dropdown for results. -## Hooks - -[useUnifiedSearchSection()](/docs/api/workspace/functions/useUnifiedSearchSection.md) hook can be used to implement a custom search section. - ## Search sections One or many available search sections (providers) can be specified: @@ -15,3 +11,97 @@ One or many available search sections (providers) can be specified: | [SearchSectionElementTypes](/docs/api/workspace/functions/SearchSectionElementTypes.md) | Allows to lookup entity types displayed in the tree form and create new entities in [authoring mode](/docs/concepts/graph-authoring.md). | | [SearchSectionEntities](/docs/api/workspace/functions/SearchSectionEntities.md) | Allows to lookup entities using [data provider](/docs/concepts/data-provider.md). | | [SearchSectionLinkTypes](/docs/api/workspace/functions/SearchSectionLinkTypes.md) | Allows to lookup displayed link types and change their [visibility settings](/docs/api/workspace/classes/DiagramModel.md#getlinkvisibility). | + +## Implement a custom search section + +[useUnifiedSearchSection()](/docs/api/workspace/functions/useUnifiedSearchSection.md) hook can be used to implement a custom search section: + +```tsx live noInline +function NpmPackagesSearchSection() { + const {shouldRender, searchStore} = Reactodia.useUnifiedSearchSection(); + + const [items, setItems] = React.useState([]); + const [selection, setSelection] = React.useState(() => new Set()); + + React.useEffect(() => { + const listener = new Reactodia.EventObserver(); + let controller = new AbortController(); + listener.listen(searchStore.events, 'executeSearch', async ({value}) => { + controller.abort(); + controller = new AbortController(); + const signal = controller.signal; + let items: Reactodia.ElementModel[] = []; + try { + items = await queryNpmRegistry(value, signal); + } catch (err) { + if (signal.aborted) { return; } + console.error(err); + } + setItems(items); + setSelection(new Set()); + }); + listener.listen(searchStore.events, 'clearSearch', ({value}) => { + controller.abort(); + setItems([]); + setSelection(new Set()); + }); + return () => { + controller.abort(); + listener.stopListening(); + }; + }, [searchStore]); + + return shouldRender ? ( +
+ +
+ ) : null; +} + +async function queryNpmRegistry( + text: string, + signal: AbortSignal +): Reactodia.ElementModel[] { + if (text.length === 0) { + return []; + } + const res = await fetch( + `https://registry.npmjs.org/-/v1/search?text=${text}`, + {signal} + ); + const data = await res.json(); + return data.objects.map((entry): Reactodia.ElementModel => ({ + id: `https://registry.npmjs.org/${entry.package.name}`, + types: [`urn:npmjs:Package`], + label: [], + properties: {}, + })); +} + +function SearchWithNpm() { + const {defaultLayout} = Reactodia.useWorker(Layouts); + const sections = React.useMemo(() => [ + { + key: 'npmPackages', + label: 'NPM packages', + component: + }, + ], []); + + return ( +
+ + + +
+ ); +} + +render(); +``` diff --git a/docs/components/visual-authoring.md b/docs/components/visual-authoring.md index 6aa225d3..e76a29ab 100644 --- a/docs/components/visual-authoring.md +++ b/docs/components/visual-authoring.md @@ -3,7 +3,5 @@ [VisualAuthoring](/docs/api/workspace/functions/VisualAuthoring) component is a [canvas widget](/docs/components/canvas.md) to provide UI for the [visual graph authoring](/docs/concepts/graph-authoring.md). :::important - `VisualAuthoring` widget must be provided to the canvas to in order to display visual graph authoring UI. - ::: diff --git a/docs/components/workspace.md b/docs/components/workspace.md index 3158e342..9390ef39 100644 --- a/docs/components/workspace.md +++ b/docs/components/workspace.md @@ -10,7 +10,7 @@ title: Workspace [useLoadedWorkspace()](/docs/api/workspace/functions/useLoadedWorkspace) hook should be used to perform an initial initialization for the workspace which correctly reverts the changes and aborts async operations via provided [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) when the workspace component is unmounted. -[useWorkspace()](/docs/api/workspace/functions/useWorkspace) hook can be used from inside `` child components to access workspace context. +[useWorkspace()](/docs/api/workspace/functions/useWorkspace) hook can be used from inside `` child components to access workspace context; see [workspace context](/docs/concepts/workspace-context.md) for details. ## Workspace Layout @@ -20,7 +20,7 @@ Default built-in layout is provided as [DefaultWorkspace](/docs/api/workspace/fu Alternative (classic) built-in layout is provided as [ClassicWorkspace](/docs/api/workspace/functions/ClassicWorkspace) component which uses [layout panels](/docs/components/layout-panels.md) with [class tree](/docs/components/class-tree.md), [instances search](/docs/components/instances-search.md), [link types toolbox](/docs/components/link-types-toolbox.md), [ClassicToolbar](/docs/api/workspace/functions/ClassicToolbar) and all built-in [canvas widgets](/docs/components/canvas.md). -When providing a custom workspace layout it is required to use [WorkspaceRoot](/docs/api/workspace/functions/WorkspaceRoot) as a top-level parent component to establish necessary defaults. +When providing a custom workspace layout it is required to use [WorkspaceRoot](/docs/api/workspace/functions/WorkspaceRoot) as a top-level parent component to establish necessary style defaults, including styles for light or dark [color scheme](/docs/concepts/design-system.mdx). ### Example: canvas-only custom layout diff --git a/docs/concepts/canvas-coordinates.md b/docs/concepts/canvas-coordinates.md index fa5fca74..53d4e145 100644 --- a/docs/concepts/canvas-coordinates.md +++ b/docs/concepts/canvas-coordinates.md @@ -11,8 +11,8 @@ Reactodia uses different coordinate systems when dealing with infinitely-resizab | Type | Description | |-------------------|-------------| | paper | Main coordinates system for [diagram content](/docs/concepts/graph-model.md) (elements, links, etc) — unlimited in size, always in 1:1 scale with element and link templates. | -| scrollable pane | Represents scaled but still unlimited in size layer, natively scrolled inside viewport container.
It is possible to use [totalPaneSize()](/docs/api/workspace/functions/totalPaneSize.md) and [paneTopLeft()](/docs/api/workspace/functions/paneTopLeft.md) to get current pane bounds with the same coordinates type. | -| client (viewport) | Represents fixed-size "window" into visible graph area, equal to [DOM client coordinates](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth) for the [Canvas](/docs/components/canvas) component. | +| scrollable pane | Represents scaled but still unlimited in size layer, natively scrolled inside viewport container.
It is possible to use [`totalPaneSize()`](/docs/api/workspace/functions/totalPaneSize.md) and [`paneTopLeft()`](/docs/api/workspace/functions/paneTopLeft.md) to get current pane bounds with the same coordinates type. | +| client (viewport) | Represents fixed-size "window" into visible graph area, equal to [DOM client coordinates](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth) for the [`Canvas`](/docs/components/canvas) component. | | page | Same as [DOM page coordinates](https://developer.mozilla.org/en-US/docs/Web/CSS/CSSOM_view/Coordinate_systems#page) — generally used when handling pointer-related events. | ![Reactodia coordinate system](/img/reactodia-coords-structure.svg) @@ -21,10 +21,10 @@ Reactodia uses different coordinate systems when dealing with infinitely-resizab | From type | To type | Method | | ------------------|-------------------|--------| -| paper | scrollable pane | [paperToScrollablePaneCoords()](/docs/api/workspace/interfaces/CanvasMetrics.md#papertoscrollablepanecoords) | -| | page | [paperToPageCoords()](/docs/api/workspace/interfaces/CanvasMetrics.md#papertopagecoords) | -| scrollable pane | paper | [scrollablePaneToPaperCoords()](/docs/api/workspace/interfaces/CanvasMetrics.md#scrollablepanetopapercoords) | -| | client (viewport) | [scrollablePaneToClientCoords()](/docs/api/workspace/interfaces/CanvasMetrics.md#scrollablepanetoclientcoords) | -| client (viewport) | paper | [clientToPaperCoords()](/docs/api/workspace/interfaces/CanvasMetrics.md#clienttopapercoords) | -| | scrollable pane | [clientToScrollablePaneCoords()](/docs/api/workspace/interfaces/CanvasMetrics.md#clienttoscrollablepanecoords) | -| page | paper | [pageToPaperCoords()](/docs/api/workspace/interfaces/CanvasMetrics.md#pagetopapercoords) | +| paper | scrollable pane | [`paperToScrollablePaneCoords()`](/docs/api/workspace/interfaces/CanvasMetrics.md#papertoscrollablepanecoords) | +| | page | [`paperToPageCoords()`](/docs/api/workspace/interfaces/CanvasMetrics.md#papertopagecoords) | +| scrollable pane | paper | [`scrollablePaneToPaperCoords()`](/docs/api/workspace/interfaces/CanvasMetrics.md#scrollablepanetopapercoords) | +| | client (viewport) | [`scrollablePaneToClientCoords()`](/docs/api/workspace/interfaces/CanvasMetrics.md#scrollablepanetoclientcoords) | +| client (viewport) | paper | [`clientToPaperCoords()`](/docs/api/workspace/interfaces/CanvasMetrics.md#clienttopapercoords) | +| | scrollable pane | [`clientToScrollablePaneCoords()`](/docs/api/workspace/interfaces/CanvasMetrics.md#clienttoscrollablepanecoords) | +| page | paper | [`pageToPaperCoords()`](/docs/api/workspace/interfaces/CanvasMetrics.md#pagetopapercoords) | diff --git a/docs/concepts/command-history.md b/docs/concepts/command-history.md index 9d69ecf9..b4540dcf 100644 --- a/docs/concepts/command-history.md +++ b/docs/concepts/command-history.md @@ -4,8 +4,125 @@ sidebar_position: 4 # Command History -This page describes how command history and undo/redo works in Reactodia. +Reactodia uses a common pattern to organize changes to the diagram model into "commands" representing different atomic actions to facilitate undo/redo support. -API references: - - [Command](/docs/api/workspace/interfaces/Command) and its [utility namespace](/docs/api/workspace/namespaces/Command) - - [CommandHistory](/docs/api/workspace/interfaces/CommandHistory) +## Commands and undo/redo history + +The [`Command`](/docs/api/workspace/interfaces/Command) interface defines an action which performs a set of changes to the Reactodia state and can be executed and reverted as needed. + +:::tip +The library contains many built-in commands to manipulate the diagram model, graph authoring state or perform other effects, you can find them all at [API > workspace > Commands](/docs/api/workspace/#commands). +::: + +To execute or revert a command, the [`CommandHistory`](/docs/api/workspace/interfaces/CommandHistory) instance from `DiagramModel.history` should be used to be able to undo or redo it later: + +```ts +function Component() { + const {model} = Reactodia.useWorkspace(); + + const onClick = () => { + const command = changeLinkTypeVisibility( + model, 'http://example.com/connectedTo', 'hidden' + ); + model.history.execute(command); + }; + + const onUndo = () => { + // Later: undo or redo a command + model.history.undo(); + model.history.redo(); + }; + + // ... +} +``` + +Another way to use command history is to perform state changes and register a "revert" command which is used for diagram geometry updates: + +```ts +function Component() { + const {model} = Reactodia.useWorkspace(); + + const onMove = () => { + const restoreGeometry = Reactodia.RestoreGeometry.capture(model); + /* ... make changes to the element positions and link vertices ... */ + model.history.registerToUndo(command); + }; + + // ... +} +``` + +## Command batches + +When executing multiple commands in a sequence in cases it would be desirable to undo or redo them all at once at though they were a single atomic command. In that case it is possible to start a [`CommandBatch`](/docs/api/workspace/interfaces/CommandBatch.md) via [`CommandHistory.startBatch()`](/docs/api/workspace/interfaces/CommandHistory.md#startbatch), execute the commands and store the batch, so a single command is added to the history: + +```ts +function Component() { + const {model} = Reactodia.useWorkspace(); + const {canvas} = Reactodia.useCanvas(); + + const onAddElements = ( + target: Reactodia.Element, + iris: readonly Reactodia.ElementIri[] + ) => { + const batch = model.history.startBatch('Adding multiple elements'); + + for (const iri of iris) { + // Some methods implicitly add commands to the history, + // i.e. to the active batch if any + const element = model.createElement(iri); + + // In other cases the command needs to be executed explicitly + batch.history.execute(setElementState(element, {'my:custom:state': 42})); + } + + batch.store(); + }; +} +``` + +It is also possible to discard a batch instead of storing it with [`CommandBatch.discard()`](/docs/api/workspace/interfaces/CommandBatch.md#discard) to avoid putting the commands in the history in the first place. + +:::note +Starting a new batch when there is an active command batch already causes the new batch to become nested, which allows to use operations creating command batches as part of a larger operation having its own top-level batch. +::: + +## How to define a new command + +While it is possible to implement [`Command`](/docs/api/workspace/interfaces/Command.md) interface directly, the library provides a [utility namespace](/docs/api/workspace/namespaces/Command) with the same name to simplify the process. + +[`Command.create()`](/docs/api/workspace/namespaces/Command/functions/create.md) defines a command from a callback which returns the reverse command: + +```ts +function exchangeElementPositions( + first: Reactodia.ElementElement, + second: Reactodia.ElementElement +): Command { + return Command.create('Exchange element positions', () => { + const position = first.position; + first.setPosition(second.position); + second.setPosition(position); + return exchangeElementPositions(first, second); + }); +} +``` + +[`Command.compound()`](/docs/api/workspace/namespaces/Command/functions/compound.md) defines a command from a sequence of other commands similar to using a command batch: + +```ts +function resetElementStateForAll( + elements: readonly Reactodia.ElementElement[] +): Command { + const commands = elements.map(el => Reactodia.setElementState(el, undefined)); + return Command.compound('Reset state for elements', commands); +} +``` + +[`Command.effect()`](/docs/api/workspace/namespaces/Command/functions/effect.md) defines a command which runs only after it executed in "forward" direction but skipped on revert: + +```ts +function logAsCommand(message: string): Command { + return Command.effect('Log a message', () => console.log(message)); +} +``` diff --git a/docs/concepts/data-provider.md b/docs/concepts/data-provider.md index 46a66fa1..3044159e 100644 --- a/docs/concepts/data-provider.md +++ b/docs/concepts/data-provider.md @@ -4,13 +4,142 @@ sidebar_position: 2 # Data Provider -This page describes the data provider contract for incremental data loading when exploring the graph. - -API references: - - [DataProvider](/docs/api/workspace/interfaces/DataProvider) - - [EmptyDataProvider](/docs/api/workspace/classes/EmptyDataProvider) - - [RdfDataProvider](/docs/api/workspace/classes/RdfDataProvider) - - [SparqlDataProvider](/docs/api/workspace/classes/SparqlDataProvider) - - [CompositeDataProvider](/docs/api/workspace/classes/CompositeDataProvider) - - [DecoratedDataProvider](/docs/api/workspace/classes/DecoratedDataProvider) - - [IndexedDbCachedProvider](/docs/api/workspace/classes/IndexedDbCachedProvider) +Reactodia defines a contract ([`DataProvider`](/docs/api/workspace/interfaces/DataProvider) interface) to query a subset of data from external source ([data graph](./graph-model.md#data-graph)) to provide means for incremental data loading when exploring the graph. + +## IRI and RDF + +Reactodia uses RDF ([Resource Description Framework](https://en.wikipedia.org/wiki/Resource_Description_Framework)) as a representation format for the graph data. The core concepts of RDF are: + - **IRI** ([Internationalized Resource Identifier](https://en.wikipedia.org/wiki/Internationalized_Resource_Identifier)) — basically a URI but not limited to ASCII and may contain most unicode characters. + - **resource** — a graph node (element) represented by an **IRI** (in which case it is a **named node**) or a anonymous dataset-local identifier (it which case it is a **blank node**). + - **literal** — a simple value represented by a string with a *datatype* or a *language* tag. + - **triple** — an expressions of the form *subject*–*predicate*–*object* to represent a graph edge of type *predicate* (link type) between *source* **resource** and *target* **resource** or **literal**. + - **quad** — a **triple** with an additional associated *graph* **IRI**. + +For interoperability with other RDF-based libraries for JavaScript, the property values for entities and relations are stored as either **named node** or **literal** values using commonly used [RDF/JS](https://rdf.js.org/) representation. + +To provide improved type-safety with TypeScript when dealing with various kinds of IRIs from the [data graph](./graph-model.md#data-graph), the library uses the following [branded string types](https://www.learningtypescript.com/articles/branded-types): + +| Type | Description | +|-----------------|-------------| +| [`ElementIri`](/docs/api/workspace/type-aliases/ElementIri.md) | IRI of a entity (**resource**). | +| [`ElementTypeIri`](/docs/api/workspace/type-aliases/ElementTypeIri.md) | IRI of a entity type (**resource**). | +| [`LinkTypeIri`](/docs/api/workspace/type-aliases/LinkTypeIri.md) | IRI of a link type, i.e. triple *predicate* when the **object** is a **resource** (the predicate is always a **named node**). | +| [`PropertyTypeIri`](/docs/api/workspace/type-aliases/PropertyTypeIri.md) | IRI of a property type, i.e. triple **predicate** when the **object** is a **literal** (the predicate is always a **named node**). | + +## Data Providers + +The library provides a number of built-in [`DataProvider`](/docs/api/workspace/interfaces/DataProvider) interface implementations for various scenarios: + +| Provider | Description | +|----------|-------------| +| [`EmptyDataProvider`](/docs/api/workspace/classes/EmptyDataProvider) | An empty provider which returns nothing from all query methods. | +| [`RdfDataProvider`](/docs/api/workspace/classes/RdfDataProvider) | Provides graph data from an in-memory [RDF/JS-compatible](https://rdf.js.org/data-model-spec/) graph dataset. | +| [`SparqlDataProvider`](/docs/api/workspace/classes/SparqlDataProvider) | Provides graph data by requesting it from a [SPARQL](https://en.wikipedia.org/wiki/SPARQL) endpoint. | +| [`CompositeDataProvider`](/docs/api/workspace/classes/CompositeDataProvider) | Provides graph data by combining results from multiple other data providers. | +| [`DecoratedDataProvider`](/docs/api/workspace/classes/DecoratedDataProvider) | Generically wraps over another provider to modify how the requests are made or alter the results. | +| [`IndexedDbCachedProvider`](/docs/api/workspace/classes/IndexedDbCachedProvider) | Caches graph data returned from another data provider using browser's built-in [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) storage. | + +:::tip +It is recommended to extend [`EmptyDataProvider`](/docs/api/workspace/classes/EmptyDataProvider) when implementing a data provider: this way methods can be implemented one-by-one as needed and no changes will be necessary if `DataProvider` will gain additional methods in the future. +::: + +### Example: provisioning an `RdfDataProvider` from a graph data in JSON Graph Format + +In this example Reactodia is initialized with `RdfDataProvider` which is provisioned with graph data in [JSON Graph Format](https://github.com/jsongraph/json-graph-specification). + +As a first step, the data in converted into RDF graph (**triples**), next the graph is added to the provider, finally all the nodes are added tot the diagram: + +```tsx live +function ExampleRdfProviderProvisionFromJGF() { + const {defaultLayout} = Reactodia.useWorker(Layouts); + + const {onMount} = Reactodia.useLoadedWorkspace(async ({context, signal}) => { + const {model, performLayout} = context; + + // Example graph data based on JSON graph documentation: + const jsonGraph = { + "graph": { + "nodes": { + "alice": { + "label": "Alice", + "metadata": { + "type": "Person", + "birthDate": "1990-01-01" + } + }, + "bob": { + "label": "Bob", + "metadata": { + "type": "Person", + "birthDate": "1990-02-02" + } + } + }, + "edges": [ + { + "source": "alice", + "relation": "isFriendOf", + "target": "bob", + "metadata": { + "since": "2000-03-03" + } + } + ] + } + } as const; + + const factory = Reactodia.Rdf.DefaultDataFactory; + const hasType = factory.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'); + const hasLabel = factory.namedNode('http://www.w3.org/2000/01/rdf-schema#label'); + + const triples: Reactodia.Rdf.Quad[] = []; + for (const [id, node] of Object.entries(jsonGraph.graph.nodes)) { + const iri = factory.namedNode(`graph:node:${id}`); + const {type, ...otherProperties} = node.metadata; + triples.push( + factory.quad(iri, hasType, factory.namedNode(`graph:type:${type}`)), + factory.quad(iri, hasLabel, factory.literal(node.label)) + ); + for (const [property, value] of Object.entries(otherProperties)) { + const propertyIri = factory.namedNode(`graph:property:${property}`); + triples.push(factory.quad(iri, propertyIri, factory.literal(value))); + } + } + + for (const edge of jsonGraph.graph.edges) { + const source = factory.namedNode(`graph:node:${edge.source}`); + const target = factory.namedNode(`graph:node:${edge.target}`); + const predicate = factory.namedNode(`graph:node:${edge.relation}`); + const edgeTriple = factory.quad(source, predicate, target); + triples.push(edgeTriple); + for (const [property, value] of Object.entries(edge.metadata)) { + const propertyIri = factory.namedNode(`graph:property:${property}`); + triples.push(factory.quad(edgeTriple, propertyIri, factory.literal(value))); + } + } + + const dataProvider = new Reactodia.RdfDataProvider(); + dataProvider.addGraph(triples); + + await model.createNewDiagram({dataProvider, signal}); + + const elementIris: Reactodia.ElementIri[] = []; + for (const {element} of await dataProvider.lookup({elementTypeId: 'graph:type:Person'})) { + elementIris.push(model.createElement(element).iri); + } + + await model.requestElementData(elementIris); + await model.requestLinks(); + await performLayout({signal}); + }, []); + + return ( +
+ + + +
+ ); +} +``` diff --git a/docs/concepts/design-system.mdx b/docs/concepts/design-system.mdx new file mode 100644 index 00000000..b6ebac4c --- /dev/null +++ b/docs/concepts/design-system.mdx @@ -0,0 +1,416 @@ +--- +sidebar_position: 10 +title: Design System +--- + +import * as React from 'react'; +import * as Reactodia from '@reactodia/workspace'; +import { ButtonToggle } from '@site/src/components/ButtonToggle'; +import { ColorBoxes } from '@site/src/components/ColorBoxes'; + +# Basic Design System + +Reactodia defines a basic design system inspired by [Infima](https://infima.dev/) styling framework to support both light and dark color schemes and easy customization via [CSS custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascading_variables/Using_CSS_custom_properties). + +This page documents base (common) styles for used as defaults for all UI components. Component-specific CSS properties are documented on the corresponding [component pages](/docs/category/components). + +See [Reactodia theme styling source](https://github.com/reactodia/reactodia-workspace/tree/master/styles/theme) for the complete list of CSS properties to customize and their defaults for both light and dark color schemes. + +## Colors + +:::tip + +Toggle active color scheme at the top to see how the default colors are defined for either light or dark themes. + +::: + +### Grays {#color-grays} + + + `var(--reactodia-color-gray-${i * 100})`) + } + /> + + +Color-scheme independent gray colors gradient from 0 (white) to 1000 (black) in increments of 100: +```css +--reactodia-color-gray-{i} +``` + +### Emphasis {#color-emphasis} + + + `var(--reactodia-color-emphasis-${i * 100})`) + } + /> + + +Color-scheme specific gray colors gradient from 0 (same as schema color) to 1000 (opposite to schema color) in increments of 100: +```css +--reactodia-color-emphasis-{i} +``` + +### Content and Background + + + + + +Color-scheme specific color for a text-like content, pure inverse for the background, and a contrast (which is suitable for content on top of a background of the named color): +```css +--reactodia-color-content +--reactodia-color-content-inverse +--reactodia-color-content-contrast +``` + + + + + +Color-scheme specific color for a background-like layers, and a surface one which can be used for layers placed on top of the main background: +```css +--reactodia-background-color +--reactodia-background-color-surface +``` + +### Named colors + +export const NamedColorBoxes = ({color}) => ( + <> + + + +); + +Named colors can be used to show specific action types for buttons, importance for statuses, etc. The primary color can be specifically used to highlight the "main" action or give a color accent to a UI element: +```css +--reactodia-color-{color}-lightest +--reactodia-color-{color}-lighter +--reactodia-color-{color}-light +--reactodia-color-{color} +--reactodia-color-{color}-dark +--reactodia-color-{color}-darker +--reactodia-color-{color}-darkest +``` + +Additionally, each color has a contrast foreground (to put on the named color) and a contrast background (to put the named color on): +```css +--reactodia-color-{color}-contrast-background +--reactodia-color-{color}-contrast-foreground +``` + +#### `primary` color + + + + + +#### `secondary` color + + + + + +#### `success` color + + + + + +#### `info` color + + + + + +#### `warning` color + + + + + +#### `danger` color + + + + + +## Text + +The following properties allow to customize font family, base size and color: + +```css +--reactodia-font-family-base +--reactodia-font-family-monospace +--reactodia-font-size-base +--reactodia-line-height-base +--reactodia-font-color-base +--reactodia-font-color-base-inverse +``` + +```tsx live +function Text() { + return ( + +

+ Normal: The quick brown fox jumps over the lazy dog. +

+

+ Monospace: The quick brown fox jumps over the lazy dog. +

+

+ Inverse: The quick brown fox jumps over the lazy dog. +

+
+ ); +} +``` + +## Borders + +The following properties allow to customize base border styling, including default border radius for UI elements such as buttons, inputs, panels, etc: +```css +--reactodia-border-width-base +--reactodia-border-radius-base +--reactodia-border-color-base +``` + +```tsx live +function Borders() { + return +
+ Panel +
+ + +
+} +``` + +## Spacing + +The following properties allow to customize default spacing between UI elements: +```css +--reactodia-spacing-base +--reactodia-spacing-vertical +--reactodia-spacing-horizontal +``` + +```tsx live +function Spacing() { + return +
+ {Array.from({length: 9}, (_, i) => +
+ )} +
+ +} +``` + +## Controls + +### Buttons + +export const Button = ({kind, state}) => { + const active = state === 'active' ? 'active' : ''; + return ( + + ); +}; + +export const Buttons = () => { + const [state, setState] = React.useState('default'); + return ( +
+
+ Button state: + +
+
+
+
+ ); +}; + + + + + +There are specific CSS properties to define the style of various buttons: +```tsx live +function Button() { + return +
+ +
+
+} +``` + +### Inputs + +export const Inputs = () => { + const [state, setState] = React.useState('default'); + return ( +
+
+ Input state: + +
+
+ + +
+
+ ); +}; + + + + + +There are specific CSS properties to define the style of various inputs, including `` and ` + + + + ); +} +``` diff --git a/docs/concepts/event-system.md b/docs/concepts/event-system.md index 8003f218..8c0a149a 100644 --- a/docs/concepts/event-system.md +++ b/docs/concepts/event-system.md @@ -5,11 +5,120 @@ title: Event System # Publish-Subscribe Event System -This page describes publish-subscribe mechanism which is used in Reactodia to connect different components and react to state changes. - -API references: - - [Events](/docs/api/workspace/interfaces/Events), [EventTrigger](/docs/api/workspace/interfaces/EventTrigger) and [EventSource](/docs/api/workspace/classes/EventSource) - - [Listener](/docs/api/workspace/type-aliases/Listener) and [AnyListener](/docs/api/workspace/type-aliases/AnyListener) - - [AnyEvent](/docs/api/workspace/interfaces/AnyEvent) - - [PropertyChange](/docs/api/workspace/interfaces/PropertyChange) - - [EventObserver](/docs/api/workspace/classes/EventObserver) +Reactodia uses a lightweight [`EventEmitter`](https://nodejs.org/docs/latest/api/events.html)-like publish-subscribe mechanism to connect different components and observe changes to the state. + +## Observing events + +An observable instance in the library typically expose an `events` property implementing an [`Events`](/docs/api/workspace/interfaces/Events) interface. Listeners can be attached directly to the `Events` or subscribed via `EventObserver` to make it easy to unsubscribe: + +```ts +const {model} = Reactodia.useWorkspace(); + +const onChangeSelection = () => { + console.log('New selection:', model.selection); +}; +// Subscribe to the selection change event +model.events.on('changeSelection', onChangeSelection); +// Unsubscribe, must pass the same callback +model.events.off('changeSelection', onChangeSelection); + +const observer = new Reactodia.EventObserver(); +// Subscribe to the language change event +observer.listen(model.events, 'changeLanguage', ({previous}) => { + console.log(`Changed language from ${previous} to ${model.language}`); +}); +// Unsubscribe from all events added via listen() by the observer +observer.stopListening(); +``` + +It is possible to listen for all events on an instance by using [`Events.onAny()`](/docs/api/workspace/interfaces/Events.md#onany) or [`EventObserver.listenAny()`](/docs/api/workspace/classes/EventObserver.md#listenany): + +```ts +function Component() { + const {model} = React.useWorkspace(); + React.useEffect(() => { + const element = model.getElement(elementId); + const observer = new Reactodia.EventObserver(); + observer.listenAny(element, ({data}) => { + if (data.requestedFocus || data.requestedRedraw) { + console.log('Element requested something'); + } + }); + return () => observer.stopListening(); + }, [elementId]); + // ... +} +``` + +### Using React hooks to listen to events + +In case of change-like events it is recommended to use [`useObservedProperty()`](/docs/api/workspace/functions/useObservedProperty.md) to observe current value: + +```ts +const {editor} = Reactodia.useWorkspace(); +// Subscribe to editor.authoringState changes +const authoringState = Reactodia.useObservedProperty( + editor.events, 'changeAuthoringState', () => editor.authoringState +); +``` + +Alternatively it is possible to use a combination of [`useEventStore()`](/docs/api/workspace/functions/useEventStore.md) and either a React built-in [`useSyncExternalStore()`](https://react.dev/reference/react/useSyncExternalStore) or a compatibility shim [`Reactodia.useSyncStore()`](/docs/api/workspace/functions/useSyncStore.md) for more control over subscription: + +```ts +import { useSyncExternalStore } from 'react'; + +function Component() { + const {editor} = Reactodia.useWorkspace(); + const eventStore = Reactodia.useEventStore( + editor.events, 'changeAuthoringState' + ); + const debouncedStore = Reactodia.useFrameDebouncedStore(eventStore); + const authoringState = useSyncExternalStore( + debouncedStore, () => editor.authoringState + ); + // ... +} +``` + +In the above example, [`Reactodia.useFrameDebouncedStore()`](/docs/api/workspace/functions/useFrameDebouncedStore.md) hook is used to debounce React component updates due to triggered events from the event store to only once each rendered frame based on [`requestAnimationFrame()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame). + +## Making an observable + +To create an observable instance it would be enough to implement the [`Events`](/docs/api/workspace/interfaces/Events) interface. An easiest way to do it would be to use [`EventSource`](/docs/api/workspace/classes/EventSource): + +```ts +// Declare event types +interface MyObservableEvents { + changeTitle: Reactodia.PropertyChange; + notification: { + readonly status: 'normal' | 'error'; + readonly message: string; + }; +} + +class MyObservableThing { + // Create an event source + private readonly source = new EventSource(); + readonly events: Events = this.source; + + // ... + + setTitle(title: string) { + const previous = this._title; + if (previous !== title) { + this._title = title; + // Trigger change event + this.source.trigger('changeTitle', {source: this, previous}); + } + } + + private handleNotification(status: 'normal' | 'error', message: string): void { + // Trigger another event + this.source.trigger('notification', {status, message}); + } +} +``` + +:::tip +[`EventSource`](/docs/api/workspace/classes/EventSource) implements [`EventTrigger`](/docs/api/workspace/interfaces/EventTrigger) interface which can be used as a separate type, e.g. a combination of `Events & EventTrigger` can be used as an "event bus" to trigger and listen for events at the same time. +::: diff --git a/docs/concepts/graph-authoring.md b/docs/concepts/graph-authoring.md index 9b4f290b..e2574501 100644 --- a/docs/concepts/graph-authoring.md +++ b/docs/concepts/graph-authoring.md @@ -1,13 +1,15 @@ --- -sidebar_position: 7 +sidebar_position: 8 --- # Graph Authoring -This page describes visual graph authoring mechanism to edit the graph data: create, update or delete [entities and relations](/docs/concepts/graph-model.md). +The library supports visual graph authoring mechanism to edit the graph data: create, update or delete [entities and relations](/docs/concepts/graph-model.md). -API references: - - [MetadataProvider](/docs/api/workspace/interfaces/MetadataProvider) - - [ValidationProvider](/docs/api/workspace/interfaces/ValidationProvider) - - [AuthoringState](/docs/api/workspace/interfaces/AuthoringState) and its [utility namespace](/docs/api/workspace/namespaces/AuthoringState) - - [EditorController](/docs/api/workspace/classes/EditorController) +:::info +This section is incomplete, please look at the reference API documentation instead: + - [`MetadataProvider`](/docs/api/workspace/interfaces/MetadataProvider) + - [`ValidationProvider`](/docs/api/workspace/interfaces/ValidationProvider) + - [`AuthoringState`](/docs/api/workspace/interfaces/AuthoringState) and its [utility namespace](/docs/api/workspace/namespaces/AuthoringState) + - [`EditorController`](/docs/api/workspace/classes/EditorController) +::: diff --git a/docs/concepts/graph-model.md b/docs/concepts/graph-model.md index 8bdbf6dd..f021bb1f 100644 --- a/docs/concepts/graph-model.md +++ b/docs/concepts/graph-model.md @@ -4,4 +4,142 @@ sidebar_position: 1 # Graph Model -This page describes how the diagram is composed of [elements](/docs/api/workspace/classes/Element.md) and [links](/docs/api/workspace/classes/Link.md), where some of them can represent [entities](/docs/api/workspace/classes/EntityElement.md), [grouped entities](/docs/api/workspace/classes/EntityGroup.md), [relations](/docs/api/workspace/classes/RelationLink.md) and [groups relations](/docs/api/workspace/classes/RelationGroup.md). +The central part of the Reactodia state is the diagram content which is a mutable collection of so-called cells presented on the [`Canvas`](/docs/components/canvas.md). + +## Diagram content + +The diagram is composed of *abstract* [elements](/docs/api/workspace/classes/Element.md) and [links](/docs/api/workspace/classes/Link.md) and can be though of as collection of graph nodes and edges drawn on the canvas surface. + +Each **element** is identified by a [generated ID](/docs/api/workspace/classes/Element.md#generateid), stores a [position](/docs/api/workspace/classes/Element.md#position) (in [paper coordinates](./canvas-coordinates.md)) and an arbitrary persisted [element state](/docs/api/workspace/classes/Element.md#elementstate). + +Each **link** is identified by a [generated ID](/docs/api/workspace/classes/Link.md#generateid), has source and target element IDs, and a [link type IRI](/docs/api/workspace/type-aliases/LinkTypeIri.md). In its state it stores path geometry as a [collection of points](/docs/api/workspace/classes/Link.md#vertices) (in [paper coordinates](./canvas-coordinates.md)) and an arbitrary persisted [link state](/docs/api/workspace/classes/Link.md#linkstate). + +:::note +Currently there is only one concrete element type besides the data graph ones: [`VoidElement`](/docs/api/workspace/classes/VoidElement.md) which is displayed as nothing (empty point) but can be connected to with the links. +::: + +## Data graph + +While elements and links are considered to be diagram graph nodes and edges, some of them can represent entities and relations from (external) data graph defined by the [`DataProvider`](./data-provider.md): + +| Cell type | Description | +|-----------|-------------| +| [`EntityElement`](/docs/api/workspace/classes/EntityElement.md) | Represents an entity (data graph node) with a globally unique ID, i.e. an [element IRI](/docs/api/workspace/type-aliases/ElementIri.md). | +| [`EntityGroup`](/docs/api/workspace/classes/EntityGroup.md) | Represents a group of entities as a single element. | +| [`RelationLink`](/docs/api/workspace/classes/RelationLink.md) | Represents a relation (data graph edge) uniquely identified by a tuple (source IRI, target IRI, [link type IRI](/docs/api/workspace/type-aliases/LinkTypeIri.md)). | +| [`RelationGroup`](/docs/api/workspace/classes/RelationGroup.md) | Represents a group of relations a single link, usually between an entity group and another element or a group. | + +:::note +An IRI is [Internationalized Resource Identifier](https://en.wikipedia.org/wiki/Internationalized_Resource_Identifier) which is basically a URI but may additionally contain most unicode characters. + +See how the library uses [IRIs and RDF](./data-provider.md#iri-and-rdf) for more details. +::: + +Basically, a sub-graph of a full external data graph composed of entities and relations forms a diagram on the canvas. By exploring that graph, other entities and relation are added to the diagram content, expanding the view of the data graph and presenting more interconnections throughout the data. + +Using the [graph authoring](./graph-authoring.md) feature it is possible to work on the changes to the data graph and apply it once ready. + +## Manipulating the diagram + +To access and manipulate the diagram one can use [diagram model](/docs/api/workspace/classes/DataDiagramModel.md) from [`WorkspaceContext`](./workspace-context.md): +```ts +function WorkingWithDiagramModel() { + const {model} = Reactodia.useWorkspace(); + + // Different ways to place entities to the canvas + const element1 = model.createElement('http://example.com/element1' as Reactodia.ElementIri); + const element2 = model.createElement('urn:my:element2' as Reactodia.ElementIri); + const element3 = model.createElement({ + id: 'my-schema:element3' as Reactodia.ElementIri, + types: ['urn:my:MyElement' as Reactodia.ElementTypeIri], + label: ['Element3'], + properties: {}, + }); + + // Place relations between specified entities (must exist on the diagram) + const [link1] = model.createLinks({ + sourceId: element1.iri, + targetId: element2.iri, + linkTypeId: 'urn:my:linkTypeA' as Reactodia.LinkTypeIri, + properties: {}, + }); + + // Remove and place element again to the canvas + model.removeElement(element3.id); + model.addElement(element3); + + // Remove and place link again to the canvas + model.removeLink(link1.id); + model.addLink(link1); + + // Get source and target of a link + model.getSource(link1) === model.getElement(link1.sourceId); + model.getTarget(link1) === mode.getElement(link1.targetId); + + for (const link of model.getElementLinks(element1)) { + // Enumerate all links connected to an element + } + + for (const element of model.elements) { + // Enumerate all elements on the diagram + } + + for (const link of model.links) { + // Enumerate all links on the diagram + } +} +``` + +## Link visibility + +Some links can be hidden from the canvas by setting its link type visibility with [`setLinkVisibility()`](/docs/api/workspace/classes/DataDiagramModel.md#setlinkvisibility) to `hidden`. The hidden links are invisible and would not affect the [graph layout](./layout-workers.md). + +Alternatively, a link type visibility can be set to `withoutLabel` to display it as path (line) only without any additional labels. + +```ts +function WorkingWithLinkVisibility() { + const {model} = Reactodia.useWorkspace(); + + model.setLinkVisibility('urn:my:linkTypeA' as Reactodia.LinkTypeIri, 'hidden'); + model.setLinkVisibility('urn:my:linkTypeB' as Reactodia.LinkTypeIri, 'withoutLabel'); +} +``` + +Link visibility settings can be changed from the UI with [`SearchSectionLinkTypes`](/docs/components/unified-search.md#search-sections) and [`LinkTypesToolbox`](/docs/components/link-types-toolbox.md) components. + +These settings are [imported and exported](#import-and-export) alongside the diagram content. + +## Import and export + +The diagram layout (which includes cell positions and states) can be exported (saved) and imported (restored) at any time using corresponding [`exportLayout()`](/docs/api/workspace/classes/DataDiagramModel.md#exportlayout) and [`importLayout()`](/docs/api/workspace/classes/DataDiagramModel.md#importlayout) methods: + +```tsx +function WorkingWithImportExport() { + const {model, onMount} = Reactodia.useLoadedWorkspace(async ({context, signal}) => { + const {model} = context; + + // Import a diagram layout on mount + const dataProvider = /* ... */; + const diagram = await getPreviouslyExportedDiagram(); + await model.importLayout({dataProvider, diagram, signal}); + }, []); + + const onClick = () => { + // Export a diagram layout by a user action + const layout = model.exportLayout(); + // Store the layout somewhere + }; + + return ( + + + + ); +} +``` + +:::note +Currently only [data graph](#data-graph) elements and links (including groups) can be exported and imported. +::: diff --git a/docs/concepts/i18n.md b/docs/concepts/i18n.md new file mode 100644 index 00000000..3c80caff --- /dev/null +++ b/docs/concepts/i18n.md @@ -0,0 +1,115 @@ +--- +sidebar_position: 9 +--- + +# UI localization and i18n + +Reactodia has a built-in support for UI text strings localization. +Each UI component in the library that displays text labels or descriptions resolves +them from [translation bundles](#translation-bundle) via [Translation interface](#translation-interface-and-hooks). + +## Translation bundle + +Localized texts are organized in a form of plain JSON objects called `TranslationBundle`. +The bundle have the following structure: + +```json +{ + "$schema": "../i18n.schema.json", + "component_name": { + "some_action.label": "Some Action", + "some_action.title": "Performs some action", + "truncate_data.command": "Truncate Data", + "graph_edge.label": "{{start}} → {{end}}", + ... + }, + ... +} +``` + +Built-in translation bundles references the JSON schema to validate mistyped or unknown translation keys. +This schema is available as [`@reactodia/workspace/i18n/i18n.schema.json`](https://github.com/reactodia/reactodia-workspace/blob/master/i18n/i18n.schema.json) +and can be used with external JSON validation tool (e.g. [`ajv-cli`](https://github.com/ajv-validator/ajv-cli)) +to check the translations. + +To provide customized translation, additional bundles can be passed to +[`Workspace`](/docs/components/workspace.md) component with `translations` property: +```tsx +function TranslationOverride() { + return ( + + + + ); +} +``` + +Additional built-in or custom translation can be used the same way by loading the JSON bundle externally and +pass them with `translations` property in th order of the one with the high priority to low priority. +Default `en` translation (`@reactodia/workspace/i18n/translations/en.reactodia-translation.json`) is always +enabled as a fallback unless `useDefaultTranslation={false}` is specified: +```tsx +import enUkTranslation from './en-uk.reactodia-translation.json'; +import deTranslation from './de.reactodia-translation.json'; + +function MultipleTranslations() { + return ( + + + + ); +} +``` + +## Using translation in the custom components + +The localization mechanism can be used for a custom component nested inside the [`Workspace`](/docs/components/workspace.md) by getting a [`Translation`](/docs/api/workspace/interfaces/Translation.md) instance which can be used to format localizable strings. + +[`useTranslation()`](/docs/api/workspace/functions/useTranslation.md) hook can be used to acquire the `Translation` object; alternatively it is available as part of the [`WorkspaceContext`](/docs/concepts/workspace-context.md) via [`WorkspaceContext.translation`](/docs/api/workspace/interfaces/WorkspaceContext.md) property. + +In the following example, additional custom translation keys are added to the workspace to provide localizable component labels: +```tsx live noInline +function MyComponent() { + const t = Reactodia.useTranslation(); + return ( + alert('Done')}> + {t.text('my_component.do_action.label')} + + ); +} + +function CustomTranslationKeys() { + const {defaultLayout} = Reactodia.useWorker(Layouts); + return ( +
+ + } + /> + +
+ ); +} + +render(); +``` diff --git a/docs/concepts/layout-workers.md b/docs/concepts/layout-workers.md index 1e9fc2a4..c865907b 100644 --- a/docs/concepts/layout-workers.md +++ b/docs/concepts/layout-workers.md @@ -1,15 +1,18 @@ --- -sidebar_position: 8 +sidebar_position: 7 +title: Layout and Web Workers --- -# Layout and Web Workers +# Graph Layout and Web Workers -This page describes how Reactodia uses [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Worker) to perform non-blocking graph layout algorithm on the diagram content. +Reactodia uses [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Worker) to perform non-blocking [graph layout algorithms](https://en.wikipedia.org/wiki/Graph_drawing) on the diagram content. -API references: - - [calculateLayout](/docs/api/workspace/functions/calculateLayout) / [applyLayout](/docs/api/workspace/functions/applyLayout) - - [blockingDefaultLayout](/docs/api/workspace/functions/blockingDefaultLayout) - - [defineWorker](/docs/api/workspace/functions/defineWorker) - - [defineLayoutWorker](/docs/api/workspace/functions/defineLayoutWorker) and [DefaultLayouts](/docs/api/layout.worker/classes/DefaultLayouts) - - [useWorker](/docs/api/workspace/functions/useWorker) - - [connectWorker](/docs/api/worker-protocol/functions/connectWorker) +:::info +This section is incomplete, please look at the reference API documentation instead: + - [`calculateLayout()`](/docs/api/workspace/functions/calculateLayout) / [`applyLayout()`](/docs/api/workspace/functions/applyLayout) + - [`blockingDefaultLayout`](/docs/api/workspace/functions/blockingDefaultLayout) + - [`defineWorker()`](/docs/api/workspace/functions/defineWorker) + - [`defineLayoutWorker()`](/docs/api/workspace/functions/defineLayoutWorker) and [`DefaultLayouts`](/docs/api/layout.worker/classes/DefaultLayouts) + - [`useWorker()`](/docs/api/workspace/functions/useWorker) + - [`connectWorker()`](/docs/api/worker-protocol/functions/connectWorker) +::: diff --git a/docs/concepts/workspace-context.md b/docs/concepts/workspace-context.md index 7bee61c0..132a527f 100644 --- a/docs/concepts/workspace-context.md +++ b/docs/concepts/workspace-context.md @@ -4,15 +4,71 @@ sidebar_position: 5 # Workspace Context -This page describes common context for the Reactodia workspace components. - -API references: - - [WorkspaceContext](/docs/api/workspace/interfaces/WorkspaceContext) - - [useWorkspace](/docs/api/workspace/functions/useWorkspace) - - [DataDiagramModel](/docs/api/workspace/classes/DataDiagramModel) (extending [DiagramModel](/docs/api/workspace/classes/DiagramModel)) - - Read-only subset — [DataGraphStructure](/docs/api/workspace/interfaces/DataGraphStructure) (extending [GraphStructure](/docs/api/workspace/interfaces/GraphStructure)) - - [SharedCanvasState](/docs/api/workspace/classes/SharedCanvasState) - - [CanvasApi](/docs/api/workspace/interfaces/DataGraphStructure) - - [useCanvas](/docs/api/workspace/functions/useCanvas) - - [EditorController](/docs/api/workspace/classes/EditorController) - - [OverlayController](/docs/api/workspace/classes/OverlayController) +Reactodia uses a common context to connect its components with the [graph model](./graph-model.md) and other services such as [graph layout](./layout-workers.md), [i18n](./i18n.md) and [visual graph authoring](./graph-authoring.md). + +## Services and stores in the context + +The [`WorkspaceContext`](/docs/api/workspace/interfaces/WorkspaceContext) contains references to different services and state stores, here is the important ones: + +| Property name | Type | Description | +|---------------|------------------|-------------| +| `model` | [`DataDiagramModel`](/docs/api/workspace/classes/DataDiagramModel.md) | Stores the diagram content and asynchronously fetches from a data provider.
See [graph model](./graph-model.md). | +| `view` | [`SharedCanvasState`](/docs/api/workspace/classes/SharedCanvasState.md) | Stores common state and settings for all [canvases](/docs/components/canvas.md) in the workspace. | +| `editor` | [`EditorController`](/docs/api/workspace/classes/EditorController.md) | Stores, modifies and validates changes from the visual graph authoring.
See [graph authoring](./graph-authoring.md). | +| `overlay` | [`OverlayController`](/docs/api/workspace/classes/OverlayController.md) | Controls UI overlays for the canvases, including dialogs and tasks. | +| `translation` | [`Translation`](/docs/api/workspace/interfaces/Translation.md) | Provides a translation for UI text strings.
See [i18n](./i18n.md). | + +## Getting the workspace context + +The [`WorkspaceContext`](/docs/api/workspace/interfaces/WorkspaceContext) instance can be acquired in two ways. +The first one is from the result of `useLoadedWorkspace()` hook which is used for initialization of the [`Workspace`](/docs/components/workspace.md) component: + +```tsx +function Example() { + const {defaultLayout} = Reactodia.useWorker(Layouts); + + const {onMount, getContext} = Reactodia.useLoadedWorkspace(async ({context, signal}) => { + /* ... */ + }, []); + + const onSomething = () => { + const {model, editor, /* etc */} = getContext(); + // Use workspace context + }; + + return ( + + {/* ... */} + + ); +} +``` + +The second way is to use [`useWorkspace()`](/docs/api/workspace/functions/useWorkspace) hook inside the [`Workspace`](/docs/components/workspace.md) component itself, e.g. a canvas widget: + +```tsx +function MyWidget() { + const {model, editor, /* etc */} = Reactodia.useWorkspace(); + // Use workspace context +} + +Reactodia.defineCanvasWidget(MyWidget, element => ({element, attachment: 'viewport'})); + +function Example() { + const {defaultLayout} = Reactodia.useWorker(Layouts); + return ( + + ]} + /> + + ); +} +``` + +:::note +The library also uses separate context for [i18n](./i18n.md) (which is accessible by [`useTranslation()`](/docs/api/workspace/functions/useTranslation.md) hook and `translation` property of the workspace context) and a nested context for the [`Canvas`](/docs/components/canvas.md). +::: diff --git a/docs/examples/graph-authoring.mdx b/docs/examples/graph-authoring.mdx new file mode 100644 index 00000000..aa05397c --- /dev/null +++ b/docs/examples/graph-authoring.mdx @@ -0,0 +1,43 @@ +--- +sidebar_position: 4 +--- +import CodeBlock from '@theme/CodeBlock'; +import Link from '@docusaurus/Link'; + +# Graph Authoring + +Example demonstrating [visual graph authoring](/docs/concepts/graph-authoring) capabilities on in-memory RDF graph data. + +:::tip + +[▶︎ Open live demo](/playground/graph-authoring) + +::: + +import GraphAuthoringExampleSource from '!@site/src/examples/PlaygroundGraphAuthoring?raw'; +import ExampleMetadataSource from '!@site/src/examples/ExampleMetadata?raw'; +import ExampleCommonSource from '!@site/src/examples/ExampleCommon?raw'; + + + {GraphAuthoringExampleSource} + + +
+ ExampleMetadata.ts + + {ExampleMetadataSource} + +
+ +
+ ExampleCommon.tsx + + {ExampleCommonSource} + +
diff --git a/docs/examples/rdf.mdx b/docs/examples/rdf-explorer.mdx similarity index 66% rename from docs/examples/rdf.mdx rename to docs/examples/rdf-explorer.mdx index 7f637080..3601ac2d 100644 --- a/docs/examples/rdf.mdx +++ b/docs/examples/rdf-explorer.mdx @@ -4,24 +4,24 @@ sidebar_position: 3 import CodeBlock from '@theme/CodeBlock'; import Link from '@docusaurus/Link'; -# RDF Graph Authoring +# Graph Authoring -Example demonstrating working with in-memory RDF data and graph authoring capabilities. +Example demonstrating graph navigation and exploration capabilities using in-memory RDF [data provider](/docs/concepts/data-provider). :::tip -[▶︎ Open live demo](/playground/rdf) +[▶︎ Open live demo](/playground/rdf-explorer) ::: -import RdfExampleSource from '!@site/src/examples/PlaygroundRdf?raw'; +import RdfExplorerExampleSource from '!@site/src/examples/PlaygroundRdfExplorer?raw'; import ExampleMetadataSource from '!@site/src/examples/ExampleMetadata?raw'; import ExampleCommonSource from '!@site/src/examples/ExampleCommon?raw'; - {RdfExampleSource} + {RdfExplorerExampleSource}
diff --git a/docs/examples/sparql.mdx b/docs/examples/sparql.mdx index 97a2d64c..665fe490 100644 --- a/docs/examples/sparql.mdx +++ b/docs/examples/sparql.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 5 --- import CodeBlock from '@theme/CodeBlock'; import Link from '@docusaurus/Link'; diff --git a/docs/examples/stress-test.mdx b/docs/examples/stress-test.mdx index 5fa138bf..cf9d4386 100644 --- a/docs/examples/stress-test.mdx +++ b/docs/examples/stress-test.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +sidebar_position: 6 --- import CodeBlock from '@theme/CodeBlock'; import Link from '@docusaurus/Link'; diff --git a/docs/examples/wikidata.mdx b/docs/examples/wikidata.mdx index 960e47ee..2b7504de 100644 --- a/docs/examples/wikidata.mdx +++ b/docs/examples/wikidata.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 6 +sidebar_position: 7 --- import CodeBlock from '@theme/CodeBlock'; import Link from '@docusaurus/Link'; diff --git a/docusaurus.config.ts b/docusaurus.config.ts index b6a80201..55353dee 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -47,6 +47,7 @@ const config: Config = { plugins: [ './src/plugins/import-raw-source', + './src/plugins/configure-webpack', [ 'docusaurus-plugin-typedoc', { @@ -55,7 +56,7 @@ const config: Config = { '../reactodia-workspace/src/worker-protocol.ts', '../reactodia-workspace/src/layout.worker.ts', ], - tsconfig: '../reactodia-workspace/tsconfig.json', + tsconfig: '../reactodia-workspace/tsconfig.typings.json', readme: 'none', hideGroupHeadings: true, excludePrivate: true, @@ -102,7 +103,8 @@ const config: Config = { position: 'left', items: [ {to: '/playground/basic', label: 'Basic Workspace'}, - {to: '/playground/rdf', label: 'RDF Graph Authoring'}, + {to: '/playground/rdf-explorer', label: 'RDF Explorer'}, + {to: '/playground/graph-authoring', label: 'Graph Authoring'}, {to: '/playground/sparql', label: 'SPARQL Navigator'}, {to: '/playground/stress-test', label: 'Stress Test'}, {to: '/playground/wikidata', label: 'Wikidata Explorer'}, @@ -159,6 +161,7 @@ const config: Config = { prism: { theme: prismThemes.github, darkTheme: prismThemes.dracula, + additionalLanguages: ['json'], }, } satisfies Preset.ThemeConfig, }; diff --git a/package-lock.json b/package-lock.json index b5e3087b..3c52e6f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@docusaurus/preset-classic": "3.1.1", "@docusaurus/theme-live-codeblock": "^3.1.1", "@mdx-js/react": "^3.0.0", - "@reactodia/workspace": "^0.27.1", + "@reactodia/workspace": "^0.28.0", "clsx": "^2.0.0", "n3": "^1.17.2", "prism-react-renderer": "^2.3.0", @@ -25,6 +25,7 @@ "@docusaurus/types": "3.1.1", "@vscode/codicons": "^0.0.36", "docusaurus-plugin-typedoc": "^1.0.5", + "source-map-loader": "^5.0.0", "typedoc": "^0.26.6", "typedoc-plugin-markdown": "^4.2.6", "typescript": "~5.5.2" @@ -2904,9 +2905,9 @@ "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==" }, "node_modules/@reactodia/workspace": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@reactodia/workspace/-/workspace-0.27.1.tgz", - "integrity": "sha512-5HXntWIrroLAqNtxO/cnRsemyjK0jRxDt8jbNzDCJS2SVpJ/uqhiuFf6THUjxljjPsKDGC5//Bu83KNTswqmUg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@reactodia/workspace/-/workspace-0.28.0.tgz", + "integrity": "sha512-2C9HciYvSK8fUh9IWl9rylcYE15N5/vcdD5yIPbzRIyPloJbt8i86QpybHUkbCVrG3jdNYWGm4jRRlJfvmVhwA==", "dependencies": { "classnames": "^2.3.2", "d3-color": "^3.1.0", @@ -13330,6 +13331,38 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-5.0.0.tgz", + "integrity": "sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA==", + "dev": true, + "dependencies": { + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.72.1" + } + }, + "node_modules/source-map-loader/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", diff --git a/package.json b/package.json index fd0dd7d9..e0ca4646 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "@docusaurus/preset-classic": "3.1.1", "@docusaurus/theme-live-codeblock": "^3.1.1", "@mdx-js/react": "^3.0.0", - "@reactodia/workspace": "^0.27.1", + "@reactodia/workspace": "^0.28.0", "clsx": "^2.0.0", "n3": "^1.17.2", "prism-react-renderer": "^2.3.0", @@ -32,6 +32,7 @@ "@docusaurus/types": "3.1.1", "@vscode/codicons": "^0.0.36", "docusaurus-plugin-typedoc": "^1.0.5", + "source-map-loader": "^5.0.0", "typedoc": "^0.26.6", "typedoc-plugin-markdown": "^4.2.6", "typescript": "~5.5.2" diff --git a/src/components/ButtonToggle/index.tsx b/src/components/ButtonToggle/index.tsx new file mode 100644 index 00000000..f8c17c25 --- /dev/null +++ b/src/components/ButtonToggle/index.tsx @@ -0,0 +1,19 @@ +export function ButtonToggle(props: { + states: readonly string[]; + value: string; + onChange: (nextValue: string) => void; +}) { + const {states, value, onChange} = props; + return ( +
+ {states.map(state => + + )} +
+ ); +} diff --git a/src/components/ColorBoxes/index.tsx b/src/components/ColorBoxes/index.tsx new file mode 100644 index 00000000..bf6fc449 --- /dev/null +++ b/src/components/ColorBoxes/index.tsx @@ -0,0 +1,15 @@ +import styles from './styles.module.css'; + +export function ColorBoxes(props: { colors: readonly string[] }) { + const {colors} = props; + return ( +
+ {colors.map(color => ( +
+ ))} +
+ ); +} diff --git a/src/components/ColorBoxes/styles.module.css b/src/components/ColorBoxes/styles.module.css new file mode 100644 index 00000000..73240629 --- /dev/null +++ b/src/components/ColorBoxes/styles.module.css @@ -0,0 +1,12 @@ +.component { + display: inline-flex; + flex-wrap: wrap; + gap: 5px; + margin-bottom: 5px; +} + +.component > * { + width: 64px; + height: 64px; + box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px; +} diff --git a/src/css/custom.css b/src/css/custom.css index c686d103..a6dca9fe 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -33,7 +33,7 @@ /* Add alpha symbol after "Docs" link in the header */ a.navbar__item.navbar__link[href="/docs/"]::after, a.menu__link[href="/docs/"]::after { - content: 'α'; + content: 'β'; margin-left: 5px; vertical-align: super; font-size: 12px; @@ -49,5 +49,4 @@ aside a.menu__link[href="/docs/"]::after, /* Style for displaying Reactodia from live editor code block */ .reactodia-live-editor .reactodia-workspace { height: var(--inline-reactodia-height); - background: white; } diff --git a/src/examples/ExampleMetadata.ts b/src/examples/ExampleMetadata.ts index b406a770..e9cf69a8 100644 --- a/src/examples/ExampleMetadata.ts +++ b/src/examples/ExampleMetadata.ts @@ -1,230 +1,234 @@ import * as Reactodia from '@reactodia/workspace'; const owl = vocabulary('http://www.w3.org/2002/07/owl#', [ - 'Class', - 'AnnotationProperty', - 'DatatypeProperty', - 'ObjectProperty', - 'domain', - 'range', + 'Class', + 'AnnotationProperty', + 'DatatypeProperty', + 'ObjectProperty', ]); const rdfs = vocabulary('http://www.w3.org/2000/01/rdf-schema#', [ - 'subClassOf', - 'subPropertyOf', + 'comment', + 'domain', + 'range', + 'seeAlso', + 'subClassOf', + 'subPropertyOf', ]); const SIMULATED_DELAY: number = 200; /* ms */ export class ExampleMetadataProvider implements Reactodia.MetadataProvider { - private readonly propertyTypes = [owl.AnnotationProperty, owl.DatatypeProperty, owl.ObjectProperty]; - private readonly editableTypes = new Set([owl.Class, ...this.propertyTypes]); - - async createEntity( - type: Reactodia.ElementTypeIri, - options: { readonly signal?: AbortSignal } - ): Promise { - await delay(SIMULATED_DELAY, options.signal); - const random32BitDigits = Math.floor((1 + Math.random()) * 0x100000000).toString(16).substring(1); - const typeLabel = Reactodia.Rdf.getLocalName(type) ?? 'Entity'; - return { - id: `${type}_${random32BitDigits}` as Reactodia.ElementIri, - types: [type], - label: [Reactodia.Rdf.DefaultDataFactory.literal(`New ${typeLabel}`)], - properties: {}, - }; + private readonly propertyTypes = [owl.AnnotationProperty, owl.DatatypeProperty, owl.ObjectProperty]; + private readonly editableTypes = new Set([owl.Class, ...this.propertyTypes]); + private readonly literalLanguages: ReadonlyArray = ['de', 'en', 'es', 'ru', 'zh']; + + getLiteralLanguages(): ReadonlyArray { + return this.literalLanguages; + } + + async createEntity( + type: Reactodia.ElementTypeIri, + options: { readonly signal?: AbortSignal } + ): Promise { + await Reactodia.delay(SIMULATED_DELAY, {signal: options.signal}); + const random32BitDigits = Math.floor((1 + Math.random()) * 0x100000000).toString(16).substring(1); + const typeLabel = Reactodia.Rdf.getLocalName(type) ?? 'Entity'; + return { + id: `${type}_${random32BitDigits}` as Reactodia.ElementIri, + types: [type], + label: [Reactodia.Rdf.DefaultDataFactory.literal(`New ${typeLabel}`)], + properties: {}, + }; + } + + async createRelation( + source: Reactodia.ElementModel, + target: Reactodia.ElementModel, + linkType: Reactodia.LinkTypeIri, + options: { readonly signal?: AbortSignal } + ): Promise { + await Reactodia.delay(SIMULATED_DELAY, {signal: options.signal}); + return { + sourceId: source.id, + targetId: target.id, + linkTypeId: linkType, + properties: {}, + }; + } + + async canConnect( + source: Reactodia.ElementModel, + target: Reactodia.ElementModel | undefined, + linkType: Reactodia.LinkTypeIri | undefined, + options: { readonly signal?: AbortSignal } + ): Promise { + await Reactodia.delay(SIMULATED_DELAY, {signal: options.signal}); + + const connections: Reactodia.MetadataCanConnect[] = []; + const addConnections = ( + types: readonly Reactodia.ElementTypeIri[], + allOutLinks: readonly Reactodia.LinkTypeIri[], + allInLinks: readonly Reactodia.LinkTypeIri[] + ) => { + const outLinks = linkType + ? allOutLinks.filter(type => type === linkType) + : allOutLinks; + const inLinks = linkType + ? allInLinks.filter(type => type === linkType) + : allInLinks; + if (types.length > 0 && (outLinks.length > 0 || inLinks.length > 0)) { + connections.push({ targetTypes: new Set(types), outLinks, inLinks }); + } + }; + + if (hasType(source, owl.Class)) { + if (hasType(target, owl.Class)) { + addConnections([owl.Class], [rdfs.subClassOf], [rdfs.subClassOf]); + } + + const targetPropertyTypes = this.propertyTypes.filter(type => hasType(target, type)); + if (targetPropertyTypes.length > 0) { + addConnections(targetPropertyTypes, [], [rdfs.domain, rdfs.range]); + } } - async createRelation( - source: Reactodia.ElementModel, - target: Reactodia.ElementModel, - linkType: Reactodia.LinkTypeIri, - options: { readonly signal?: AbortSignal } - ): Promise { - await delay(SIMULATED_DELAY, options.signal); - return { - sourceId: source.id, - targetId: target.id, - linkTypeId: linkType, - properties: {}, - }; - } - - async canConnect( - source: Reactodia.ElementModel, - target: Reactodia.ElementModel | undefined, - linkType: Reactodia.LinkTypeIri | undefined, - options: { readonly signal?: AbortSignal } - ): Promise { - await delay(SIMULATED_DELAY, options.signal); - - const connections: Reactodia.MetadataCanConnect[] = []; - const addConnections = ( - types: readonly Reactodia.ElementTypeIri[], - allOutLinks: readonly Reactodia.LinkTypeIri[], - allInLinks: readonly Reactodia.LinkTypeIri[] - ) => { - const outLinks = linkType - ? allOutLinks.filter(type => type === linkType) - : allOutLinks; - const inLinks = linkType - ? allInLinks.filter(type => type === linkType) - : allInLinks; - if (types.length > 0 && (outLinks.length > 0 || inLinks.length > 0)) { - connections.push({targetTypes: new Set(types), outLinks, inLinks}); - } - }; - - if (hasType(source, owl.Class)) { - if (hasType(target, owl.Class)) { - addConnections([owl.Class], [rdfs.subClassOf], [rdfs.subClassOf]); - } - - const targetPropertyTypes = this.propertyTypes.filter(type => hasType(target, type)); - if (targetPropertyTypes.length > 0) { - addConnections(targetPropertyTypes, [], [owl.domain, owl.range]); - } - } - - const sourcePropertyTypes = this.propertyTypes.filter(type => hasType(source, type)); - if (sourcePropertyTypes.length > 0) { - for (const type of sourcePropertyTypes) { - if (hasType(target, type)) { - addConnections([type], [rdfs.subPropertyOf], [rdfs.subPropertyOf]); - } - } - - if (hasType(target, owl.Class)) { - addConnections([owl.Class], [owl.domain, owl.range], []); - } + const sourcePropertyTypes = this.propertyTypes.filter(type => hasType(source, type)); + if (sourcePropertyTypes.length > 0) { + for (const type of sourcePropertyTypes) { + if (hasType(target, type)) { + addConnections([type], [rdfs.subPropertyOf], [rdfs.subPropertyOf]); } + } - return connections; - } - - async canModifyEntity( - entity: Reactodia.ElementModel, - options: { readonly signal?: AbortSignal; } - ): Promise { - await delay(SIMULATED_DELAY, options.signal); - const editable = entity.types.some(type => this.editableTypes.has(type)); - return { - canChangeIri: entity.types.includes(owl.Class), - canEdit: editable, - canDelete: editable, - }; - } - - async canModifyRelation( - link: Reactodia.LinkModel, - source: Reactodia.ElementModel, - target: Reactodia.ElementModel, - options: { readonly signal?: AbortSignal; } - ): Promise { - await delay(SIMULATED_DELAY, options.signal); - switch (link.linkTypeId) { - case owl.domain: - case owl.range: - case rdfs.subClassOf: - case rdfs.subPropertyOf: { - return { - canChangeType: true, - canDelete: true, - }; - } - default: { - return {}; - } - } + if (hasType(target, owl.Class)) { + addConnections([owl.Class], [rdfs.domain, rdfs.range], []); + } } - async getEntityTypeShape( - type: Reactodia.ElementTypeIri, - options: { readonly signal?: AbortSignal; } - ): Promise { - await delay(SIMULATED_DELAY, options.signal); + return connections; + } + + async canModifyEntity( + entity: Reactodia.ElementModel, + options: { readonly signal?: AbortSignal; } + ): Promise { + await Reactodia.delay(SIMULATED_DELAY, {signal: options.signal}); + const editable = entity.types.some(type => this.editableTypes.has(type)); + return { + canChangeIri: entity.types.includes(owl.Class), + canEdit: editable, + canDelete: editable, + }; + } + + async canModifyRelation( + link: Reactodia.LinkModel, + source: Reactodia.ElementModel, + target: Reactodia.ElementModel, + options: { readonly signal?: AbortSignal; } + ): Promise { + await Reactodia.delay(SIMULATED_DELAY, {signal: options.signal}); + switch (link.linkTypeId) { + case rdfs.domain: + case rdfs.range: + case rdfs.subClassOf: + case rdfs.subPropertyOf: { return { - properties: [], + canChangeType: true, + canDelete: true, }; + } + default: { + return {}; + } } - - async filterConstructibleTypes( - types: ReadonlySet, - options: { readonly signal?: AbortSignal } - ): Promise> { - await delay(SIMULATED_DELAY, options.signal); - return new Set(Array.from(types).filter(type => this.editableTypes.has(type))); + } + + async getEntityShape( + types: ReadonlyArray, + options: { readonly signal?: AbortSignal; } + ): Promise { + await Reactodia.delay(SIMULATED_DELAY, {signal: options.signal}); + const properties = new Map(); + if (types.some(type => this.editableTypes.has(type))) { + properties.set(rdfs.comment, { + valueShape: {termType: 'Literal'}, + }); + properties.set(rdfs.seeAlso, { + valueShape: {termType: 'NamedNode'}, + }); } + return {properties}; + } + + async filterConstructibleTypes( + types: ReadonlySet, + options: { readonly signal?: AbortSignal } + ): Promise> { + await Reactodia.delay(SIMULATED_DELAY, {signal: options.signal}); + return new Set(Array.from(types).filter(type => this.editableTypes.has(type))); + } } export class ExampleValidationProvider implements Reactodia.ValidationProvider { - async validate( - event: Reactodia.ValidationEvent - ): Promise { - const items: Array = []; - - if (event.target.types.includes(owl.Class)) { - event.state.links.forEach(e => { - if (e.type === 'relationAdd' && e.data.sourceId === event.target.id) { - items.push({ - type: 'link', - target: e.data, - severity: 'error', - message: 'Cannot add any new link from a Class', - }); - items.push({ - type: 'element', - target: event.target.id, - severity: 'warning', - message: `Cannot create <${e.data.linkTypeId}> link from a Class`, - }); - } - }); - } - - if (event.target.types.includes(owl.ObjectProperty)) { - if (!event.outboundLinks.some(link => link.linkTypeId === rdfs.subPropertyOf)) { - items.push({ - type: 'element', - target: event.target.id, - severity: 'info', - message: 'It might be a good idea to make the property a sub-property of another', - }); - } + async validate( + event: Reactodia.ValidationEvent + ): Promise { + const items: Array = []; + + if (event.target.types.includes(owl.Class)) { + event.state.links.forEach(e => { + if (e.type === 'relationAdd' && e.data.sourceId === event.target.id) { + items.push({ + type: 'link', + target: e.data, + severity: 'error', + message: 'Cannot add any new link from a Class', + }); + items.push({ + type: 'element', + target: event.target.id, + severity: 'warning', + message: `Cannot create <${e.data.linkTypeId}> link from a Class`, + }); } - - await delay(SIMULATED_DELAY, event.signal); - return {items}; + }); } -} - -async function delay(amountMs: number, ct: AbortSignal | undefined) { - ct?.throwIfAborted(); - await waitTimeout(amountMs); - ct?.throwIfAborted(); -} -function waitTimeout(amountMs: number): Promise { - if (amountMs === 0) { - return Promise.resolve(); + if (event.target.types.includes(owl.ObjectProperty)) { + if (!event.outboundLinks.some(link => link.linkTypeId === rdfs.subPropertyOf)) { + items.push({ + type: 'element', + target: event.target.id, + severity: 'info', + message: 'It might be a good idea to make the property a sub-property of another', + }); + } } - return new Promise(resolve => setTimeout(resolve, amountMs)); + + await Reactodia.delay(SIMULATED_DELAY, {signal: event.signal}); + return {items}; + } } type VocabularyKeyType = - K extends Capitalize ? Reactodia.ElementTypeIri : Reactodia.LinkTypeIri; + K extends Capitalize + ? Reactodia.ElementTypeIri + : Reactodia.LinkTypeIri & Reactodia.PropertyTypeIri; + type Vocabulary = { - readonly [K in Keys[number]]: VocabularyKeyType; + readonly [K in Keys[number]]: VocabularyKeyType; }; function vocabulary(prefix: string, keys: Keys): Vocabulary { - const result: { [key: string]: string } = Object.create(null); - for (const key of keys) { - result[key] = prefix + key; - } - return result as Vocabulary; + const result: { [key: string]: string } = Object.create(null); + for (const key of keys) { + result[key] = prefix + key; + } + return result as Vocabulary; } function hasType(model: Reactodia.ElementModel | undefined, type: Reactodia.ElementTypeIri) { - return Boolean(!model || model.types.find(t => t === type)); + return Boolean(!model || model.types.includes(type)); } diff --git a/src/examples/PlaygroundBasic.tsx b/src/examples/PlaygroundBasic.tsx index 6225db68..ae536851 100644 --- a/src/examples/PlaygroundBasic.tsx +++ b/src/examples/PlaygroundBasic.tsx @@ -7,9 +7,7 @@ const Layouts = Reactodia.defineLayoutWorker(() => new Worker( )); export function PlaygroundBasic() { - const GRAPH_DATA = - 'https://raw.githubusercontent.com/reactodia/reactodia-workspace/' + - 'master/examples/resources/orgOntology.ttl'; + const GRAPH_DATA = 'https://reactodia.github.io/resources/orgOntology.ttl'; const {defaultLayout} = Reactodia.useWorker(Layouts); diff --git a/src/examples/PlaygroundClassicWorkspace.tsx b/src/examples/PlaygroundClassicWorkspace.tsx index 7a421bfc..23ca823a 100644 --- a/src/examples/PlaygroundClassicWorkspace.tsx +++ b/src/examples/PlaygroundClassicWorkspace.tsx @@ -17,9 +17,7 @@ export function PlaygroundClassicWorkspace() { const [dataSource, setDataSource] = React.useState({ type: 'url', - url: - 'https://raw.githubusercontent.com/reactodia/reactodia-workspace/' + - 'master/examples/resources/orgOntology.ttl' + url: 'https://reactodia.github.io/resources/orgOntology.ttl', }); const [searchCommands] = React.useState(() => new Reactodia.EventSource diff --git a/src/examples/PlaygroundRdf.tsx b/src/examples/PlaygroundGraphAuthoring.tsx similarity index 74% rename from src/examples/PlaygroundRdf.tsx rename to src/examples/PlaygroundGraphAuthoring.tsx index 1f03b991..cf6bc606 100644 --- a/src/examples/PlaygroundRdf.tsx +++ b/src/examples/PlaygroundGraphAuthoring.tsx @@ -13,21 +13,19 @@ type TurtleDataSource = | { type: 'url'; url: string } | { type: 'data'; data: string }; -export function PlaygroundRdf() { +export function PlaygroundGraphAuthoring() { const {defaultLayout} = Reactodia.useWorker(Layouts); const [dataSource, setDataSource] = React.useState({ type: 'url', - url: - 'https://raw.githubusercontent.com/reactodia/reactodia-workspace/' + - 'master/examples/resources/orgOntology.ttl' + url: 'https://reactodia.github.io/resources/orgOntology.ttl', }); const [searchCommands] = React.useState(() => new Reactodia.EventSource ); const {onMount} = Reactodia.useLoadedWorkspace(async ({context, signal}) => { - const {model, editor} = context; + const {model, editor, performLayout} = context; editor.setAuthoringMode(true); let turtleData: string; @@ -47,7 +45,24 @@ export function PlaygroundRdf() { await model.importLayout({dataProvider, signal}); - searchCommands.trigger('focus', {sectionKey: 'elementTypes'}); + if (dataSource.type === 'url') { + const elements = [ + model.createElement('http://www.w3.org/ns/org#Organization'), + model.createElement('http://www.w3.org/ns/org#FormalOrganization'), + model.createElement('http://www.w3.org/ns/org#hasMember'), + model.createElement('http://www.w3.org/ns/org#hasSubOrganization'), + model.createElement('http://www.w3.org/ns/org#subOrganizationOf'), + model.createElement('http://www.w3.org/ns/org#unitOf'), + ]; + model.history.execute(Reactodia.setElementExpanded(elements[0], true)); + await Promise.all([ + model.requestElementData(elements.map(el => el.iri)), + model.requestLinks(), + ]); + await performLayout({signal}); + } else { + searchCommands.trigger('focus', {sectionKey: 'elementTypes'}); + } }, [dataSource]); const [metadataProvider] = React.useState(() => new ExampleMetadataProvider()); @@ -89,11 +104,9 @@ class RenameSubclassOfProvider extends Reactodia.RenameLinkToLinkStateProvider { } } -interface ToolbarActionOpenTurtleGraphProps { +function ToolbarActionOpenTurtleGraph(props: { onOpen: (dataSource: TurtleDataSource) => void; -} - -function ToolbarActionOpenTurtleGraph(props: ToolbarActionOpenTurtleGraphProps) { +}) { const {onOpen} = props; return ( new Worker( + new URL('@reactodia/workspace/layout.worker', import.meta.url) +)); + +type TurtleDataSource = + | { type: 'url'; url: string } + | { type: 'data'; data: string }; + +export function PlaygroundRdfExplorer() { + const {defaultLayout} = Reactodia.useWorker(Layouts); + + const [dataSource, setDataSource] = React.useState({ + type: 'url', + url: 'https://reactodia.github.io/resources/orgOntology.ttl', + }); + const [searchCommands] = React.useState(() => + new Reactodia.EventSource + ); + + const {onMount} = Reactodia.useLoadedWorkspace(async ({context, signal}) => { + const {model} = context; + + let turtleData: string; + if (dataSource.type === 'url') { + const response = await fetch(dataSource.url, {signal}); + turtleData = await response.text(); + } else { + turtleData = dataSource.data; + } + + const dataProvider = new Reactodia.RdfDataProvider(); + try { + dataProvider.addGraph(new N3.Parser().parse(turtleData)); + } catch (err) { + throw new Error('Error parsing RDF graph data', {cause: err}); + } + + await model.importLayout({dataProvider, signal}); + + searchCommands.trigger('focus', {sectionKey: 'elementTypes'}); + }, [dataSource]); + + return ( + window.open(iri)}> + + + + + } + searchCommands={searchCommands} + languages={[ + {code: 'de', label: 'Deutsch'}, + {code: 'en', label: 'english'}, + {code: 'es', label: 'español'}, + {code: 'ru', label: 'русский'}, + {code: 'zh', label: '汉语'}, + ]} + /> + + ); +} + +function ToolbarActionOpenTurtleGraph(props: { + onOpen: (dataSource: TurtleDataSource) => void; +}) { + const {onOpen} = props; + return ( + { + const turtleText = await file.text(); + onOpen({type: 'data', data: turtleText}); + }}> + Load RDF (Turtle) data + + ); +} diff --git a/src/pages/live-demo/rdf.tsx b/src/pages/live-demo/rdf.tsx index 58f8ff20..3d2d4ca7 100644 --- a/src/pages/live-demo/rdf.tsx +++ b/src/pages/live-demo/rdf.tsx @@ -1,5 +1,5 @@ import { Redirect } from '@docusaurus/router'; export default function Page(): JSX.Element { - return ; + return ; } diff --git a/src/pages/playground/graph-authoring.tsx b/src/pages/playground/graph-authoring.tsx new file mode 100644 index 00000000..f36e50ca --- /dev/null +++ b/src/pages/playground/graph-authoring.tsx @@ -0,0 +1,27 @@ +import BrowserOnly from '@docusaurus/BrowserOnly'; +import Layout from '@theme/Layout'; +import { InlineReactodia, InlineReactodiaHead } from '@site/src/components/InlineReactodia'; +import { ViewSource } from '@site/src/components/ViewSource'; + +export default function Example(): JSX.Element { + return ( + <> + + + + {() => { + const {PlaygroundGraphAuthoring} = require('@site/src/examples/PlaygroundGraphAuthoring') as + typeof import('@site/src/examples/PlaygroundGraphAuthoring'); + return ( + + + + ); + }} + + + + + ); +} diff --git a/src/pages/playground/rdf.tsx b/src/pages/playground/rdf-explorer.tsx similarity index 64% rename from src/pages/playground/rdf.tsx rename to src/pages/playground/rdf-explorer.tsx index 7a85624c..a6af0135 100644 --- a/src/pages/playground/rdf.tsx +++ b/src/pages/playground/rdf-explorer.tsx @@ -7,20 +7,20 @@ export default function Example(): JSX.Element { return ( <> - {() => { - const {PlaygroundRdf} = require('@site/src/examples/PlaygroundRdf') as - typeof import('@site/src/examples/PlaygroundRdf'); + const {PlaygroundRdfExplorer} = require('@site/src/examples/PlaygroundRdfExplorer') as + typeof import('@site/src/examples/PlaygroundRdfExplorer'); return ( - + ); }} - + ); diff --git a/src/plugins/configure-webpack/index.js b/src/plugins/configure-webpack/index.js new file mode 100644 index 00000000..2020e7c1 --- /dev/null +++ b/src/plugins/configure-webpack/index.js @@ -0,0 +1,28 @@ +export default async function importRawSource(context, opts) { + return { + // A compulsory field used as the namespace for directories to cache + // the intermediate data for each plugin. + // If you're writing your own local plugin, you will want it to + // be unique in order not to potentially conflict with imported plugins. + // A good way will be to add your own project name within. + name: 'docusaurus-reactodia-configure-webpack', + + configureWebpack(config, isServer, utils) { + return { + module: { + rules: [ + { + test: /\.js$/, + enforce: "pre", + use: [ + { + loader: 'source-map-loader', + } + ] + }, + ], + }, + }; + } + } +} diff --git a/static/resources/orgOntology.ttl b/static/resources/orgOntology.ttl new file mode 100644 index 00000000..bf1d75e9 --- /dev/null +++ b/static/resources/orgOntology.ttl @@ -0,0 +1,1059 @@ +@prefix rdf: . +@prefix rdfs: . +@prefix owl: . +@prefix xsd: . +@prefix skos: . +@prefix foaf: . +@prefix dct: . +@prefix gr: . +@prefix owlTime: . +@prefix org: . +@prefix vcard: . +@prefix prov: . +@prefix : . + + +# -- Meta data ----------------------------------------------------------- + + + + + a owl:Ontology; + + owl:versionInfo "0.8"; + + rdfs:label "Core organization ontology"@en; + rdfs:label "Ontologie des organisations"@fr; + rdfs:label "Ontologia delle organizzazioni"@it; + rdfs:label "Ontología de organizaciones"@es; + + rdfs:comment "Vocabulary for describing organizational structures, specializable to a broad variety of types of organization."@en; + rdfs:comment "Vocabolario per descrivere strutture organizzative, le quali possono essere specializzate in una vasta varietà di tipi di organizzazione"@it; + rdfs:comment "Vocabulario para describir organizaciones, adaptable a una amplia variedad de ellas."@es; + + dct:created "2010-05-28"^^xsd:date; + dct:modified "2010-06-09"^^xsd:date; + dct:modified "2010-10-08"^^xsd:date; + dct:modified "2012-09-30"^^xsd:date; + dct:modified "2012-10-06"^^xsd:date; + dct:modified "2013-02-15"^^xsd:date; + dct:modified "2013-12-16"^^xsd:date; + dct:modified "2014-01-02"^^xsd:date; # added Italian translation, PhilA. + dct:modified "2014-01-25"^^xsd:date; # Erratas: http://lists.w3.org/Archives/Public/public-gld-comments/2014Jan/0000.html + dct:modified "2014-02-05"^^xsd:date; # added Japanese comments, PhilA. + dct:modified "2014-04-12"^^xsd:date; # Added Spanish translation Guadalupe Aguado, Elena Montiel, Olga Giraldo and María Poveda from Ontology Engineering Group + + + dct:title "Core organization ontology"@en; + dct:title "Ontologie des organisations"@fr; + dct:title "Ontologia delle organizzazioni"@it; + dct:title "Ontología de organizaciones"@es; + + dct:contributor [foaf:mbox "dave@epimorphics.com"; foaf:name "Dave Reynolds"]; + + dct:contributor [foaf:mbox "dguardiola@quinode.fr"; foaf:name "Dominique Guardiola"], + [foaf:mbox "antonio.maccioni@agid.gov.it"; foaf:name "Antonio Maccioni"], + [foaf:mbox "giorgia.lodi@agid.gov.it"; foaf:name "Giorgia Lodi"], + [foaf:name "Shuji Kamitsuna"; foaf:homepage ]; + dct:contributor [foaf:mbox "lupe@fi.upm.es"; foaf:name "Guadalupe Aguado de Cea"]; + dct:contributor [foaf:mbox "emontiel@fi.upm.es"; foaf:name "Elena Montiel Ponsoda"]; + dct:contributor [foaf:mbox "ogiraldo@fi.upm.es"; foaf:name "Olga Ximena Giraldo"]; + dct:contributor [foaf:mbox "mpoveda@fi.upm.es"; foaf:name "María Poveda Villalón"]; ; + + dct:license ; + rdfs:seeAlso ; + . + +# -- Organizational structure ----------------------------------------------------------- + +org:Organization a owl:Class, rdfs:Class; + rdfs:subClassOf foaf:Agent; + owl:equivalentClass foaf:Organization; + rdfs:label "Organization"@en; + rdfs:label "Organisation"@fr; + rdfs:label "Organizzazione"@it; + + owl:hasKey (org:identifier) ; + rdfs:comment """Represents a collection of people organized together into a community or other social, commercial or political structure. The group has some common purpose or reason for existence which goes beyond the set of people belonging to it and can act as an Agent. Organizations are often decomposable into hierarchical structures. It is recommended that SKOS lexical labels should be used to label the Organization. In particular `skos:prefLabel` for the primary (possibly legally recognized name), `skos:altLabel` for alternative names (trading names, colloquial names) and `skos:notation` to denote a code from a code list. Alternative names: _Collective_ _Body_ _Org_ _Group_"""@en; + rdfs:comment """Représente un groupe de personnes organisées en communauté où tout autre forme de structure sociale, commerciale ou politique. Le groupe a un but commun ou une raison d'être qui va au-delà de la somme des personnes qui en font partie et peut agir en tant que "Agent". Les organisations sont souvent décomposables en structures hiérarchisées. Il est recommandé que des labels lexicaux SKOS soient utilisés pour nommer l'Organisation. En particulier `skos:prefLabel` pour le nom principal (en général le nom légal), `skos:altLabel` pour les noms alternatifs (marques, sigles, appellations familières) et `skos:notation` pour indiquer un code provenant d'une liste de code."""@fr; + rdfs:comment """Rappresenta una collezione di persone organizzate all'interno di una communità o di una qualche struttura sociale, commerciale o politica. Il gruppo condivide un obiettivo o una ragione d'essere che va oltre gli stessi membri appartenenti al gruppo e può agire come un Agent. Le organizzazioni si possono spesso suddividere in strutture gerarchiche. Si raccomanda di usare le label per l'Organization mediante le proprietà di SKOS. In particolare, `skos:prefLabel` per il nome principale (possibilmente un nome legalmente riconosciuto)”, `skos:altLabel` come nome alternativo (denominazione commerciale, denominazione colloquiale) e `skos:notation` per indicare un codice di una lista di codici."""@it; + rdfs:comment "コミュニティー、その他の社会、商業、政治的な構造に共に編入された人々の集合を表わします。グループには、そこに属する人々を超えた、存在に対するある共通の目的や理由があり、エージェント(代理)を務めることができます。組織は、多くの場合、階層構造に分割できます。"@ja; + rdfs:isDefinedBy ; + . + +org:Organization rdfs:label "organización"@es ; + rdfs:comment "Grupo de personas que se organiza en una comunidad u otro tipo de estructura social, comercial o política. Dicho grupo tiene un objetivo o motivo común para su existencia que va más allá del conjunto de personas que lo forman y que puede actuar como “agente”. A menudo las organizaciones se pueden agrupar en estructuras jerárquicas. Se recomienda el uso de etiquetas de SKOS para denominar a cada “organización”. En concreto, `skos:prefLabel` para la denominación principal o recomendada (aquella reconocida legalmente, siempre que sea posible), `skos:altLabel` para denominaciones alternativas (nombre comercial, sigla, denominación por la que se conoce a la organización coloquialmente) y `skos:notation` para referirse al código que identifique a la organización en una lista de códigos. Denominaciones alternativas: _colectivo_ _corporación_ _grupo_"@es . + +org:FormalOrganization a owl:Class, rdfs:Class; + + rdfs:subClassOf org:Organization, foaf:Organization; + rdfs:label "Formal Organization"@en; + rdfs:label "Organisation Formelle"@fr; + rdfs:label "Organizzazione formale"@it; + + rdfs:comment """An Organization which is recognized in the world at large, in particular in legal jurisdictions, with associated rights and responsibilities. Examples include a Corporation, Charity, Government or Church. Note that this is a super class of `gr:BusinessEntity` and it is recommended to use the GoodRelations vocabulary to denote Business classifications such as DUNS or NAICS."""@en; + rdfs:comment """Une Organisation reconnue, en particulier par les juridictions locales, ayant des droits et des responsabilités. Exemples : entreprises, association à but non-lucratif, collectivité, église. Notez que c'est une super-classe de `gr:BusinessEntity` et qu'il est recommandé d'utiliser le vocabulaire GoodRelations pour indiquer les classifications économiques comme le code NACE."""@fr; + rdfs:comment """Un'organizzazione che è riconosciuta a livello mondiale o, in generale, all'interno di una qualche giurisdizione, e che quindi possiede diritti e responsabilità. Ad esempio aziende, enti governativi, associazioni di volontariato. Si noti che questa è una superclasse di `gr:BusinessEntity` e che quindi è raccomandabile usare il vocabolario GoodRelations per esprimere classificazioni di tipo industriale e commerciale come DUNS e NAICS."""@it; + rdfs:comment "関連する権利と責任を有する(特に法的管轄区域において)世界中に広く認識されている組織。例には、企業、慈善団体、政府や教会が含まれます。"@ja; + rdfs:isDefinedBy ; + . + +org:FormalOrganization rdfs:label "organización formal"@es ; + rdfs:comment "Organización reconocida a nivel mundial, en particular en jurisdicciones legales, con derechos y responsabilidades asociadas. Algunos ejemplos son: organización corporativa, organización benéfica, organización gubernamental, organización religiosa. Se debe tener en cuenta que ésta es una superclase de `gr:BusinessEntity` y que se recomienda el uso del vocabulario GoodRelations para referirse a clasificaciones de negocios tales como DUNS o NAICS."@es . + +gr:BusinessEntity rdfs:subClassOf org:FormalOrganization . + +org:OrganizationalUnit a owl:Class, rdfs:Class; + rdfs:subClassOf org:Organization; + + rdfs:label "OrganizationalUnit"@en; + rdfs:label "Unité opérationnelle"@fr; + rdfs:label "Unità Organizzativa"@it; + + rdfs:comment """An Organization such as a University Support Unit which is part of some larger FormalOrganization and only has full recognition within the context of that FormalOrganization, it is not a Legal Entity in its own right. Units can be large and complex containing other Units and even FormalOrganizations. Alternative names: _OU_ _Unit_ _Department_"""@en; + rdfs:comment """Une organisation telle que le support informatique d'une université, qui fait partie d'une Organisation Formelle plus importante et qui ne peut être reconnue qu'en tant que membre de cette organisation supérieure, ce n'est pas une entité légale en elle-même. Les unités opérationnelles peuvent être étendues, complexes et inclure elles-mêmes d'autres branches ou Unités Opérationnelles, voire des Organisations Formelles."""@fr; + rdfs:comment """Un'organizzazione come ad esempio l'unità dei sistemi informativi che è parte di una più grande FormalOrganization e che, pur essendo riconosciuta nel contesto della propria organizzazione di riferimento, non è legalmente riconosciuta come entità a sé stante. Le unità possono essere ampie e complesse e contenere al loro interno sia altre unità che addirittura FormalOrganization."""@it; + rdfs:comment "あるより大きな組織の一部であり、その組織の中においてのみ完全に認識される部局や支援部署などの組織です。特に、その単位はそれ自体では法的実体と見なされません。"@ja; + rdfs:isDefinedBy ; + . + +org:OrganizationalUnit rdfs:label "unidad organizativa"@es ; + rdfs:comment "Organización que forma parte de una organización formal más amplia, como el servicio de informática o centro de cálculo de una universidad, y que sólo tiene reconocimiento pleno en el contexto de dicha organización formal, pero que no es una entidad legal propiamente dicha. Estas unidades pueden ser amplias y complejas, e incluir a otras unidades o incluso a otras organizaciones formales. Denominaciones alternativas: departamento."@es . + + +org:subOrganizationOf a owl:ObjectProperty, rdf:Property; + rdfs:label "subOrganization of"@en; + rdfs:label "sous-Organization de"@fr; + rdfs:label "sotto-Organization di"@it; + + rdfs:domain org:Organization; + rdfs:range org:Organization; + rdfs:subPropertyOf org:transitiveSubOrganizationOf; + + rdfs:comment """Represents hierarchical containment of Organizations or OrganizationalUnits; indicates an Organization which contains this Organization. Inverse of `org:hasSubOrganization`."""@en; + rdfs:comment """Représente une relation hierarchique des Organisations ou des Unités Opérationnelles; indique une Organisation sujet qui contient cette Organisation. Inverse de `org:hasSubOrganization`."""@fr; + rdfs:comment """Rappresenta un contenimento gerarchico di una Organization o di una OrganizationalUnit. È l'inverso di `org:hasSubOrganization`. Ha nome come nome alternativo hasSubOrg."""@it; + rdfs:comment "組織または組織単位の階層的包含を表わします。この組織を含む組織を示します。"@ja; + rdfs:isDefinedBy ; + . + +org:subOrganizationOf rdfs:label "es suborganización de"@es ; + rdfs:comment "Distribución jerárquica de organizaciones o unidades. Indica que una organización contiene a otra organización. Es la relación inversa de `org:hasSubOrganization`"@es . + +org:transitiveSubOrganizationOf a owl:ObjectProperty, owl:TransitiveProperty, rdf:Property; + + rdfs:label "transitive sub-organization"@en; + rdfs:label "sous-Organization transitive de"@fr; + rdfs:label "sotto-Organization transitiva"@it; + + rdfs:domain org:Organization; + rdfs:range org:Organization; + + rdfs:comment """The transitive closure of subOrganizationOf, giving a representation of all organizations that contain this one. Note that technically this is a super property of the transitive closure so it could contain additional assertions but such usage is discouraged."""@en; + rdfs:comment """La version transitive de la propriété subOrganizationOf, renvoie une représentation de toutes les organisations qui contiennent celle-ci. Notez que ceci est une super-propriété de la relation transitive donc elle pourrait contenir des assertions additionnelles mais cet usage n'est pas recommandé."""@fr; + rdfs:comment """È la chiusura transitiva di subOrganizationOf, quindi rappresenta tutte le organizzazioni che la contengono. Tecnicamente, essendo una chiusura transitiva, può contenere asserzioni che non la riguardano e quindi il suo uso è sconsigliato."""@it; + rdfs:comment "subOrganizationOfの推移閉包で、これを含むすべての組織の表現を与える。技術的に、これが推移閉包のスーパープロパティーであるため、追加の言明を含むことができますが、そのような使用法はお勧めできないことに注意してください。"@ja; + rdfs:isDefinedBy ; + . + +org:transitiveSubOrganizationOf rdfs:label "es suborganización de manera transitiva de"@es ; + rdfs:comment "La versión transitiva de la propiedad “subOrganizationOf”, es decir, la representación de todas las organizaciones en las que esta está contenida. Téngase en cuenta que desde el punto de vista técnico esta es una propiedad que contiene a todas las propiedades transitivas, de forma que podría contener afirmaciones adicionales, aunque su uso no está aconsejado."@es ; + rdfs:label "es suborganización de (transitiva)"@es . + +org:hasSubOrganization a owl:ObjectProperty, rdf:Property; + rdfs:label "has SubOrganization"@en; + rdfs:label "a une Sous-Organization"@fr; + rdfs:label "ha sotto-Organization"@it; + + rdfs:domain org:Organization; + rdfs:range org:Organization; + + rdfs:comment """Represents hierarchical containment of Organizations or Organizational Units; indicates an organization which is a sub-part or child of this organization. Inverse of `org:subOrganizationOf`."""@en; + rdfs:comment """Indique le statut de dépendance hiérarchique pour des Organisations ou des Unités Opérationnelles; indique une Organisation qui est une sous-partie ou une branche d'une Organisation plus large. C'est la propriété inverse de `org:subOrganizationOf`."""@fr; + rdfs:comment """Rappresenta un contenimento gerarchico di una Organization o di una OrganizationalUnit. Indica una organizzazione che è parte di una organizzazione più grande. È l'inverso di `org:subOrganizationOf`."""@it; + rdfs:comment "組織または組織単位の階層的包含を表わします。この組織のサブパートまたは子である組織を示します。"@ja; + rdfs:isDefinedBy ; + . + +org:hasSubOrganization rdfs:label "tiene suborganización"@es ; + rdfs:comment "Organización jerárquica de organizaciones o unidades. Indica que una organización es parte de otra organización más amplia o pertenece a ella. Es la relación inversa de `org:subOrganizationOf`."@es . + +org:subOrganizationOf owl:inverseOf org:hasSubOrganization . + +org:hasSubOrganization owl:inverseOf org:subOrganizationOf . + + +org:purpose a rdf:Property; + rdfs:label "purpose"@en; + rdfs:label "but"@fr; + rdfs:label "obiettivo"@it; + + rdfs:domain org:Organization; + + rdfs:comment """Indicates the purpose of this Organization. There can be many purposes at different levels of abstraction but the nature of an organization is to have a reason for existence and this property is a means to document that reason. An Organization may have multiple purposes. It is recommended that the purpose be denoted by a controlled term or code list, ideally a `skos:Concept`. However, the range is left open to allow for other types of descriptive schemes. It is expected that specializations or application profiles of this vocabulary will constrain the range of the purpose. Alternative names: _remit_ _responsibility_ (esp. if applied to OrganizationalUnits such as Government Departments)."""@en; + rdfs:comment """Indique le but de cette Organisation. Il peut exister plusieurs buts à différents niveaux d'abstraction mais la nature d'une organisation est d'avoir une raison d'exister et cette propriété doit servir à documenter cette raison d'être. Une Organisation peut avoir plusieurs Buts. Il est recommandé que le but soit libellé à l'aide d'un vocabulaire contrôlé ou autre code établi, idéalement avec un concept `skos:Concept`. Toutefois, le champ de cette propriété est laissé ouvert et pourrait accepter d'autres schémas de description. Il est préférable que les spécialisations ou les profils d'applications de ce vocabulaire contraignent le champ de cette propriété."""@fr; + rdfs:comment """Indica l'obiettivo di questa Organization. In generale, si possono esprimere gli obiettivi di un'organizzazione secondo diversi livelli di astrazione, ma la natura stessa dell'organizzazione ha una ragione d'essere ed è proprio questa che deve essere catturata con tale proprietà. Inoltre, un'Organization può avere obiettivi multipli. È raccomandabile che l'obiettivo faccia parte di una code list, e che sia preferibilmente un `skos:Concept`. Ad ogni modo, il codominio della proprietà è lasciato aperto per consentire altri tipi di di descrizione. Conseguentemente, eventuali specializzazioni o profili applicativi possono utilizzare quel vocabolario come codominio della proprietà."""@it; + rdfs:comment "この組織の目的を示します。異なる抽象レベルの多くの目的がありえますが、組織の本質は存在理由を持つことであり、このプロパティーはその理由をドキュメント化する手段です。組織は、複数の目的を持っている可能性があります。"@ja; + rdfs:isDefinedBy ; + . + +org:purpose rdfs:label "tiene objetivo"@es ; + rdfs:comment "Finalidad u objetivo de la organización. La organización puede tener muchos objetivos a diferentes niveles de abstracción, pero en la naturaleza de las organizaciones está el tener una razón para existir, y la finalidad de esta propiedad es documentar dicha razón. La organización podrá tener más de un objetivo. Se recomienda el uso de vocabularios controlados o listas de códigos para indicar el objetivo, preferentemente mediante el uso de un `skos:Concept`. Sin embargo, el rango no está predeterminado, de forma que otros tipos de esquemas descriptivos tiene cabida. Se espera que ciertas especializaciones de este vocabulario o ciertos perfiles de aplicaciones restrinjan el rango del objetivo. Denominaciones alternativas: área_ _jurisdicción_ _ responsabilidad _ (especialmente cuando se aplica a unidades tales como ministerios o divisiones administrativas de los gobiernos)"@es . + +org:hasUnit a owl:ObjectProperty, rdf:Property; + + rdfs:label "has Unit"@en; + rdfs:label "possède une Unité"@fr; + rdfs:label "ha Unit"@it; + + rdfs:domain org:FormalOrganization; + rdfs:range org:OrganizationalUnit; + rdfs:subPropertyOf org:hasSubOrganization; + + rdfs:comment """Indicates a unit which is part of this Organization, e.g. a Department within a larger FormalOrganization. Inverse of `org:unitOf`."""@en; + rdfs:comment """Indique une Unité qui fait partie d'une Organisation, par exemple un Départment au sein d'une Organisation Formelle plus large. Inverse de `org:unitOf`."""@fr; + rdfs:comment """Indica un'unità che è parte di questa Organization, come ad esempio un dipartimento facente parte di una più ampia FormalOrganization. È l'inverso di `org:unitOf`."""@it; + rdfs:comment "例えば、より大きな組織内の部局など、この組織の一部である単位を示します。"@ja; + rdfs:isDefinedBy ; + . + +org:hasUnit rdfs:label "contiene unidad"@es ; + rdfs:comment "Unidad que es parte de la organización, como, por ejemplo, un departamento incluido en una organización formal más amplia."@es . + +org:unitOf a owl:ObjectProperty, rdf:Property; + + rdfs:label "unit Of"@en; + rdfs:label "unité de"@fr; + rdfs:label "unità di"@it; + + rdfs:domain org:OrganizationalUnit; + rdfs:range org:FormalOrganization; + rdfs:subPropertyOf org:subOrganizationOf; + + rdfs:comment """Indicates an Organization of which this Unit is a part, e.g. a Department within a larger FormalOrganization. This is the inverse of `org:hasUnit`."""@en; + rdfs:comment """Indique l'Organisation dont cette Organisation ou Unité fait partie, par exemple un Départment au sein d'une Organisation Formelle plus large. Inverse de `org:hasUnit`."""@fr; + rdfs:comment """Indica un Organization di cui questa Unit fa parte, come ad esempio un dipartimento all'interno di una più vasta FormalOrganization. È l'inverso di `org:hasUnit`."""@it; + rdfs:comment "例えば、より大きな組織内の部局など、この単位がその一部分である組織を示します。"@ja; + rdfs:isDefinedBy ; + . + +org:unitOf rdfs:label "es unidad de"@es ; + rdfs:comment "Organización de la que es parte esta unidad, por ejemplo, un departamento incluido en una organización formal más amplia."@es . + +org:unitOf owl:inverseOf org:hasUnit . + +org:hasUnit owl:inverseOf org:unitOf . + + +org:classification a owl:ObjectProperty, rdf:Property; + + rdfs:label "classification"@en; + rdfs:label "classification"@fr; + rdfs:label "classificazione"@it; + + rdfs:domain org:Organization; + rdfs:range skos:Concept; + + rdfs:comment """Indicates a classification for this Organization within some classification scheme. Extension vocabularies may wish to specialize this property to have a range corresponding to a specific `skos:ConceptScheme`. This property is under discussion and may be revised or removed - in many cases organizations are best categorized by defining a sub-class hierarchy in an extension vocabulary."""@en; + rdfs:comment """Indique une classification pour cette Organisation dans le cadre d'un schéma de classification. Il est possible de spécialiser cette propriété en utilisant un vocabulaire spécialisé pour que le champ corresponde à un concept spécifique `skos:ConceptScheme`. Cette propriété est en discussion est pourrait être révisée ou supprimée - dans de nombreux cas, les organisations sont mieux catégorisées par une hiérarchie de sous-classe dans un vocabulaire externe."""@fr; + rdfs:comment """Indica una classificazione per questa Organization all'interno di un qualche schema di classificazione. Alcuni vocabolari potrebbero voler specializzare questa proprietà per avere un codominio corrispondente a uno specifico `skos:ConceptScheme`. Si noti che la presenza di questa proprietà è ancora in fase di discussione e potrebbe essere revisionata o rimossa."""@it; + rdfs:comment """ある分類表内のこの組織に対する分類を示します。 +アプリケーションがorg:Organizationのサブクラスを組織的なカテゴリーを表わす手段として定義することも許容されることに注意してください。"""@ja; + rdfs:isDefinedBy ; + . + +org:classification rdfs:label "pertenece a la clasificación"@es ; + rdfs:comment "Ordenación jerárquica que se hace de una organización dentro de un esquema de clasificación. Es posible que algunos vocabularios especifiquen esta propiedad de forma que el rango se corresponda con un `skos:ConceptScheme` específico. La conveniencia de incluir esta propiedad se está debatiendo y puede que se revise o elimine (en muchos casos las organizaciones se clasifican mejor si se define una jerarquía de subclases en un vocabulario aparte)"@es . + +org:identifier a owl:DatatypeProperty, rdf:Property; + + rdfs:label "identifier"@en; + rdfs:label "identifiant"@fr; + rdfs:label "identificatore"@it; + + rdfs:domain org:Organization; + rdfs:subPropertyOf skos:notation; + + rdfs:comment """Gives an identifier, such as a company registration number, that can be used to used to uniquely identify the organization. Many different national and international identier schemes are available. The org ontology is neutral to which schemes are used. The particular identifier scheme should be indicated by the datatype of the identifier value. Using datatypes to distinguish the notation scheme used is consistent with recommended best practice for `skos:notation` of which this property is a specialization."""@en; + rdfs:comment """Donne un identifiant, comme par exemple le numéro d'enregistrement d'une entreprise, qui peut être utilisé comme identifiant unique pour l'Organisation. De nombreux schémas nationaux et internationaux sont disponibles. Cette ontologie reste neutre par rapport au schéma utilisé. Le schéma particulier utilisé devrait être indiqué par le `datatype` de la valeur de l'identifiant. Utiliser les datatypes pour distinguer les schémas de notation est cohérent avec les bonnes pratiques pour `skos:notation` dont cette propriété est une spécialisation."""@fr; + rdfs:comment """Indica un identificatore univoco per l'organizzazione, come ad esempio la partita IVA di un'azienda. Molti schemi di identificazione a livello nazionale e internazionale sono disponibili allo scopo. L'ontologia ORG è neutrale rispetto allo schema da utilizzare. Lo schema di identificazione dovrebbe essere indicato dal datatype del valore dell'identificatore. L'uso del datatype per distinguere lo schema di identificazione è coerente con le best practice per `skos:notation`, di cui questa proprietà è una specializzazione."""@it; + rdfs:comment "組織を一意に識別するために使用できる会社登録番号などの識別子を与えます。"@ja; + rdfs:isDefinedBy ; + . + +org:identifier rdfs:label "tiene identificador"@es ; + rdfs:comment "Código o identificador, como por ejemplo el CIF de una empresa, que permite identificar de forma inequívoca a una organización. Existen muchos códigos de identificación tanto nacionales como internacionales. Esta ontología no obliga al uso de ningún esquema en concreto. Los códigos de identificación utilizados en cada caso se deberían indicar mediante el uso de la propiedad “datatype” del valor del identificador. El uso de la propiedad “datatype” para especificar el esquema de notación utilizado está en consonancia con las buenas prácticas recomendadas para el uso de la propiedad `skos:notation`, de la que esta propiedad es una especialización."@es . + + +org:linkedTo a owl:ObjectProperty, rdf:Property; + + rdfs:label "linked to"@en; + rdfs:label "relié à"@fr; + rdfs:label "collegato a"@it; + + rdfs:domain org:Organization; + rdfs:range org:Organization; + + rdfs:comment """Indicates an arbitrary relationship between two organizations. Specializations of this can be used to, for example, denote funding or supply chain relationships."""@en; + rdfs:comment """Indique une relation arbitraire entre deux Organisations. Des spécialisations peuvent être utilisées pour, par exemple, qualifier une relation de fournisseur ou de financeur."""@fr; + rdfs:comment """Indica una relazione arbitraria tra due organizzazioni. Ad esempio, specializzazioni di questa proprietà possono essere usate per denotare relazioni particolari tipo il finanziamento o la fornitura."""@it; + rdfs:comment "2つの組織の任意の関係を示します。"@ja; + rdfs:isDefinedBy ; + . + +org:linkedTo rdfs:label "está relacionado con"@es ; + rdfs:label "está relacionada con"@es ; + rdfs:comment "Relación arbitraria entre dos organizaciones. Las especializaciones de esta relación se pueden utilizar para denotar relaciones de financiación o suministro, entre otras."@es . + +# -- Reporting relationships and roles ----------------------------------------------------------- + + +org:memberOf a owl:ObjectProperty, rdf:Property; + + rdfs:label "member of"@en; + rdfs:label "membre de"@fr; + rdfs:label "membro di"@it; + + rdfs:domain foaf:Agent; + rdfs:range org:Organization; + + rdfs:comment """Indicates that a person is a member of the Organization with no indication of the nature of that membership or the role played. Note that the choice of property name is not meant to limit the property to only formal membership arrangements, it is also indended to cover related concepts such as affilliation or other involvement in the organization. Extensions can specialize this relationship to indicate particular roles within the organization or more nuanced relationships to the organization. Has an optional inverse, `org:hasmember`."""@en; + rdfs:comment """Indique qu'une personne est membre de l'Organisation sans précision sur la nature de cet engagement ou du rôle joué. Notez que le choix du nom de cette propriété ne vise pas à la limiter aux seuls engagements formels, elle peut également couvrir des concepts reliés comme l'affiliation ou le bénévolat. Des extensions peuvent spécialiser cette relation pour indiquer des rôles particuliers au sein de l'Organisation or des relations plus nuancées avec elle. Possède une propriété inverse optionnelle, `org:hasmember`."""@fr; + rdfs:comment """Indica che una persona è membro di una Organization senza una precisa indicazione sulla natura di questa appartenenza e sul suo ruolo. Si noti che la scelta del nome di questa proprietà non intende limitarla alla sola rappresentazione formalmente di un'appartenenza. La proprietà può coprire anche altri coinvolgimenti nell'organizzazione. Questa proprietà può essere specializzata per indicare ruoli all'interno organizzazione o relazioni di diverse tipologie. Ha `org:hasmember` come proprietà inversa opzionale."""@it; + rdfs:comment "エージェント(人または他の組織)が組織のメンバーであることを示します。ただし、その構成員の本質や担う役割は示しません。プロパティー名の選択は、プロパティーを正式な構成員配置のみに制限することが目的ではないことに注意してください。所属や組織へのその他の関与などの関連する概念をカバーすることも意図されています。拡張により、この関係を特殊化し、組織内の特定の役割やよりニュアンスを含んだ組織との関係を示すことができます。"@ja; + rdfs:isDefinedBy ; + . + +org:memberOf rdfs:label "es miembro de"@es ; + rdfs:comment "Persona que pertenece a la organización o es miembro de la misma, sin que conste la naturaleza de dicha pertenencia o el papel que desempeña. Se debe tener en cuenta que la elección de una denominación para esta propiedad no significa que la propiedad esté limitada a ciertos tipos de pertenencia formales, sino que pretende cubrir conceptos relacionados como el de afiliación u otras formas de participación en la organización. Se puede hacer uso de extensiones para especializar esta relación de forma que incluya tipos específicos de pertenencia a las organizaciones o relaciones especiales con la organización."@es . + + +org:hasMember a owl:ObjectProperty, rdf:Property; + + rdfs:label "has member"@en; + rdfs:label "possède un membre"@fr; + rdfs:label "ha membro"@it; + + rdfs:domain org:Organization; + rdfs:range foaf:Agent; + owl:equivalentProperty foaf:member; + + rdfs:comment """Indicates a person who is a member of the subject Organization. Inverse of `org:memberOf`, see that property for further clarification. Provided for compatibility with `foaf:member`."""@en; + rdfs:comment """Indique une personne membre de l'Organisation sujet. Inverse de `org:memberOf`, voyez la description de cette propriété pour plus de précisions. Fourni pour la compatibilité avec `foaf:member`."""@fr; + rdfs:comment """Indica una persona che è membro della data Organization. È l'inverso di `org:memberOf` ed è fornita per compatibilità con `foaf:member`."""@it; + rdfs:comment "対象組織のメンバーであるエージェント(人または他の組織)を示します。org:memberOfの逆。さらに明確な説明については、そのプロパティーを参照してください。"@ja; + rdfs:isDefinedBy ; + . + +org:hasMember rdfs:label "tiene miembro"@es ; + rdfs:comment "Persona que es miembro de la organización en cuestión. Es la relación inversa de `org:memberOf`, véase la descripción de esa propiedad para más detalles. Se prevé compatibilidad con foaf:member`."@es . + +org:memberOf owl:inverseOf org:hasMember . + +org:hasMember owl:inverseOf org:memberOf . + + + +org:reportsTo a owl:ObjectProperty, rdf:Property; + + rdfs:label "reports to"@en; + rdfs:label "est subordonné à"@fr; + rdfs:label "riporta a"@it; + + rdfs:domain [a owl:Class; owl:unionOf (foaf:Agent org:Post)]; + rdfs:range [a owl:Class; owl:unionOf (foaf:Agent org:Post)]; + + rdfs:comment """Indicates a reporting relationship as might be depicted on an organizational chart. The precise semantics of the reporting relationship will vary by organization but is intended to encompass both direct supervisory relationships (e.g. carrying objective and salary setting authority) and more general reporting or accountability relationships (e.g. so called _dotted line_ reporting)."""@en; + rdfs:comment """Indique une relation de subordination comme elle pourrait figurer dans un organigramme. La sémantique précise de cette subordination pourra varier selon l'Organisation mais vise à englober aussi bien les relations hiérarchiques directes (définition d'objectifs, montant du salaire) que des relations plus générales ou organisationnelles (les liens en pointillés dans les organigrammes)."""@fr; + rdfs:comment """Indica una relazione di subordinazione all'interno dell'organigramma. La semantica precisa può variare a seconda dell'organizzazione, per esempio può essere usata per rappresentare la proprietà di supervisione oppure per le relazioni di rendicontazione."""@it; + rdfs:comment "組織図で描かれるかもしれないような上下関係を示します。エージェント間またはエージェントが就くことができるポスト間の上下関係を直接的に示すために使用できます。"@ja; + rdfs:isDefinedBy ; + . + +org:reportsTo rdfs:label "responde ante"@es ; + rdfs:comment "Relación de subordinación que se representa en los organigramas de las organizaciones. La semántica de la relación de subordinación varía según las organizaciones, pero su intención es abarcar tanto a las relaciones de supervisión directa (por ejemplo, aquellas en las que la autoridad determina los objetivos o el salario) como a las relaciones de subordinación más generales (por ejemplo, las llamadas líneas de autoridad o de mando (y responsabilidad) (http://www.promonegocios.net/organigramas/tipos-de-organigramas.html))."@es . + + +org:Role a owl:Class, rdfs:Class; + rdfs:subClassOf skos:Concept; + + rdfs:label "Role"@en; + rdfs:label "Rôle"@fr; + rdfs:label "Ruolo"@it; + + rdfs:comment """Denotes a role that a Person or other Agent can take in an organization. Instances of this class describe the abstract role; to denote a specific instance of a person playing that role in a specific organization use an instance of `org:Membership`. It is common for roles to be arranged in some taxonomic structure and we use SKOS to represent that. The normal SKOS lexical properties should be used when labelling the Role. Additional descriptive properties for the Role, such as a Salary band, may be added by extension vocabularies."""@en; + + rdfs:comment """Indique le rôle qu'une Personne ou un autre Agent peut avoir dans une Organisation. Les instances de cette classe décrivent le rôle dans l'absolu; pour indiquer une personne ayant ce rôle spécifique dans une Organisation, utilisez une instance de `org:Membership`. Il est courant que les rôles soient organisés dans une sorte de taxonomie, ce qui peut être représenté avec SKOS. Les propriétés de libellés standards de SKOS devraient être utilisées pour libeller le Rôle. D'autres propriétés additionnelles pour ce rôle, comme une fourchette de Salaire peuvent être ajoutées par une extension de ce vocabulaire."""@fr; + rdfs:comment """Indica il ruolo che una Person o un altro Agent può assumere in un'organizzazione. Le istanze di questa classe descrivono un ruolo astratto; per esprimere il ruolo che una precisa persona ricopre in un'organizzazione si usi un'istanza di `org:Membership`. È comune organizzare i ruoli in una qualche struttura tassonomica e quindi si raccomanda SKOS per questo. Altre proprietà descrittive per il Role, come salario, possono essere aggiunte mediante l'uso di altri vocabolari."""@it; + rdfs:comment "人またはその他のエージェントが組織で担うことができる役割を表わします。この種のインスタンスは、抽象的な役割を記述します。特定の組織でその役割を担っている人の特定のインスタンスを示すためには、org:Membershipのインスタンスを使用します。"@ja; + rdfs:isDefinedBy ; + . + +org:Role rdfs:label "actividad"@es ; + rdfs:comment "Función que una persona o agente desempeña en el seno de una organización. Las instancias de esta clase describen la actividad en abstracto; si lo que se pretende es incluir una instancia que refleje la función o actividad que desempeña una persona en concreto en una organización específica, se indica el uso de instancias de la clase `org:Membership`. Es común que dichas actividades se representen en una estructura taxonómica mediante SKOS. Las propiedades léxicas de SKOS deberían utilizarse a la hora de denominar o etiquetar la actividad desempeñada. Para añadir propiedades descriptivas adicionales, como rango salarial, se tendrá que recurrir a vocabularios externos."@es . + +org:Membership a owl:Class, rdfs:Class; + + rdfs:label "Membership"@en; + rdfs:label "Engagement"@fr; + rdfs:label "Appartenenza"@it; + + rdfs:comment """Indicates the nature of an Agent's membership of an organization. Represents an n-ary relation between an Agent, an Organization and a Role. It is possible to directly indicate membership, independent of the specific Role, through use of the `org:memberOf` property."""@en; + rdfs:comment """Indique la nature de l'engagement d'un Agent dans une Organisation. Représente une relation n-aire entre un Agent, une Organisation et un Role. Il est possible d'indiquer directement l'appartenance à une organisation, independemment d'un rôle spécifique, à travers l'usage de la propriété `org:memberOf`."""@fr; + rdfs:comment """Indica la natura della relazione di appartenenza di un Agent in un'organizzazione. Rappresenta una relazione n-aria tra un'Agent, un Organization e un Role. È possibile indicare direttamente la membership, indipendentemente dallo specifico Role, attraverso l'uso della proprietà `org:memberOf`"""@it; + rdfs:comment "組織のエージェントの構成員の本質を示します。"@ja; + rdfs:isDefinedBy ; + . + +org:Membership rdfs:label "membresía"@es ; + rdfs:comment "Pertenencia o afiliación de un agente a una organización. Es una relación n-aria entre un agente, una organización y una actividad. Es posible indicar pertenencia mediante el uso de la propiedad `org:memberOf`, independientemente de la actividad específica que se desempeñe."@es . + + +org:member a owl:ObjectProperty, rdf:Property, owl:FunctionalProperty; + + rdfs:label "member"@en; + rdfs:label "membre"@fr; + rdfs:label "membro"@it; + + rdfs:domain org:Membership; + rdfs:range foaf:Agent; + + rdfs:comment """Indicates the Person (or other Agent including Organization) involved in the Membership relationship. Inverse of `org:hasMembership`"""@en; + rdfs:comment """Indique une personne (ou tout autre Agent, y compris une Organisation) impliqué dans la relation d'Engagement. Inverse de `org:hasMembership`"""@fr; + rdfs:comment """Indica la Person (o un altro Agent) coinvolto in una relazione di Membership. È l'inverso di `org:hasMembership`."""@it; + rdfs:comment "構成員関係に含まれている人(または、組織を含んでいる他のエージェント)を示します。"@ja; + rdfs:isDefinedBy ; + . + +org:member rdfs:label "es condición de miembro sobre agente"@es ; + rdfs:comment "Persona (u otro agente, incluyendo una organización) que participa en la relación de membresía. Es la relación inversa de `org:hasMembership`."@es . + + +org:organization a owl:ObjectProperty, rdf:Property, owl:FunctionalProperty; + + rdfs:label "organization"@en; + rdfs:label "organisation"@fr; + rdfs:label "organizzazione"@it; + + rdfs:domain org:Membership; + rdfs:range org:Organization; + + rdfs:comment """Indicates Organization in which the Agent is a member."""@en; + rdfs:comment """Indique l'Organization dont l'agent est membre."""@fr; + rdfs:comment """Indica l'Organization in cui l'Agent è un membro."""@it; + rdfs:comment "エージェントがメンバーである組織を示します。"@ja; + + rdfs:isDefinedBy ; + . + +org:organization rdfs:label "es condición de miembro sobre organización"@es ; + rdfs:comment "Organización a la que pertenece el agente en calidad de miembro."@es . + + + +org:role a owl:ObjectProperty, rdf:Property; + + rdfs:label "role"@en; + rdfs:label "rôle"@fr; + rdfs:label "ruolo"@it; + + rdfs:domain [a owl:Class; owl:unionOf (org:Membership org:Post)]; +# rdfs:domain org:Membership; + rdfs:range org:Role; + + rdfs:comment """Indicates the Role that the Agent plays in a Membership relationship with an Organization."""@en; + rdfs:comment """Indique le Rôle de l'Agent dans son Engagement avec l'Organisation."""@fr; + rdfs:comment """Indica il Role che un Agent ricopre in una relazione di Membership con una Organization"""@it; + rdfs:comment "エージェントが組織との構成員関係において担う役割を示します。ポストの保持者が担う役割を示すためにorg:Postで用いることもできます。"@ja; + rdfs:isDefinedBy ; + . + +org:role rdfs:label "desempeña la actividad de"@es ; + rdfs:comment "Actividad que el agente desempeña en una relación de pertenencia a una organización."@es . + +org:hasMembership a owl:ObjectProperty, rdf:Property; + + rdfs:label "membership"@en; + rdfs:label "engagement"@fr; + rdfs:label "appartenenza"@it; + + rdfs:domain foaf:Agent; + rdfs:range org:Membership; + + rdfs:comment """Indicates a membership relationship that the Agent plays. Inverse of `org:member`."""@en; + rdfs:comment """Indique pour cet Agent un engagement dans une Organisation. Inverse de `org:member`."""@fr; + rdfs:comment """Indica una relazione di appartenenza che coinvolge un Agent. È l'inverso di `org:member`."""@it; + rdfs:comment "エージェントが担う構成員関係を示します。"@ja; + + rdfs:isDefinedBy ; + . + +org:hasMembership rdfs:label "tiene membresía"@es ; + rdfs:comment "Relación de pertenencia o afiliación a una organización en la que el agente desempeña un cargo o función. Es la relación inversa de `org:member`."@es . + +org:hasMembership owl:inverseOf org:member . + +org:member owl:inverseOf org:hasMembership . + + +org:memberDuring a owl:ObjectProperty, rdf:Property; + + rdfs:label "member During"@en; + rdfs:label "durée d'engagement"@fr; + rdfs:label "membro durante"@it; + + rdfs:domain org:Membership; + +# This now an informative, not a normative, range constraint +# rdfs:range owlTime:Interval; + + rdfs:comment """Optional property to indicate the interval for which the membership is/was valid."""@en; + rdfs:comment """Propriété optionnelle pour indiquer l'intervalle durant lequel l'engagemnet est ou était valide."""@fr; + rdfs:comment """Proprietà opzionale per indicare l'intervallo per il quale l'appartenenza è/è stata valida."""@it; + rdfs:comment "構成員が有効である/であった期間を示すためのオプションのプロパティー。"@ja; + rdfs:isDefinedBy ; + . + +org:memberDuring rdfs:label "es miembro durante"@es ; + rdfs:comment "Propiedad opcional que indica el periodo durante el cual la relación de membresía o pertenencia a una organización se mantiene en vigencia."@es . + + +org:roleProperty a owl:AnnotationProperty, rdf:Property; + + rdfs:label "role (property)"@en; + rdfs:label "rôle (propriété)"@fr; + rdfs:label "ruolo (proprietà)"@it; + + rdfs:domain org:Role; + rdfs:range rdf:Property; + + rdfs:comment """This is a metalevel property which is used to annotate an `org:Role` instance with a sub-property of `org:memberOf` that can be used to directly indicate the role for easy of query. The intended semantics is a Membership relation involving the Role implies the existence of a direct property relationship through an inference rule of the form: `{ [] org:member ?p; org:organization ?o; org:role [org:roleProperty ?r] } -> {?p ?r ?o}`."""@en; + rdfs:comment """Ceci est une méta-propriété utilisée pour annoter une instance de `org:Role` ayant une sous-propriété `org:memberOf` qui peut être utilisée pour indiquer directement le rôle et pouvoir faire des requêtes plus facilement. La sémantique visée est un Engagement impliquant l'existence d'une relation de propriété directe à travers d'une règle d'inférence de la forme: `{ [] org:member ?p; org:organization ?o; org:role [org:roleProperty ?r] } -> {?p ?r ?o}`."""@fr; + rdfs:comment """Questa è una meta-proprietà usata per annotare un'istanza di `org:Role` con una sotto-proprietà di `org:memberOf` e può essere usata per indicare direttamente il ruolo per facilitare un'interrogazione sui dati."""@it; + rdfs:comment "これは、クエリが容易になるように役割を直接的に示すために使用できるorg:memberOfのサブプロパティーでorg:Roleインスタンスを注釈するために用いられるメタレベルのプロパティーです。"@ja; + rdfs:isDefinedBy ; + . + +org:roleProperty rdfs:label "desempeña la actividad de (propiedad)"@es ; + rdfs:comment "Meta-propiedad que se utiliza para anotar una instancia de `org:Role` con una sub-propiedad de `org:memberOf`, que puede ser utilizada para indicar directamente la actividad a fin de facilitar las consultas a los datos. The intended semantics is that a Membership relation involving the Role implies the existence of a direct property relationship through an inference rule of the form: { [] org:member ?a; org:organization ?o; org:role [org:roleProperty ?r] } -> {?a ?r ?o}"@es . + + +org:headOf a owl:ObjectProperty, rdf:Property; + + rdfs:label "head of"@en; + rdfs:label "responsable de"@fr; + rdfs:label "responsabile di"@it; + + rdfs:domain foaf:Agent; + rdfs:range org:Organization; + rdfs:subPropertyOf org:memberOf; + + rdfs:comment """Indicates that a person is the leader or formal head of the Organization. This will normally mean that they are the root of the `org:reportsTo` (acyclic) graph, though an organization may have more than one head."""@en; + rdfs:comment """Indique qu'une personne est le directeur ou le responsable formel d'une Organisation. Ceci indique souvent qu'il est au sommet de du graphe acyclique des `org:reportsTo`, même si une organisation peut avoir plus d'un responsable."""@fr; + rdfs:comment """Indica che una persona è leader o responsabile formale di una Organization. Questo significa che la persona è alla radice del grafo (aciclico) creato dalle `org:reportsTo`, sebbene un'organizzazione possa avere più di un responsabile."""@it; + rdfs:comment "人(または他のエージェント)が組織のリーダーや正式なトップであることを示します。"@ja; + rdfs:isDefinedBy ; + . + +org:headOf rdfs:label "es director ejecutivo de"@es ; + rdfs:comment "Persona que es jefe o jefa, representante ,,director o directora de la organización. Esto significa que dicha persona es el rango de la relación `org:reportsTo` en el organigrama de la organización (acíclico), aunque una organización puede tener más de un jefe."@es . + + +org:Head a org:Role; + # This class is not in the Rec document (PhilA, 2014-02-05) + + rdfs:label "head"@en; + rdfs:label "responsable"@fr; + rdfs:label "responsabile"@it; + + skos:prefLabel "head"@en; + skos:prefLabel "responsable"@fr; + skos:prefLabel "responsabile"@it; + + rdfs:comment "A role corresponding to the `org:headOf` property"@en; + rdfs:comment "Un rôle correspondant à la propriété `org:headOf`"@fr; + rdfs:comment "Un ruolo corrispondente alla proprietà `org:headOf`."@it; + org:roleProperty org:headOf ; + rdfs:isDefinedBy ; + . + +org:Head rdfs:label "director ejecutivo"@es ; + rdfs:label "directora ejecutiva"@es ; + rdfs:comment "Actividad correspondiente a la propiedad `org:headOf`."@es . + + +org:remuneration a owl:ObjectProperty, rdf:Property; + + rdfs:label "remuneration"@en; + rdfs:label "rémuneration"@fr; + rdfs:label "remunerazione"@it; + + rdfs:domain org:Role; + + rdfs:comment """Indicates a salary or other reward associated with the role. Typically this will be denoted using an existing representation scheme such as `gr:PriceSpecification` but the range is left open to allow applications to specialize it (e.g. to remunerationInGBP)."""@en; + + rdfs:comment """Indique un salaire ou tout autre compensation associée au Rôle. Typiquement, ceci sera annoté en utilisant un schéma existant comme `gr:PriceSpecification` mais le champ de cette propriété est laissé ouvert afin de permettre aux applications de la spécialiser (par exemple remunerationEuro)."""@fr; + rdfs:comment """Indica il salario o altra forma di remunerazione associata al ruolo. In genere, questo si denota usando uno schema di rappresentazione esistente come il `gr:PriceSpecification` ma il codominio è lasciato libero di essere specializzato a seconda delle applicazioni."""@it; + rdfs:comment "役割に関係する給料やその他の報酬を示します。"@ja; + rdfs:isDefinedBy ; + . + +org:remuneration rdfs:label "recibe remuneración"@es ; + rdfs:comment "Salario o cualquier otra remuneración asociada con la actividad. La forma usual de referirse a dicha remuneración será utilizando un esquema de representación como el propuesto en la ontología GoodRelations `gr:PriceSpecification`, pero el rango se deja abierto a que las distintas aplicaciones lo especialicen (por ejemplo, remunerationInGBP)"@es . + + +# -- Location ----------------------------------------------------------- + + + +org:Site a owl:Class, rdfs:Class; + + rdfs:label "Site"@en; + rdfs:label "Site"@fr; + rdfs:label "Sede"@it; + + rdfs:comment """An office or other premise at which the organization is located. Many organizations are spread across multiple sites and many sites will host multiple locations. In most cases a Site will be a physical location. However, we don't exclude the possibility of non-physical sites such as a virtual office with an associated post box and phone reception service. Extensions may provide subclasses to denote particular types of site."""@en; + + rdfs:comment """Un établissement ou tout autre lieu dans lequel une Organisation est localisé. Beaucoup d'organisations sont dispersées à travers plusieurs sites. Dans la plupart des cas un Site sera un lieu physique. Toutefois, nous n'excluons pas la possibilité de sites non-physiques comme un bureau virtuel avec une boîte postale et un service de secrétariat mutualisé. Des extensions pourraient fournir des sous-classes pour décrire des types de sites particuliers."""@fr; + rdfs:comment """Un ufficio o altra sede dovei l'organizzazione è situata. Molte organizzazione sono distribuite su più sedi e molte sedi ospitano più ubicazioni. Nella maggior parte dei casi un Site è una locazione fisica. Non si esclude la possibilità di indicare sedi non fisiche come ad esempio gli uffici virtuali. Le estensioni dell'ontologia potrebbero usare delle sottoclassi per rappresentare i tipi particolari di sede."""@it; + rdfs:comment "組織が位置するオフィスやその他の敷地。多くの組織が複数のサイトに散在しており、多くのサイトが多数の場所を持つでしょう。"@ja; + rdfs:isDefinedBy ; + . + +org:Site rdfs:label "sede"@es ; + rdfs:comment "Oficina, local o cualquier otro lugar en el que se encuentra una organización. Muchas organizaciones están distribuidas en varias sedes, que a su vez están repartidas en distintas ubicaciones. En muchos casos una sede será un sitio o local físico. Sin embargo, no se excluye la posibilidad de lugares no físicos como oficinas virtuales con los correspondientes apartados de correo y servicio de atención telefónica. Se pueden añadir más subtipos mediante extensiones para incluir tipos especiales de lugares."@es . + + +org:siteAddress a owl:ObjectProperty, rdf:Property; + + rdfs:label "site Address"@en; + rdfs:label "adresse du Site"@fr; + rdfs:label "indirizzo della sede"@it; + + rdfs:domain org:Site; + # rdfs:range vcard:VCard; + + rdfs:comment """Indicates an address for the site in a suitable encoding. Use of vCard (using the http://www.w3.org/TR/vcard-rdf/ vocabulary) is encouraged but the range is left open to allow other encodings to be used. The address may include email, telephone, and geo-location information and is not restricted to a physical address. """@en; + rdfs:comment """Indique une adresse pour le site dans un encodage approprié. L'usage du vocabulaire vCard ( http://www.w3.org/TR/vcard-rdf/) est encouragé, mais le range est ouvert pour permettre l'utilisation d'autres vocabulaires. L'adresse peut comporter le courriel, le téléphone, et l'information de géolocalisation; et n'est donc pas seulement limitée à une adresse physique. """@fr; + rdfs:comment """Indica un indirizzo per la sede in una codifica appropriata. Il codominio è lasciato libero ma è consigliabile l'uso del vocabolario vCard (http://www.w3.org/TR/vcard-rdf/). L'indirizzo può includere email, numero di telefono e informazioni di geolocalizzazione e non è vincolato ad essere un indirizzo fisico."""@it; + rdfs:comment "適切にコード化されたサイトのアドレスを示します。vCard[vcard-rdf]語彙などの有名なアドレスのコード化の使用が奨励されますが、他の符号化の使用を可能とするために値域はオープンのままにされます。アドレスには、電子メール、電話およびジオロケーション情報を含むことができ、物理的なアドレスに制限されません。"@ja; + rdfs:isDefinedBy ; + . + +org:siteAddress rdfs:label "es la dirección de la sede"@es ; + rdfs:comment "Dirección de la sede según una codificación adecuada. Se recomienda el uso de vCard (que utiliza el vocabulario en http://www.w3.org/TR/vcard-rdf/), pero el rango no se restringe únicamente al uso de este vocabulario sino que se permite el uso de otros códigos. La dirección puede constar de una dirección de correo electrónico, un número de teléfono o información de geo-localización, y no se limita a una dirección postal física."@es . + + +org:hasSite a owl:ObjectProperty, rdf:Property; + + rdfs:label "has site"@en; + rdfs:label "a un site"@fr; + rdfs:label "ha sede"@it; + + rdfs:domain org:Organization; + rdfs:range org:Site; + + rdfs:comment """Indicates a site at which the Organization has some presence even if only indirect (e.g. virtual office or a professional service which is acting as the registered address for a company). Inverse of `org:siteOf`."""@en; + rdfs:comment """Indique un site sur lequel l'Organisation possède une présence, même indirecte (domiciliation, boite postale). Inverse de `org:siteOf`."""@fr; + rdfs:comment """Indica la sede in cui l'Organization ha una qualche presenza anche in modo indiretto (ad esempio un ufficio virtuale). È l'inverso di `org:siteOf`."""@it; + rdfs:comment "組織が、間接(例えば、会社の登録住所として機能しているバーチャル・オフィスやプロフェッショナル・サービス)のみであったとしても、ある存在感を持っているサイトを示します。"@ja; + rdfs:isDefinedBy ; + . + +org:hasSite rdfs:label "tiene sede en"@es ; + rdfs:comment "Lugar en donde la organización tiene algún tipo de presencia, incluso si es de forma indirecta (por ejemplo, una oficina virtual o servicio profesional que hagan la función de dirección registrada de la compañía). Es la relación inversa de `org:siteOf`."@es . + + +org:siteOf a owl:ObjectProperty, rdf:Property; + + rdfs:label "site Of"@en; + rdfs:label "site de"@fr; + rdfs:label "sede di"@it; + + rdfs:domain org:Site; + rdfs:range org:Organization; + + rdfs:comment """Indicates an Organization which has some presence at the given site. This is the inverse of `org:hasSite`."""@en; + rdfs:comment """Indique une Organisation qui a une présence sur le site en question. Inverse de `org:hasSite`."""@fr; + rdfs:comment """Indica un'Organization che ha una qualche presenza nella data sede. È l'inverso di `org:hasSite`."""@it; + rdfs:comment "あるサイトである存在感を持っている組織を示します。"@ja; + rdfs:isDefinedBy ; + . + +org:siteOf rdfs:label "es sede de"@es ; + rdfs:comment "Organización que tiene ubicación en un lugar. Es la relación inversa de `org:hasSite`."@es . + +org:hasSite owl:inverseOf org:siteOf . + +org:siteOf owl:inverseOf org:hasSite . + + + +org:hasPrimarySite a owl:ObjectProperty, rdf:Property; + + rdfs:label "primary Site"@en; + rdfs:label "site principal"@fr; + rdfs:label "sede principale"@it; + + rdfs:domain org:Organization; + rdfs:range org:Site; + rdfs:subPropertyOf org:hasSite; + + rdfs:comment """Indicates a primary site for the Organization, this is the default means by which an Organization can be contacted and is not necessarily the formal headquarters."""@en; + rdfs:comment """Indique le site principal d'une Organisation, le moyen par défaut par lequel l'Organisation peut être contactée et pas nécessairement le siège social légal."""@fr; + rdfs:comment """Indica la sede principale per l'Organization. È da considerarsi come la sede di default in cui l'Organization deve essere contattata pur non essendo necessariamente il quartier generale."""@it; + rdfs:comment "組織の主要サイトを示します。組織の窓口となりえるデフォルトの手段ですが、正式な本部とは限りません。"@ja; + rdfs:isDefinedBy ; + . + +org:hasPrimarySite rdfs:label "tiene sede principal en"@es ; + rdfs:comment "Oficina principal de la organización, la opción por defecto para ponerse en contacto con una organización, aunque no corresponde necesariamente con las oficinas centrales de la organización."@es . + + +org:hasRegisteredSite a owl:ObjectProperty, rdf:Property; + + rdfs:label "registered Site"@en; + rdfs:label "siège social"@fr; + rdfs:label "sede legale"@it; + + rdfs:domain org:FormalOrganization; + rdfs:range org:Site; + rdfs:subPropertyOf org:hasPrimarySite; + + rdfs:comment """Indicates the legally registered site for the organization, in many legal jurisdictions there is a requirement that FormalOrganizations such as Companies or Charities have such a primary designed site. """@en; + rdfs:comment """Indique l'établissement principal légalement enregistré pour l'Organisation. Dans de nombreuses juridictions existe l'obligation pour une Organisation Formelle d'avoir un tel site principal. """@fr; + rdfs:comment """Indica la sede legale per l'Organization. In molte giurisdizioni è richiesto che una FormalOrganization abbia una sede di questo tipo."""@it; + rdfs:comment "組織の法律上登録されたサイトを示し、多くの法的管轄区域では、会社や慈善団体などのFormalOrganizations(正式な組織)がそのような主要サイトを持っているという要件があります。"@ja; + rdfs:isDefinedBy ; + . + + org:hasRegisteredSite rdfs:label "tiene sede registrada en"@es ; + rdfs:comment "Oficina o sede legalmente registrada de la organización. En muchas jurisdicciones legales existe el requisito de que organizaciones formales tales como empresas u organizaciones de beneficencia tengan una sede principal de este tipo."@es . + + +org:basedAt a owl:ObjectProperty, rdf:Property; + + rdfs:label "based At"@en; + rdfs:label "basé à"@fr; + rdfs:label "basata a"@it; + + rdfs:domain foaf:Person; + rdfs:range org:Site; + + rdfs:comment """Indicates the site at which a person is based. We do not restrict the possibility that a person is based at multiple sites."""@en; + rdfs:comment """Indique le site sur lequel une personne est basée. Nous ne limitons pas le nombre de sites sur lesquels une personne peut être basée."""@fr; + rdfs:comment """Indica la sede in cui una è stabilita una persona. Non esclude la possibilità che una persona sia allocata su più sedi."""@it; + rdfs:comment "人が基礎としているサイトを示します。人が複数のサイトを基礎としている可能性を制限しません。"@ja; + rdfs:isDefinedBy ; + . + +org:basedAt rdfs:label "trabaja en la sede"@es ; + rdfs:comment "Lugar en el que trabaja una persona. No se restringe el hecho de que una persona pueda estar adscrita a múltiples ubicaciones."@es . + + +org:location a owl:DatatypeProperty, rdf:Property; + + rdfs:label "location"@en; + rdfs:label "localisation"@fr; + rdfs:label "luogo"@it; + + rdfs:domain foaf:Person; + rdfs:range xsd:string; + + rdfs:comment """Gives a location description for a person within the organization, for example a _Mail Stop_ for internal posting purposes."""@en; + rdfs:comment """Indique la description de l'endroit ou est basé une personne de l'Organisation, par exemple pour des besoins de messagerie interne (Bureau 42)."""@fr; + rdfs:comment """Indica la descrizione del luogo presso cui è possibile reperire una persona dell'organizzazione."""@it; + rdfs:comment "例えば、内部配送目的のメール・ストップ(Mail Stop)などの、組織内の人の位置記述を提供します。"@ja; + rdfs:isDefinedBy ; + . + +org:location rdfs:label "está ubicado en"@es ; + rdfs:label "está ubicada en"@es ; + rdfs:comment "Lugar o ubicación exacta de una persona en una organización con el objetivo de facilitar, por ejemplo, la entrega de correo."@es . + + +# -- Projects and other activities ----------------------------------------------------------- + + +org:OrganizationalCollaboration a owl:Class, rdfs:Class; + + rdfs:subClassOf org:Organization; + owl:equivalentClass + [ a owl:Class ; + owl:intersectionOf ( + org:Organization + [a owl:Restriction ; + owl:allValuesFrom org:Organization ; + owl:onProperty org:hasMember + ] + ) + ]; + + rdfs:label "Endeavour"@en; + rdfs:label "Partenariat"@fr; + rdfs:label "Collaborazione"@it; + + rdfs:comment """A collaboration between two or more Organizations such as a project. It meets the criteria for being an Organization in that it has an identity and defining purpose independent of its particular members but is neither a formally recognized legal entity nor a sub-unit within some larger organization. Might typically have a shorter lifetime than the Organizations within it, but not necessarily. All members are `org:Organization`s rather than individuals and those Organizations can play particular roles within the venture. Alternative names: _Project_ _Venture_ _Endeavour_ _Consortium_ _Endeavour_"""@en; + rdfs:comment """Une collaboration entre deux ou plusieurs Organisations, telle qu'un projet commun. Un partenariat peut être considéré comme Organisation dans le sens ou il possède une identité et un But propre indépendant de ceux de ses membres, mais ce n'est ni une entité légale ni une sous-unité d'une Organisation plus grande. Typiquement, elle peut avoir une durée de vie plus courte que les Organisations qui la composent, mais pas nécessairement. Tous les membres sont des `org:Organization`s plutôt que des individus et ces Organisations peuvent jouer des Rôles particuliers au sein du Partenariat. """@fr; + rdfs:comment """È una collaborazione tra due o più Organization come ad esempio un progetto. Consente di rappresentare alcune identità dell'Organization che sono fuori dallo scopo principale e non sono formalmente riconosciute. Potrebbe anche avere un ciclo di vita limitato."""@it; + rdfs:comment "プロジェクトなどの2つ以上の組織間のコラボレーション。それは、アイデンティティを有し、その特定のメンバーとは無関係に目的を定めているという点で、組織としての基準を満たしますが、正式に認識された法的実体でも、あるより大きな組織内のサブユニットでもありません。一般的には、その内部の組織よりも存続期間が短いかもしれませんが、必ずしもそうとは限りません。"@ja; + rdfs:isDefinedBy ; + . + +org:OrganizationalCollaboration rdfs:label "proyecto de cooperación empresarial"@es ; + rdfs:comment "Colaboración determinada entre dos o más organizaciones, como en el caso de un proyecto común. Cumple con los criterios de ser una organización en sí misma, en la medida en que tiene una identidad y un propósito definido independiente de sus miembros en particular, pero no es una entidad legal formalmente reconocida ni una sub-unidad dentro de una organización más grande. La duración suele ser más corta que la de las organizaciones que lo componen, pero no necesariamente. Todos sus miembros son de tipo `org:Organization` en vez de individuos, y desempeñan una actividad concreta en el marco del proyecto de cooperación."@es . + +# -- Historical information ----------------------------------------------------------- + +org:ChangeEvent a owl:Class, rdfs:Class; + rdfs:subClassOf prov:Activity; + + rdfs:label "Change Event"@en; + rdfs:label "Évènement"@fr; + rdfs:label "Evento di cambiamento"@it; + + rdfs:comment """Represents an event which resulted in a major change to an organization such as a merger or complete restructuring. It is intended for situations where the resulting organization is sufficient distinct from the original organizations that it has a distinct identity and distinct URI. Extension vocabularies should define sub-classes of this to denote particular categories of event. The instant or interval at which the event occurred should be given by `prov:startAtTime` and `prov:endedAtTime`, a description should be given by `dct:description`. """@en; + rdfs:comment """Représente un Évènement impliquant un changement majeur dans l'Organisation, comme une fusion ou une restructuration. Prévu pour des situations ou l'organisation finale est suffisamment différente des Organisations originales pour qu'elle ait une identité et une URI distinctes. Des vocabulaires d'extension devraient définir des sous-classes de celle-ci pour annoter les différentes catégories d'Évènemenents. Le moment ou l'intervalle de l'Évènement devrait être indiqué avec `prov:startAtTime` et `prov:endedAtTime`, et une description avec la classe `dct:description`. """@fr; + rdfs:comment """Rappresenta un evento risultato essere un importante cambiamento per un'organizzazione come ad esempio una fusione o una riorganizzazione. È pensato per quelle situazioni in cui l'organizzazione risultante si distingue da quella originale sufficientemente da essere rappresentata con una URI differente. Le estensioni del vocabolario dovrebbero definire le sotto-classi per esprimere particolari categorie di eventi. L'istante o l'intervallo in cui l'evento accade dovrebbe essere espresso tramite `prov:startAtTime` e`prov:endedAtTime`. Una descrizione dovrebbe essere fornita attraverso `dct:description`."""@it; + rdfs:comment "合併や完全な再編などの組織に大きな変化をもたらした出来事を表わします。これは、結果として作成される組織と元の組織とが、別のアイデンティティーと別のURIを持つに足るほど異なる状況を対象としています。"@ja; + rdfs:isDefinedBy ; + . + +org:ChangeEvent rdfs:label "evento de cambio"@es ; + rdfs:comment "Evento que da como resultado un cambio sustancial en la organización, por ejemplo, una fusión o una reestructuración total. Está pensado para situaciones en las que la organización resultante es lo suficientemente distinta de las organizaciones originales, tiene una identidad distinta y una URI también distinta. Se deberían definir subtipos de eventos mediante vocabularios específicos (Extension vocabularies) para referirse a categorías de eventos específicos. El momento o periodo en el que el evento ocurre se debería expresar mediante las propiedades `prov:startAtTime` y `prov:endedAtTime`, y una descripción del mismo se debería incluir mediante el uso de la propiedad `dct:description`."@es . + + +org:originalOrganization a owl:ObjectProperty, rdf:Property; + + rdfs:label "original organization"@en; + rdfs:label "organisation originelle"@fr; + rdfs:label "organizzazione originale"@it; + + rdfs:domain org:ChangeEvent; + rdfs:range org:Organization; + rdfs:subPropertyOf prov:used; + + rdfs:comment """Indicates one or more organizations that existed before the change event. Depending on the event they may or may not have continued to exist after the event. Inverse of `org:changedBy`."""@en; + rdfs:comment """Indique une ou plusieurs organisations qui ont existé avant un évènement de changement. Selon l'évènement, ces organisations ont pu continuer à exister ou non. Inverse de `org:changedBy`. """@fr; + rdfs:comment """Indica una o più organizzazioni pregresse rispetto a un evento di cambiamento. A seconda dell'evento, queste organizzazioni potrebbero essere esistenti dopo l'evento o aver cessato la loro esistenza. È l'inverso di `org:changedBy`."""@it; + rdfs:comment "変更のきっかけとなった出来事以前に存在した1つ以上の組織を示します。出来事によって、出来事の後にそれらは存在し続けたかも、存在し続けなかったかもしれません。"@ja; + rdfs:isDefinedBy ; + . + +org:originalOrganization rdfs:label "es organización original"@es ; + rdfs:comment "Una o más organizaciones que existían antes de que sucediera el cambio en la organización. Dependiendo del tipo de cambio, dichas organizaciones pueden haber dejado de existir o no. Es la relación inversa de `org:changedBy`."@es . + + +org:changedBy a owl:ObjectProperty, rdf:Property; + + rdfs:label "changed by"@en; + rdfs:label "modifiée par"@fr; + rdfs:label "cambiata da"@it; + + rdfs:domain org:Organization; + rdfs:range org:ChangeEvent; + + rdfs:comment """Indicates a change event which resulted in a change to this organization. Depending on the event the organization may or may not have continued to exist after the event. Inverse of `org:originalOrganization`."""@en; + rdfs:comment """Indique un évènement qui a impliqué un changement dans l'Organisation. Selon l'évènement, l'Organisation a continué à exister après l'évènement, ou pas. Inverse de `org:originalOrganization`."""@fr; + rdfs:comment """Indica un evento che ha contribuito al cambiamento di questa organizzazione. A seconda dell'evento, l'organizzazione potrebbe essere esistente dopo l'evento o aver cessato la propria esistenza. È l'inverso di `org:originalOrganization`."""@it; + rdfs:comment "この組織の変更のきっかけとなった出来事を示します。"@ja; + rdfs:isDefinedBy ; + . + +org:changedBy rdfs:label "es modificada por"@es ; + rdfs:label "es modificado por"@es ; + rdfs:comment "Evento de cambio que resulta en una modificación en la organización. Dependiendo del evento, la organización puede dejar de existir tras el cambio. Es la relación inversa de `org:originalOrganization`."@es . + + +org:originalOrganization owl:inverseOf org:changedBy . + +org:changedBy owl:inverseOf org:originalOrganization . + + + +org:resultedFrom a owl:ObjectProperty, rdf:Property; + + rdfs:label "resulted from"@en; + rdfs:label "issue de"@fr; + rdfs:label "risultato da"@it; + + rdfs:domain org:Organization; + rdfs:range org:ChangeEvent; + rdfs:subPropertyOf prov:wasGeneratedBy; + + rdfs:comment """Indicates an event which resulted in this organization. Inverse of `org:resultingOrganization`."""@en; + rdfs:comment """Indique un évènement dont est issue l'Organisation. Inverse de `org:resultingOrganization`."""@fr; + rdfs:comment """Indica l'evento che ha permesso all'organizzazione di instaurarsi. È l'inverso di `org:resultingOrganization`."""@it; + rdfs:comment "この組織になった(導いた、作成された)きっかけとなった出来事を示します。"@ja; + rdfs:isDefinedBy ; + . + +org:resultedFrom rdfs:label "es el resultado de"@es ; + rdfs:comment "Evento que tiene como resultado la creación de una organización."@es . + + +org:resultingOrganization a owl:ObjectProperty, rdf:Property; + + rdfs:label "resulted in"@en; + rdfs:label "a donné naissance à"@fr; + rdfs:label "risultato in"@it; + + rdfs:domain org:ChangeEvent; + rdfs:range org:Organization; + + rdfs:comment """Indicates an organization which was created or changed as a result of the event. Inverse of `org:resultedFrom`."""@en; + rdfs:comment """Indique une organisation qui a été créée ou a été modifiée à la suite d'un Évènement de changement. Inverse de `org:resultedFrom`."""@fr; + rdfs:comment """Indica l'organizzazione che è stata creata o mutata a seguito dell'evento. È l'inverso di `org:resultedFrom`."""@it; + rdfs:comment "出来事の結果、作成、変更された組織を示します。"@ja; + rdfs:isDefinedBy ; + . + +org:resultingOrganization rdfs:label "resulta en"@es ; + rdfs:comment "Organización que ha sido creada o modificada tras un evento específico.  Es la relación inversa de `org:resultedFrom`."@es . + + +org:resultedFrom owl:inverseOf org:resultingOrganization . + +org:resultingOrganization owl:inverseOf org:resultedFrom . + + +# Property chain to license derivation relation +prov:wasDerivedFrom owl:propertyChainAxiom (org:resultedFrom org:originalOrganization) . + + + +# -- Posts - added 2012-09-30 ----------------------------------------------------------- + +org:Post a owl:Class, rdfs:Class; + + rdfs:label "Post"@en; + rdfs:label "Poste"@fr; + rdfs:label "Impiego"@it; + + rdfs:comment """A Post represents some position within an organization that exists independently of the person or persons filling it. Posts may be used to represent situations where a person is a member of an organization ex officio (for example the Secretary of State for Scotland is part of UK Cabinet by virtue of being Secretary of State for Scotland, not as an individual person). A post can be held by multiple people and hence can be treated as a organization in its own right."""@en; + rdfs:comment """Un Poste représente une position au sein d'une Organisation qui existe indépendamment de la personne ou des personnes qui le remplissent. Les postes peuvent être utilisés pour représenter des situations où une personne est membre d'une Organisation d'office (par exemple, le Secrétaire d'Etat pour l'Ecosse fait partie du Cabinet du Royaume-Uni du fait d'être Secrétaire d'Etat pour l'Ecosse, non pas comme une personne physique). Un poste après peut être occupé par plusieurs personnes et peut donc être considéré comme une Organisation à part entière."""@fr; + rdfs:comment """Un Impiego rappresenta una posizione all'interno dell'organizzazione che esiste indipendentemente dalla persona che la ricopre. Gli impieghi possono essere utilizzati per le situazioni in cui una persona è membro di un'organizzazione o di un ufficio (ad esempio un segretario di stato). Un Impiego può essere ricoperto da più persone."""@it; + rdfs:comment "ポストは、それを埋める人(人々)とは無関係に存在する組織内のある位置を表わします。ポストは、人が職権上、組織のメンバーである状況を表わすために使用できます(例えば、スコットランド大臣は、個人としてではなく、スコットランド大臣であることにより、英国内閣の一部です)。ポストは、複数の人々によって保持されることが可能だあるため、それ自体を組織として扱うことができます。"@ja; + rdfs:isDefinedBy ; + . + +org:Post rdfs:label "puesto"@es ; + rdfs:comment "Puesto o posición que representa algún tipo de empleo dentro de una organización, que existe independientemente de la persona o personas que lo desempeñan. Esta clase puede utilizarse para representar situaciones en las que una persona es miembro de una organización ex oficio (por ejemplo, el Secretario de Estado escocés es parte del Gabinete del gobierno británico por virtud de ser Secretario de Estado en Escocia, y no como individuo). Un puesto puede ser desempeñado por múltiples individuos y de aquí que sea tratado como una organización en sí misma."@es . + +org:holds a owl:ObjectProperty, rdf:Property; + + rdfs:label "holds"@en; + rdfs:label "occupe"@fr; + rdfs:label "ricopre"@it; + + rdfs:comment """Indicates a Post held by some Agent."""@en; + rdfs:comment """Indicate un Poste occupé par un Agent."""@fr; + rdfs:comment """Indica un Impiego ricoperto da un Agent."""@it; + rdfs:comment "あるエージェントによって保持されているポストを示します。"@ja; + rdfs:domain foaf:Agent; + rdfs:range org:Post; + + # Corrected 2014-01-25 + # rdfs:subPropertyOf org:memberOf; + + rdfs:isDefinedBy ; + . + +org:holds rdfs:label "ocupa"@es ; + rdfs:comment "Puesto ocupado por algún agente."@es . + +org:heldBy a owl:ObjectProperty, rdf:Property; + + rdfs:label "held by"@en; + rdfs:label "occupé par"@fr; + rdfs:label "ricoperto da"@it; + + rdfs:comment """Indicates an Agent which holds a Post."""@en; + rdfs:comment """Indicate un Agent qui occupe le Poste."""@fr; + rdfs:comment """Indica un Agent che ricopre un Post."""@it; + rdfs:comment "ポストを保持するエージェントを示します。"@ja; + rdfs:domain org:Post; + rdfs:range foaf:Agent; + + # Corrected 2014-01-25 + # rdfs:subPropertyOf org:hasMember; + + rdfs:isDefinedBy ; + . + +org:heldBy rdfs:label "ocupado por"@es ; + rdfs:comment "Agente que ocupa un puesto."@es . + +org:holds owl:inverseOf org:heldBy . + + +org:postIn a owl:ObjectProperty, rdf:Property; + + rdfs:label "post in"@en; + rdfs:label "poste chez"@fr; + rdfs:label "impiego in"@it; + + rdfs:comment """Indicates the Organization in which the Post exists."""@en; + rdfs:comment """Indicate l'Organisation dans laquelle le Poste existe."""@fr; + rdfs:comment """Indica l'Organization in cui il Post è presente."""@it; + rdfs:comment "ポストが存在する組織を示します。"@ja; + rdfs:domain org:Post; + rdfs:range org:Organization; + + rdfs:isDefinedBy ; + . + +org:postIn rdfs:label "es un puesto en"@es ; + rdfs:comment "Organización en la que existe el puesto."@es . + +org:hasPost a owl:ObjectProperty, rdf:Property; + + rdfs:label "post"@en; + rdfs:label "possède un poste"@fr; + rdfs:label "impiego"@it; + + rdfs:comment """Indicates a Post which exists within the Organization."""@en; + rdfs:comment """Indicate un Poste qui existe dans l'Organisation."""@fr; + rdfs:comment """Indica il Post che è presente in una Organization."""@it; + rdfs:comment "組織内に存在するポストを示します。"@ja; + rdfs:domain org:Organization; + rdfs:range org:Post; + + rdfs:isDefinedBy ; + . + +org:hasPost rdfs:label "tiene puesto"@es ; + rdfs:comment "Posición que existe en una organización."@es . + +org:postIn owl:inverseOf org:hasPost . + + +# -- Disjointness of backbone ----------------------------------------------------------- + + + +org:Organization owl:disjointWith org:Role . + +org:Organization owl:disjointWith org:Membership . + +org:Organization owl:disjointWith org:Site . + +org:Organization owl:disjointWith org:ChangeEvent . + + + +org:Role owl:disjointWith org:Membership . + +org:Role owl:disjointWith org:Site . + +org:Role owl:disjointWith org:ChangeEvent . + + + +org:Membership owl:disjointWith org:Site . + +org:Membership owl:disjointWith org:ChangeEvent . + + + +org:Site owl:disjointWith org:ChangeEvent .