This is an automated email from the ASF dual-hosted git repository. kinow pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/jena.git
commit d7d2b38365f4e2535372773cc0d7ed9ab6a3dea3 Author: Bruno P. Kinoshita <[email protected]> AuthorDate: Mon Mar 14 21:48:01 2022 +1300 [JENA-2312] Use the service endpoint in the URL used by the UI to query the backend --- .../jena-fuseki-ui/src/mixins/current-dataset.js | 89 ++++++++++++++++++++++ .../jena-fuseki-ui/src/services/fuseki.service.js | 12 +-- jena-fuseki2/jena-fuseki-ui/src/utils/index.js | 25 ++++++ .../jena-fuseki-ui/src/views/dataset/Edit.vue | 20 ++--- .../jena-fuseki-ui/src/views/dataset/Info.vue | 72 +++++------------ .../jena-fuseki-ui/src/views/dataset/Query.vue | 34 ++++++--- .../jena-fuseki-ui/src/views/dataset/Upload.vue | 24 +++--- 7 files changed, 183 insertions(+), 93 deletions(-) diff --git a/jena-fuseki2/jena-fuseki-ui/src/mixins/current-dataset.js b/jena-fuseki2/jena-fuseki-ui/src/mixins/current-dataset.js new file mode 100644 index 0000000..2859839 --- /dev/null +++ b/jena-fuseki2/jena-fuseki-ui/src/mixins/current-dataset.js @@ -0,0 +1,89 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BUS } from '@/events' + +/** + * A mixin for views and components that need to have the current dataset loaded. The + * dataset is loaded by its name, which is a prop for the view or component. + */ + +export default { + props: { + datasetName: { + type: String, + required: true + } + }, + data () { + return { + isDatasetStatsLoading: true, + serverData: { + datasets: [] + } + } + }, + computed: { + currentDataset () { + return this.serverData.datasets.find(dataset => dataset['ds.name'] === `/${this.datasetName}`) + }, + services () { + if (!this.currentDataset || !this.currentDataset['ds.services']) { + return [] + } + return this.currentDataset['ds.services'] + .slice() + .sort((left, right) => { + return left['srv.type'].localeCompare(right['srv.type']) + }) + .reduce((acc, cur) => { + acc[cur['srv.type']] = cur + return acc + }, {}) + } + }, + methods: { + loadCurrentDataset () { + this.isDatasetStatsLoading = true + this.$fusekiService + .getServerData() + .then(serverData => { + this.serverData = serverData + }) + this.$fusekiService + .getDatasetStats(this.datasetName) + .then(datasetStats => { + this.datasetStats = datasetStats + }) + this.isDatasetStatsLoading = false + } + }, + beforeRouteEnter (from, to, next) { + next(async vm => { + BUS.$on('connection:reset', vm.loadCurrentDataset) + vm.loadCurrentDataset() + }) + }, + async beforeRouteUpdate (from, to, next) { + this.loadCurrentDataset() + next() + }, + beforeRouteLeave (from, to, next) { + BUS.$off('connection:reset') + next() + } +} diff --git a/jena-fuseki2/jena-fuseki-ui/src/services/fuseki.service.js b/jena-fuseki2/jena-fuseki-ui/src/services/fuseki.service.js index 60a332d..eaf7414 100644 --- a/jena-fuseki2/jena-fuseki-ui/src/services/fuseki.service.js +++ b/jena-fuseki2/jena-fuseki-ui/src/services/fuseki.service.js @@ -87,15 +87,15 @@ class FusekiService { return response.data } - async getDatasetSize (datasetName) { + async getDatasetSize (datasetName, endpoint) { const promisesResult = await Promise.all([ axios - .get(this.getFusekiUrl(`/${datasetName}/sparql`), { + .get(this.getFusekiUrl(`/${datasetName}/${endpoint}`), { params: { query: DATASET_SIZE_QUERY_1 } }), - axios.get(this.getFusekiUrl(`/${datasetName}/sparql`), { + axios.get(this.getFusekiUrl(`/${datasetName}/${endpoint}`), { params: { query: DATASET_SIZE_QUERY_2 } @@ -160,15 +160,15 @@ class FusekiService { return axios.get(this.getFusekiUrl('/$/tasks')) } - async countGraphsTriples (datasetName) { + async countGraphsTriples (datasetName, endpoint) { const promisesResult = await Promise.all([ axios - .get(this.getFusekiUrl(`/${datasetName}/sparql`), { + .get(this.getFusekiUrl(`/${datasetName}/${endpoint}`), { params: { query: DATASET_COUNT_GRAPH_QUERY_1 } }), - axios.get(this.getFusekiUrl(`/${datasetName}/sparql`), { + axios.get(this.getFusekiUrl(`/${datasetName}/${endpoint}`), { params: { query: DATASET_COUNT_GRAPH_QUERY_2 } diff --git a/jena-fuseki2/jena-fuseki-ui/src/utils/index.js b/jena-fuseki2/jena-fuseki-ui/src/utils/index.js new file mode 100644 index 0000000..6e58a59 --- /dev/null +++ b/jena-fuseki2/jena-fuseki-ui/src/utils/index.js @@ -0,0 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export function displayError (vm, error) { + console.error(error) + vm.$bvToast.toast(`${error}`, { + title: 'Error', + noAutoHide: true, + appendToast: false + }) +} diff --git a/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Edit.vue b/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Edit.vue index c1e83d7..6ada112 100644 --- a/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Edit.vue +++ b/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Edit.vue @@ -118,6 +118,8 @@ import { } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' import { library } from '@fortawesome/fontawesome-svg-core' +import currentDatasetMixin from '@/mixins/current-dataset' +import { displayError } from '@/utils' library.add(faTimes, faCheck) @@ -132,12 +134,9 @@ export default { FontAwesomeIcon }, - props: { - datasetName: { - type: String, - required: true - } - }, + mixins: [ + currentDatasetMixin + ], data () { return { @@ -218,13 +217,9 @@ export default { this.code = '' this.selectedGraph = '' try { - this.graphs = await this.$fusekiService.countGraphsTriples(this.datasetName) + this.graphs = await this.$fusekiService.countGraphsTriples(this.datasetName, this.services.query['srv.endpoints'][0]) } catch (error) { - this.$bvToast.toast(`${error}`, { - title: 'Error', - noAutoHide: true, - appendToast: false - }) + displayError(this, error) } finally { this.loadingGraphs = false this.loadingGraph = false @@ -243,6 +238,7 @@ export default { const result = await this.$fusekiService.fetchGraph(this.datasetName, graphName) this.code = result.data } catch (error) { + console.error(error) this.$bvToast.toast(`${error}`, { title: 'Error', noAutoHide: true, diff --git a/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Info.vue b/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Info.vue index 2daed94..66c4720 100644 --- a/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Info.vue +++ b/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Info.vue @@ -149,7 +149,8 @@ <script> import Menu from '@/components/dataset/Menu' -import { BUS } from '@/events' +import { displayError } from '@/utils' +import currentDatasetMixin from '@/mixins/current-dataset' export default { name: 'DatasetInfo', @@ -158,24 +159,15 @@ export default { Menu }, - props: { - datasetName: { - type: String, - required: true - } - }, + mixins: [ + currentDatasetMixin + ], data () { return { - serverData: { - datasets: [] - }, - datasetStats: { - - }, + datasetStats: {}, datasetSize: null, isDatasetSizeLoading: false, - isDatasetStatsLoading: true, popoverShow: false, statsFields: [ { @@ -219,17 +211,6 @@ export default { }, computed: { - currentDataset () { - return this.serverData.datasets.find(dataset => dataset['ds.name'] === `/${this.datasetName}`) - }, - services () { - if (!this.currentDataset || !this.currentDataset['ds.services']) { - return [] - } - return this.currentDataset['ds.services'].slice().sort((left, right) => { - return left['srv.type'].localeCompare(right['srv.type']) - }) - }, statsItems () { if (!this.datasetStats || !this.datasetStats.datasets) { return [] @@ -284,46 +265,29 @@ export default { beforeRouteEnter (from, to, next) { next(async vm => { - BUS.$on('connection:reset', vm.initializeData) - vm.initializeData() + vm.datasetSize = null }) }, async beforeRouteUpdate (from, to, next) { - this.initializeData() - next() - }, - - beforeRouteLeave (from, to, next) { - BUS.$off('connection:reset') + this.datasetSize = null next() }, methods: { async countTriplesInGraphs () { this.popoverShow = false - this.isDatasetStatsLoading = true this.isDatasetSizeLoading = true - this.datasetSize = await this.$fusekiService.getDatasetSize(this.datasetName) - this.isDatasetSizeLoading = false - this.$refs['count-triples-button'].disabled = this.isDatasetSizeLoading - this.datasetStats = await this.$fusekiService.getDatasetStats(this.datasetName) - this.isDatasetStatsLoading = false - }, - initializeData () { - this.isDatasetStatsLoading = true - this.$fusekiService - .getServerData() - .then(serverData => { - this.serverData = serverData - }) - this.$fusekiService - .getDatasetStats(this.datasetName) - .then(datasetStats => { - this.datasetStats = datasetStats - }) - this.isDatasetStatsLoading = false - this.datasetSize = null + try { + this.datasetSize = await this.$fusekiService.getDatasetSize(this.currentDataset['ds.name'], this.services.query['srv.endpoints'][0]) + this.$refs['count-triples-button'].disabled = this.isDatasetSizeLoading + this.datasetStats = await this.$fusekiService.getDatasetStats(this.datasetName) + } catch (error) { + displayError(this, error) + } finally { + this.isDatasetSizeLoading = false + this.$refs['count-triples-button'].disabled = this.isDatasetSizeLoading + } } } } diff --git a/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Query.vue b/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Query.vue index fa9b11e..3d3f153 100644 --- a/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Query.vue +++ b/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Query.vue @@ -120,6 +120,7 @@ import Yasqe from '@triply/yasqe' import Yasr from '@triply/yasr' import queryString from 'query-string' import Vue from 'vue' +import currentDatasetMixin from '@/mixins/current-dataset' const SELECT_TRIPLES_QUERY = `SELECT ?subject ?predicate ?object WHERE { @@ -145,19 +146,15 @@ export default { Menu }, - props: { - datasetName: { - type: String, - required: true - } - }, + mixins: [ + currentDatasetMixin + ], data () { return { loading: true, yasqe: null, yasr: null, - datasetUrl: `/${this.datasetName}/sparql`, contentTypeSelect: 'application/sparql-results+json', contentTypeSelectOptions: [ { value: 'application/sparql-results+json', text: 'JSON' }, @@ -192,6 +189,15 @@ export default { } }, + computed: { + datasetUrl () { + if (!this.datasetName || !this.services.query || !this.services.query['srv.endpoints'] || this.services.query['srv.endpoints'].length === 0) { + return '' + } + return `/${this.datasetName}/${this.services.query['srv.endpoints'][0]}` + } + }, + created () { this.$nextTick(() => { setTimeout(() => { @@ -213,7 +219,7 @@ export default { showQueryButton: true, resizeable: false, requestConfig: { - endpoint: this.$fusekiService.getFusekiUrl(`/${vm.datasetName}/sparql`) + endpoint: this.$fusekiService.getFusekiUrl(this.datasetUrl) }, /** * Based on YASGUI code, but modified to avoid parsing the Vue Route query @@ -264,13 +270,19 @@ export default { watch: { datasetUrl: function (val, oldVal) { - this.yasqe.options.requestConfig.endpoint = this.$fusekiService.getFusekiUrl(this.datasetUrl) + if (this.yasqe) { + this.yasqe.options.requestConfig.endpoint = this.$fusekiService.getFusekiUrl(this.datasetUrl) + } }, contentTypeSelect: function (val, oldVal) { - this.yasqe.options.requestConfig.acceptHeaderSelect = this.contentTypeSelect + if (this.yasqe) { + this.yasqe.options.requestConfig.acceptHeaderSelect = this.contentTypeSelect + } }, contentTypeGraph: function (val, oldVal) { - this.yasqe.options.requestConfig.acceptHeaderGraph = this.contentTypeGraph + if (this.yasqe) { + this.yasqe.options.requestConfig.acceptHeaderGraph = this.contentTypeGraph + } } }, diff --git a/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Upload.vue b/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Upload.vue index 827b1dc..55cf352 100644 --- a/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Upload.vue +++ b/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Upload.vue @@ -25,7 +25,10 @@ <Menu :dataset-name="datasetName" /> </b-card-header> <b-card-body> - <div> + <div v-if="!this.services['gsp-rw'] || this.services['gsp-rw'].length === 0"> + <b-alert show variant="warning">No service for Graph Store Protocol configured</b-alert> + </div> + <div v-else> <div v-show="$refs.upload && $refs.upload.dropActive" class="drop-active"> <h3>Drop files to upload</h3> </div> @@ -172,6 +175,7 @@ import FileUpload from 'vue-upload-component' import { library } from '@fortawesome/fontawesome-svg-core' import { faPlus, faUpload, faTimesCircle, faMinusCircle } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' +import currentDatasetMixin from '@/mixins/current-dataset' library.add(faPlus, faUpload, faTimesCircle, faMinusCircle) @@ -184,12 +188,9 @@ export default { FileUpload }, - props: { - datasetName: { - type: String, - required: true - } - }, + mixins: [ + currentDatasetMixin + ], data () { return { @@ -211,8 +212,7 @@ export default { name: 'file', headers: { // e.g. CSRF headers }, - data: { - }, + data: {}, autoCompress: 1024 * 1024, uploadAuto: false, isOption: false @@ -269,8 +269,12 @@ export default { }) }, postActionUrl () { + if (!this.services['gsp-rw'] || this.services['gsp-rw'].length === 0) { + return '' + } const params = (this.form.datasetGraphName && this.form.datasetGraphName !== '') ? `?graph=${this.form.datasetGraphName}` : '' - return this.$fusekiService.getFusekiUrl(`/${this.datasetName}/data${params}`) + const dataEndpoint = this.services['gsp-rw']['srv.endpoints'].find(endpoint => endpoint !== '') || '' + return this.$fusekiService.getFusekiUrl(`/${this.datasetName}/${dataEndpoint}${params}`) } },
