graphdb-workbench
Version:
The web application for GraphDB APIs
500 lines (465 loc) • 28.7 kB
HTML
<link href="css/graphs-vizualizations.css?v=1.11.3-TR1" rel="stylesheet"/>
<link href="css/rdf-details-side-panel.css?v=1.11.3-TR1" rel="stylesheet"/>
<link href="css/lib/ng-tags-input/ng-tags-input.min.css?v=1.11.3-TR1" rel="stylesheet"/>
<link href="js/lib/d3-tip/d3-tip.css?v=1.11.3-TR1" rel="stylesheet"/>
<div class="container-fluid">
<h1>
{{title}}
<span class="btn btn-link"
uib-popover-template="'js/angular/templates/titlePopoverTemplate.html'"
popover-trigger="mouseenter"
popover-placement="bottom-right"
popover-append-to-body="true"><span class="icon-info"></span></span>
</h1>
<div core-errors></div>
<div system-repo-warning></div>
<div class="alert alert-danger" ng-show="repositoryError">
<p>The currently selected repository cannot be used for queries due to an error:</p>
<p>{{repositoryError}}</p>
</div>
<div class="toolbar-holder" ng-show="configLoaded && getActiveRepository() && 'SYSTEM' !== getActiveRepository()">
<button ng-show="!queryResultsMode && !noGoHome" class="btn btn-link p-0 return-home-btn"
uib-tooltip="Back to visual graph home"
tooltip-placement="bottom"
tooltip-trigger="mouseenter"
ng-click="goToHome()">
<em class="icon-arrow-up icon-2x"></em>
</button>
<button ng-show="!queryResultsMode && configLoaded.startMode == 'search'" class="btn btn-link p-0"
uib-tooltip="Search another resource"
tooltip-placement="bottom"
tooltip-trigger="mouseenter"
ng-disabled="!nodeSelected"
ng-click="searchVisible = !searchVisible">
<em class="icon-search icon-2x"></em>
</button>
<button class="btn btn-link p-0"
uib-tooltip="Click to rotate the graph to the left"
tooltip-placement="bottom"
tooltip-trigger="mouseenter"
ng-disabled="!nodeSelected"
ng-click="rotate(true)">
<em class="icon-rotate-left icon-2x"></em>
</button>
<button class="btn btn-link p-0"
uib-tooltip="Click to rotate the graph to the right"
tooltip-placement="bottom"
tooltip-trigger="mouseenter"
ng-disabled="!nodeSelected"
ng-click="rotate(false)">
<em class="icon-rotate-right icon-2x"></em>
</button>
<button class="btn btn-link p-0"
uib-tooltip="{{numberOfPinnedNodes > 0 ? 'Unpin all nodes' : 'Pin down all nodes'}}"
ng-class="numberOfPinnedNodes > 0 ? 'active' : ''"
tooltip-placement="bottom"
tooltip-trigger="mouseenter"
ng-disabled="!nodeSelected"
ng-click="togglePinAllNodes()">
<em class="icon-pin icon-2x"></em>
</button>
<button class="btn btn-link p-0"
uib-tooltip="Save graph snapshot"
tooltip-placement="bottom"
tooltip-trigger="mouseenter"
ng-if="isUser() && !embedded"
ng-disabled="!nodeSelected"
ng-click="saveOrUpdateGraph()">
<em class="icon-save icon-2x"></em>
</button>
<button class="btn btn-link p-0"
uib-tooltip="Click to configure the view"
tooltip-placement="bottom"
tooltip-trigger="mouseenter"
ng-if="isUser()"
ng-click="showSettings()">
<em class="icon-settings icon-2x visual-graph-settings-btn"></em>
</button>
</div>
<div class="search-bar" ng-show="getActiveRepository() && !isLoadingLocation() && hasActiveLocation() && 'SYSTEM' !== getActiveRepository()">
<div class="row slider mb-2"
ng-show="configLoaded.startMode == 'search' && (searchVisible || !nodeSelected)" ng-cloak>
<div class="col-lg-12">
<div class="card">
<div class="card-block">
<h3>{{configLoaded.name}}</h3>
<p>Search for an IRI to view it.
<span ng-if="configLoaded.name != defaultGraphConfig.name">This is a user defined advanced configuration.</span>
<p ng-if="configLoaded.hint">Hint: {{configLoaded.hint}}</p>
</p>
<search-resource-input class="incontext-search-rdf-resource"
namespacespromise="getNamespacesPromise"
autocompletepromisestatus="getAutocompletePromise"
text-button=""
visual-button="Show"
visual-callback="openUri(uri)"
empty="empty">
</search-resource-input>
</div>
</div>
</div>
</div>
<div ng-show="!configLoaded">
<div ng-if="getActiveRepository() && !isLoadingLocation() && hasActiveLocation()"
ng-cloak>
<div class="card mb-2">
<div class="card-block">
<h3>Easy graph</h3>
<p>Search for an IRI to view it and configure the visualisation through the UI without using SPARQL</p>
<search-resource-input class="search-rdf-resources"
namespacespromise="getNamespacesPromise"
autocompletepromisestatus="getAutocompletePromise"
text-button=""
visual-button="Show"
visual-callback="easyGraphSearch(uri)"
empty="empty">
</search-resource-input>
</div>
</div>
<div ng-show="isFreeAccessEnabled() || isUser()" class="card mb-2">
<div class="card-block graph-configurations" ng-init="getGraphConfigs()">
<div class="clearfix">
<a ng-if="isUser()" ng-href="graphs-visualizations/config/save" class="btn btn-link pull-right create-graph-config"><span class="icon-plus"></span> Create graph config</a>
<h3>Advanced graph configurations</h3>
<p>Define how the visualisation works by writing your own SPARQL queries</p>
</div>
<div ng-show="graphConfigs.length == 0">No graph configs</div>
<table class="table table-hover mb-0" aria-describedby="Graph configurations table">
<tbody>
<tr ng-repeat="config in graphConfigs">
<td width="20">
<a href ng-click="goToGraphConfig(config)">
<img ng-if="config.startMode == 'search'" src="css/images/search.png?v=1.11.3-TR1" alt="" width="64" uib-popover="Starting point - Search box" popover-trigger="mouseenter">
<img ng-if="config.startMode == 'node'" src="css/images/node.png?v=1.11.3-TR1" alt="" width="64" uib-popover="Starting point - Fixed resource" popover-trigger="mouseenter">
<img ng-if="config.startMode == 'query'" src="css/images/query.png?v=1.11.3-TR1" alt="" width="64" uib-popover="Starting point - Query results" popover-trigger="mouseenter">
</a>
</td>
<td>
<h5>
<a href ng-click="goToGraphConfig(config)" uib-popover={{config.description}} popover-trigger="mouseenter">{{config.name}}</a>
</h5>
<samp class="text-muted small text-overflow d-block" ng-if="config.startMode == 'query'">{{config.startGraphQuery}}</samp>
<samp class="text-muted small text-overflow d-block" ng-if="config.startMode == 'node'">{{config.startIRI}}</samp>
</td>
<td class="text-xs-right" ng-if="isUser() && config.owner === principal().username">
<a ng-href="graphs-visualizations/config/save/{{config.id}}" class="btn btn-link" uib-tooltip="Edit configuration"><span class="icon-edit"></span></a>
<button type="button" ng-click="deleteConfig(config)" class="btn btn-link delete-config" uib-tooltip="Delete configuration"><span class="icon-trash"></span></button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div ng-show="isFreeAccessEnabled() || isUser()" class="card mb-2">
<div class="card-block">
<h3 class="mb-2">Saved graphs</h3>
<div ng-show="savedGraphs.length == 0">No saved visual graph snapshots</div>
<table class="table table-hover mb-0" ng-init="refreshSavedGraphs()" aria-describedby="Saved graphs table">
<tbody>
<tr ng-repeat="graph in savedGraphs">
<td>
<h5><a href ng-click="loadSavedGraph(graph)">{{graph.name}}</a></h5>
</td>
<td>
<span ng-show="graph.config != 'default'">Advanced: <strong>{{findConfigById(graph.config).name}}</strong></span>
<span ng-show="graph.config == 'default'">Easy graph</span>
</td>
<td class="text-xs-right">
<button class="btn btn-link"
uib-tooltip="Get URL to graph" tooltip-trigger="mouseenter"
ng-click="copyToClipboardSavedGraph(graph)">
<span class="icon-link"></span>
</button>
<button class="btn btn-link"
ng-if="isUser() && graph.owner === principal().username"
uib-tooltip="Rename graph" tooltip-trigger="mouseenter"
ng-click="renameSavedGraph(graph)">
<span class="icon-edit"></span>
</button>
<button class="btn btn-link"
ng-if="isUser() && graph.owner === principal().username"
uib-tooltip="Delete graph" tooltip-trigger="mouseenter"
ng-click="deleteSavedGraph(graph)">
<span class="icon-trash"></span>
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<keyboard-shortcuts template-url="res/graphexplore/keyboard-shortcuts.html"></keyboard-shortcuts>
<div class="graph-visualization" ng-hide="loading || !nodeSelected"></div>
<div onto-loader-new
ng-show="loading"
size="100"
style="height: 75vh; display: flex;">
</div>
<pageslide
ps-class="rdf-info-side-panel node-info predicate-info"
ps-open="showInfoPanel"
onopen="onopen"
onclose="onclose"
ps-side="right"
ps-custom-height="calc(100vh - 55px)"
ps-size="{{pageslideExpanded ? '80vw' : '25vw'}}">
<div class="rdf-side-panel-content break-word-alt p-1 pt-2">
<span class="toggle-sidepanel" title="Collapse sidepanel" ng-click="toggleSidePanel()">
<em ng-class="pageslideExpanded ? 'icon-caret-right' : 'icon-caret-left'"></em>
</span>
<button class="close mb-1 ml-1" ng-click="closeInfoPanel()"></button>
<h3 class="hovered-parent" ng-if="showPredicates">
Predicates
</h3>
<ul class="rdf-list tab-content" ng-if="showPredicates">
<li ng-repeat='predicate in predicates track by $index' class="item clearfix break-word-alt">
<div role="{{predicate.partOfTriple ? 'button' : ''}}"
ng-click="clickLink(predicate)">
<em class="{{predicate.partOfTriple ? 'fa fa-long-arrow-right triple-pred' : ''}}"></em>
<span id="{{predicate.linkId + predicate.nodeIndex}}">{{splitPredicate(predicate.value)}}</span>
</div>
</li>
</ul>
<div ng-if="showFilter" class="filter-sidepanel tab-content">
<h4>Graph settings</h4>
<div>
<div class="form-group mb-2">
<label uib-tooltip="Limit the number of links when often they are too many">Maximum links to show</label>
<div class="form-inline">
<button type="button" class="btn btn-link px-0" ng-disabled="settings['linksLimit'] < 1"
ng-click="changeLimit(-1)">
<span class="icon-minus"></span>
</button>
<input type="number" class="form-control input-number" size="20"
ng-model="settings['linksLimit']"
min="0" max="1000" class="ng-pristine ng-valid ng-valid-number"
ng-change="validateLinksLimit()">
<button type="button" class="btn btn-link px-0" ng-disabled="settings['linksLimit'] > 999"
ng-click="changeLimit(1)">
<span class="icon-plus"></span>
</button>
<span style="margin-top: 5px" ng-if="invalidLimit"
class="idError alert alert-danger"
uib-tooltip="{{INVALID_LINKS_TOOLTIP}}">
{{INVALID_LINKS_MSG}}
</span>
</div>
</div>
<div class="form-group mb-2" ng-show="shouldShowSettings()">
<label uib-tooltip="Preferred languages for node and predicates labels">Preferred languages</label>
<div class="input-group preferred-languages">
<tags-input class="wb-tags-input" ng-model="settings['languagesMap']" min-length="2" add-on-space="true"
add-on-comma="true" placeholder="Add a language tag"></tags-input>
</div>
</div>
<div class="form-group mb-2">
<div class="checkbox">
<label uib-tooltip="Include/Exclude predicates from owl: rdf: rdfs: sesame: dul: prov: fibo: wd:">
<input type="checkbox" ng-model="settings['includeSchema']" class="include-schema-statements">
Include schema statements
</label>
</div>
</div>
<div class="form-group mb-2">
<div class="checkbox">
<label uib-tooltip="Include/exclude inferred statements">
<input type="checkbox" ng-model="settings['includeInferred']" class="include-inferred-statements">
Include inferred statements
</label>
</div>
</div>
<!-- Enable-Disable owl:sameAs checkbox -->
<div class="form-group mb-2">
<div class="checkbox" uib-tooltip="{{shouldDisableSameAs() ? 'Requires \'Include Inferred\'!' : ''}}">
<label style="{{'opacity: ' + (!settings['includeInferred'] ? '0.5' : '1')}}" >
<input id="sameAsCheck" type="checkbox" ng-model="settings['sameAsState']"
ng-disabled="shouldDisableSameAs()">
Expand results over owl:sameAs
</label>
</div>
</div>
<!-- Enable-Disable owl:sameAs checkbox -->
<div class="form-group mb-2">
<div class="checkbox">
<label uib-tooltip="Show predicate labels as links titles">
<input type="checkbox" class="show-predicate-labels" ng-model="settings['showLinksText']">
Show predicate labels
</label>
</div>
</div>
<uib-tabset active="active" ng-show="shouldShowSettings()">
<uib-tab>
<uib-tab-heading class="nav-item"
tooltip-placement="bottom"
tooltip-trigger="mouseenter"><span class="nav-link">Types</span></uib-tab-heading>
<div class="form-group mb-2 mt-1">
<label uib-tooltip="Types of nodes to show with preference when there are too many nodes">Preferred types</label>
<div>
<tags-input class="preferred-types wb-tags-input" ng-model="settings['preferredTypesMap']" min-length="3" add-on-space="true"
add-on-comma="true" placeholder="Add preferred type"
on-tag-adding="validateTag($tag, 'Preferred types', false)"
on-tag-added="addedTag($tag)"></tags-input>
</div>
</div>
<div class="form-group mb-2">
<div class="checkbox">
<label uib-tooltip="Show only nodes of the preferred types">
<input type="checkbox" class="show-preferred-types-only" ng-model="settings['preferredTypesOnly']">
Show preferred types only
</label>
</div>
</div>
<div class="form-group">
<label uib-tooltip="Types of nodes to exclude from the visual graph">Ignored types</label>
<div>
<tags-input class="ignored-types wb-tags-input" ng-model="settings['rejectedTypesMap']" min-length="3" add-on-space="true"
add-on-comma="true" placeholder="Add ignored type"
on-tag-adding="validateTag($tag, 'Ignored types', false)"
on-tag-added="addedTag($tag)"></tags-input>
</div>
</div>
</uib-tab>
<uib-tab>
<uib-tab-heading class="nav-item"
tooltip-placement="bottom"
tooltip-trigger="mouseenter"><span class="nav-link predicates-tab">Predicates</span></uib-tab-heading>
<div class="form-group mb-2 mt-1">
<div>
<label uib-tooltip="Predicates to show with preference when there are too many links">Preferred predicates</label>
<tags-input class="preferred-predicates wb-tags-input" ng-model="settings['preferredPredicatesMap']" min-length="3"
add-on-space="true"
add-on-comma="true" placeholder="Add preferred predicate"
on-tag-adding="validateTag($tag, 'Preferred predicates', false)"
on-tag-added="addedTag($tag)"></tags-input>
</div>
</div>
<div class="form-group mb-2">
<div class="checkbox">
<label uib-tooltip="Show only links of the preferred predicates">
<input type="checkbox" class="show-preferred-predicates-only" ng-model="settings['preferredPredicatesOnly']">
Show preferred predicates only
</label>
</div>
</div>
<div class="form-group ">
<label uib-tooltip="Ignored predicates will not appear as links in the visual graph but will be listed as instance properties when you click on a node">Ignored predicates</label>
<div>
<tags-input class="ignored-predicates wb-tags-input" ng-model="settings['rejectedPredicatesMap']" min-length="3"
add-on-space="true"
add-on-comma="true" placeholder="Add ignored predicate"
on-tag-adding="validateTag($tag, 'Ignored predicates', true)"
on-tag-added="addedTag($tag)"
template="ignored-predicates-template"
tag-class="getTagClass($tag.text)"></tags-input>
</div>
</div>
</uib-tab>
</uib-tabset>
<div class="mt-1">
<button type="button" class="btn btn-secondary btn-lg reset-settings" ng-click="resetSettings()">Reset</button>
<button type="submit" class="btn btn-primary btn-lg save-settings-btn" ng-click="updateSettings()">Save</button>
</div>
<script type="text/ng-template" id="ignored-predicates-template">
<div class="tag-template">
<div uib-tooltip="{{$getDisplayText().endsWith('*') ? 'IRIs that end with * are treated as wildcards and will match any IRI that begins with the text before the *' : ''}}">
<span>{{$getDisplayText()}}</span>
<a class="remove-button" ng-click="$removeTag()">×</a>
</div>
</div>
</script>
</div>
</div>
<div ng-if="showNodeInfo" class="tab-content">
<h3 class="hovered-parent">
<a class="uri" rel="noopener" target="_blank" href="resource?{{resourceType}}={{encodedIri}}" style="text-decoration: underline;">{{rdfsLabel}}</a>
<button class="btn btn-link btn-sm px-0 hovered-item"
style="opacity: 1"
ng-click="copyToClipboard(nodeIri)"
title="Copy to Clipboard">
<span class="icon-link"></span>
</button>
</h3>
<rdfs-comment-label
rdfs-comment="rdfsComment"
expanded="expanded"
always-expanded="pageslideExpanded">
</rdfs-comment-label>
<div class="media mb-1">
<div class="media-left"
uib-tooltip="Labels"
tooltip-placement="top"
tooltip-trigger="mouseenter">
<em class="icon-tag icon-lg" aria-hidden="true"></em>
</div>
<div class="media-body">
<span ng-repeat="l in nodeLabels">
{{l.label}}<span class="language-tag" ng-if="l.lang">{{l.lang}}</span>
<span ng-if="!$last"> · </span>
</span>
</div>
</div>
<div class="break-word-alt">
<strong>Types: </strong><em class="text-muted" ng-if="!nodeTypes.length">No types</em><br>
<ul class="list-inline">
<li class="list-inline-item" ng-repeat="nodeType in nodeTypes"
ng-class="{'lead d-block': $index == 0}">
<span class="tag tag-default tag-inverse"
ng-attr-style="{{'background-color: ' + getColor(nodeType)}}">{{replaceIRIWithPrefix(nodeType)}}</span>
</li>
</ul>
</div>
<div class="mb-1" ng-show="rdfRank >= 0">
<strong>RDF rank: </strong>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="{{rdfRank}}"
aria-valuemin="0" aria-valuemax="1" style="word-break: normal; width: {{rdfRank*100}}%">
{{rdfRank}}
</div>
</div>
</div>
<div ng-if="nodeImage" class="rdf-image mb-1"
ng-attr-style="{{'background-image: url(' + nodeImage + ')'}}">
</div>
<list-items-search-filter
filter-query-obj="propertiesQueryObj"
filter-function="propertiesFilterFunc"
list-items-obj="propertiesObj"
list-items-not-filtered="propertiesNotFiltered"
search-placeholder={{propertiesSearchPlaceholder}}>
</list-items-search-filter>
<div ng-switch on="propertiesObj.items.length">
<p ng-switch-when="0" class="alert alert-warning">No properties found</p>
<div ng-switch-default ui-scroll-viewport class="rdf-list">
<div ui-scroll='item in datasource' adapter="adapterContainer.adapter"
class="datasource mb-1">
<div class="item clearfix break-word-alt small">{{item.key}}</div>
<div class="data-value">
<a ng-if="item.value[0].t === 'i'" href="#" ng-click="openIRI(item.value[0].v, $event)" ng-bind="item.value[0].v"></a>
<span ng-if="item.value[0].t !== 'i'" ng-bind="item.value[0].v"></span>
<span class="language-tag" ng-if="item.value[0].t !== 'lt:http://www.w3.org/2001/XMLSchema#string'" ng-bind="replaceIRIWithPrefix(getLiteralFromPropValue(item.value[0].t))"></span>
<button class="btn btn-link btn-sm" type="button"
ng-if="item.value.length > 1"
ng-click="toggleMoreInfo($event, this)">
Show {{item.value.length - 1}} more <span
class="icon-caret-down"></span>
</button>
</div>
<ul class="hidden-data-value text-secondary">
<li class="small"
ng-repeat="value in item.value track by $index"
ng-hide="$index == 0">
<a ng-if="value.t === 'i'" href="#" ng-click="openIRI(value.v, $event)" ng-bind="value.v"></a>
<span ng-if="value.t !== 'i'" ng-bind="value.v"></span>
<span class="language-tag" ng-if="value.t !== 'lt:http://www.w3.org/2001/XMLSchema#string'" ng-bind="replaceIRIWithPrefix(getLiteralFromPropValue(value.t))"></span>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</pageslide>