Unverified Commit 143db709 authored by Alberto Nale's avatar Alberto Nale Committed by GitHub
Browse files

[KNOWAGE-7048][KNOWAGE-7055][KNOWAGE-7064][KNOWAGE-7062][KNOWAGE-7029][KNOWAGE-7034][KNOWAGE-7076]

KNOWAGE-7048
KNOWAGE-7055

KNOWAGE-7064
Changed the button icon to reload because there is no non premium icon available that is similar

KNOWAGE-7062
Added the extra check for scenario tag

KNOWAGE-7029
Added an extra check to see if the measure is editable

KNOWAGE-7034
No longer reloading the preview if there was an error

KNOWAGE-7076
Added max width so truncate would show up
parents 3733183e c8b94cb4
......@@ -488,6 +488,7 @@
"title": "Olap custom view List"
},
"deleteVersion": {
"errorMessage": "You can not delete active version, please try again.",
"id": "id",
"title": "Select the version to delete"
},
......@@ -502,6 +503,7 @@
"selectLevels": "Select visible levels",
"title": "Drill Through"
},
"editErrorLocked": "It's not possible to edit a schema if you have not set a lock on it.",
"editModeConfirm": "You are leaving edit mode. Continue?",
"filterDialog": {
"ancestorDescendantWarning": "Warning: You selected some members that are in ancestor-descendant relationship: measures will be aggregated over both of them. Are you sure this is what you want?",
......@@ -538,6 +540,7 @@
"detail2": "You can change it acting on the form below.",
"dropdownLabel": "Available hierarchies"
},
"notEditable": "Measure is not editable",
"openDesigner": "Open Designer",
"openDesignerMsg": "By opening designer you will lose all unsaved changes, are you sure?",
"outputWizard": {
......
......@@ -95,8 +95,8 @@
<ScenarioWizard v-if="scenarioWizardVisible" :visible="scenarioWizardVisible" :hiddenFormDataProp="hiddenFormDataProp" :sbiExecutionId="id" :olapDesignerProp="olapDesigner" @saveScenario="saveScenario" @deleteScenario="deleteScenario" @close="scenarioWizardVisible = false" />
<AlgorithmDialog v-if="algorithmDialogVisible" :visible="algorithmDialogVisible" :sbiExecutionId="id" @close="algorithmDialogVisible = false" />
<OlapFilterDialog :visible="filterDialogVisible" :propFilter="selectedFilter" :id="id" :olapDesignerMode="olapDesignerMode" :parameters="parameters" :profileAttributes="profileAttributes" :olapDesigner="olapDesigner" @close="closeFilterDialog" @applyFilters="applyFilters"></OlapFilterDialog>
<OlapSaveNewVersionDialog :visible="saveVersionDialogVisible" :id="id" @close="saveVersionDialogVisible = false"></OlapSaveNewVersionDialog>
<OlapDeleteVersionsDialog :visible="deleteVersionDialogVisible" :id="id" :propOlapVersions="olapVersions" @close="deleteVersionDialogVisible = false"></OlapDeleteVersionsDialog>
<OlapSaveNewVersionDialog :visible="saveVersionDialogVisible" :id="id" @close="saveVersionDialogVisible = false" @newVersionSaved="onNewVersionSaved"></OlapSaveNewVersionDialog>
<OlapDeleteVersionsDialog :visible="deleteVersionDialogVisible" :id="id" :propOlapVersions="olapVersions" :olap="olap" @close="deleteVersionDialogVisible = false"></OlapDeleteVersionsDialog>
</template>
<script lang="ts">
......@@ -876,12 +876,14 @@ export default defineComponent({
async undo() {
this.loading = true
await this.$http
.post(process.env.VUE_APP_OLAP_PATH + `1.0/model/undo/?SBI_EXECUTION_ID=${this.id}`, {}, { headers: { Accept: 'application/json, text/plain, */*', 'Content-Type': 'application/json;charset=UTF-8', 'X-Disable-Errors': 'true' } })
.then(() => {
.post(process.env.VUE_APP_OLAP_PATH + `1.0/model/undo/?SBI_EXECUTION_ID=${this.id}`, null, { headers: { Accept: 'application/json, text/plain, */*', 'Content-Type': 'application/json;charset=UTF-8', 'X-Disable-Errors': 'true' } })
.then((response: AxiosResponse<any>) => {
this.$store.commit('setInfo', {
title: this.$t('common.toast.updateTitle'),
msg: this.$t('common.toast.success')
})
this.olap = response.data
this.formatOlapTable()
})
.catch((error: any) =>
this.$store.commit('setError', {
......@@ -936,11 +938,16 @@ export default defineComponent({
}
},
handleTableDoubleClick(event: any) {
if (!this.olapHasScenario) return
if (!event.target.attributes.cell) return
let clickLocation = event.target.getBoundingClientRect()
if (!this.checkIfVersionIsSet()) {
return this.$store.commit('setError', { title: this.$t('common.toast.errorTitle'), msg: this.$t('documentExecution.olap.sliceVersionError') })
} else if (this.checkIfModelIsLocked()) {
return this.$store.commit('setError', { title: this.$t('common.toast.errorTitle'), msg: this.$t('documentExecution.olap.editErrorLocked') })
} else if (!this.checkIfMeasureIsEditable(event.target.getAttribute('measurename'))) {
return this.$store.commit('setError', { title: this.$t('common.toast.errorTitle'), msg: this.$t('documentExecution.olap.notEditable') })
} else {
// @ts-ignore
this.$refs.whatifInput.style.top = `${clickLocation.top}px`
......@@ -954,25 +961,6 @@ export default defineComponent({
this.whatifInputOrdinal = event.target.attributes.ordinal.value
}
},
closeWhatifInput() {
// @ts-ignore
this.$refs.whatifInput.style.display = 'none'
},
async onWhatifInput() {
let postData = { expression: this.whatifInputNewValue }
this.loading = true
await this.$http
.post(process.env.VUE_APP_OLAP_PATH + `1.0/model/setValue/${this.whatifInputOrdinal}?SBI_EXECUTION_ID=${this.id}`, postData, { headers: { Accept: 'application/json, text/plain, */*', 'Content-Type': 'application/json;charset=UTF-8' } })
.then((response: AxiosResponse<any>) => {
this.olap = response.data
this.closeWhatifInput()
})
.catch(() => {})
.finally(() => (this.loading = false))
this.formatOlapTable()
},
checkIfVersionIsSet() {
let versionIsSet = false
for (let i = 0; i < this.olap.filters.length; i++) {
......@@ -981,6 +969,51 @@ export default defineComponent({
}
}
return versionIsSet
},
checkIfModelIsLocked() {
if (this.olap.modelConfig.status == 'locked_by_other' || this.olap.modelConfig.status == 'unlocked') {
return true
} else return false
},
checkIfMeasureIsEditable(measureName) {
if (this.olap.modelConfig && this.olap.modelConfig.writeBackConf) {
if (this.olap.modelConfig.writeBackConf.editableMeasures == null || this.olap.modelConfig.writeBackConf.editableMeasures.length == 0) {
return true
} else {
var measures = this.olap.modelConfig.writeBackConf.editableMeasures
for (var i = 0; i < measures.length; i++) {
if (measures[i] === measureName) {
return true
}
}
}
return false
}
},
closeWhatifInput() {
// @ts-ignore
this.$refs.whatifInput.style.display = 'none'
},
async onWhatifInput() {
if (this.whatifInputNewValue != this.whatifInputOldValue) {
let postData = { expression: this.whatifInputNewValue }
this.loading = true
await this.$http
.post(process.env.VUE_APP_OLAP_PATH + `1.0/model/setValue/${this.whatifInputOrdinal}?SBI_EXECUTION_ID=${this.id}`, postData, { headers: { Accept: 'application/json, text/plain, */*', 'Content-Type': 'application/json;charset=UTF-8' } })
.then((response: AxiosResponse<any>) => {
this.olap = response.data
this.closeWhatifInput()
this.formatOlapTable()
})
.catch(() => {})
.finally(() => (this.loading = false))
}
this.closeWhatifInput()
},
onNewVersionSaved(olap: iOlap) {
this.olap = olap
this.formatOlapTable()
this.saveVersionDialogVisible = false
}
}
})
......
......@@ -26,6 +26,7 @@
<script lang="ts">
import { defineComponent, PropType } from 'vue'
import { iOlap } from '../Olap'
import Column from 'primevue/column'
import DataTable from 'primevue/datatable'
import Dialog from 'primevue/dialog'
......@@ -34,7 +35,7 @@ import olapDeleteVersionsDialogDescriptor from './OlapDeleteVersionsDialogDescri
export default defineComponent({
name: 'olap-delete-versions-dialog',
components: { Column, DataTable, Dialog },
props: { visible: { type: Boolean }, id: { type: String }, propOlapVersions: { type: Array as PropType<{ id: number; name: string; description: string }[]> } },
props: { visible: { type: Boolean }, id: { type: String }, propOlapVersions: { type: Array as PropType<{ id: number; name: string; description: string }[]> }, olap: { type: Object as PropType<iOlap> } },
emits: ['close'],
computed: {},
data() {
......@@ -63,6 +64,13 @@ export default defineComponent({
},
async deleteVersions() {
this.loading = true
if (this.checkIfActiveVersionIsSelected()) {
this.$store.commit('setError', { title: this.$t('common.toast.errorTitle'), msg: this.$t('documentExecution.olap.deleteVersion.errorMessage') })
this.loading = false
return
}
const versionsToDelete = this.selectedVersions?.map((version: { id: number; name: string; description: string }) => version.id).join(',')
if (!versionsToDelete || versionsToDelete.length === 0) return
await this.$http
......@@ -81,6 +89,27 @@ export default defineComponent({
})
)
this.loading = false
},
checkIfActiveVersionIsSelected() {
if (!this.olap) return
let selected = false
let activeVersions = []
for (let i = 0; i < this.olap.filters.length; i++) {
if (this.olap.filters[i].name === 'Version') {
activeVersions = this.olap.filters[i].hierarchies[0].slicers
break
}
}
for (let i = 0; i < this.selectedVersions.length; i++) {
const index = activeVersions.findIndex((version: any) => version.name === this.selectedVersions[i].name)
if (index !== -1) {
selected = true
break
}
}
return selected
}
}
})
......
<template>
<div id="top-toolbar-container" class="p-d-flex" :style="toolbarDescriptor.style.topToolbarContainer">
<span id="topaxis" ref="filterPanelContainer" class="kn-flex p-d-flex" :style="toolbarDescriptor.style.topAxis" @drop="onDrop($event)" @dragover.prevent @dragenter="displayDropzone" @dragleave="hideDropzone">
<span class="swapAxis" :style="toolbarDescriptor.style.toolbarMainColor" @click="$emit('swapAxis')"> &nbsp; </span>
<Button icon="fa-solid fa-repeat" class="p-button-text p-button-rounded p-button-plain" :style="toolbarDescriptor.style.whiteColor" @click="$emit('swapAxis')" />
<Button v-if="scrollContainerWidth < scrollContentWidth" icon="fas fa-arrow-circle-left" class="p-button-text p-button-rounded p-button-plain p-ml-1 p-as-center" :style="toolbarDescriptor.style.whiteColor" @click="scrollLeft" />
<div ref="filterItemsContainer" class="p-d-flex p-ai-center kn-flex" :style="toolbarDescriptor.style.scroll">
<div v-for="(column, index) in columns" :key="index" class="p-d-flex">
......@@ -128,13 +128,6 @@ export default defineComponent({
})
</script>
<style lang="scss" scoped>
.swapAxis {
cursor: pointer;
width: 32px;
background-image: url(http://localhost:8080/knowage/themes/commons/img/olap/double-arrow.png);
background-repeat: no-repeat;
background-position: center center;
}
.filter-dragging {
background-color: #bbd6ed !important;
}
......
......@@ -26,14 +26,15 @@
</form>
<template #footer>
<Button class="kn-button kn-button--secondary" @click="close"> {{ $t('common.close') }}</Button>
<Button class="kn-button kn-button--primary" @click="save"> {{ $t('common.save') }}</Button>
<Button class="kn-button kn-button--secondary" :disabled="loading" @click="close"> {{ $t('common.close') }}</Button>
<Button class="kn-button kn-button--primary" :disabled="loading" @click="save"> {{ $t('common.save') }}</Button>
</template>
</Dialog>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { AxiosResponse } from 'axios'
import Dialog from 'primevue/dialog'
import InlineMessage from 'primevue/inlinemessage'
import olapSaveNewVersionDialogDescriptor from './OlapSaveNewVersionDialogDescriptor.json'
......@@ -43,7 +44,7 @@ export default defineComponent({
name: 'olap-save-new-version-dialog',
components: { Dialog, InlineMessage, Textarea },
props: { visible: { type: Boolean }, id: { type: String } },
emits: ['close', 'save'],
emits: ['close', 'save', 'newVersionSaved'],
computed: {},
data() {
return {
......@@ -64,14 +65,15 @@ export default defineComponent({
await this.$http
.post(
process.env.VUE_APP_OLAP_PATH + `1.0/model/saveAs?SBI_EXECUTION_ID=${this.id}`,
{ name: this.version.name ?? 'sbiNoDescription', descr: this.version.descr ?? 'sbiNoDescription' },
{ name: this.version.name !== '' ? this.version.name : 'sbiNoDescription', descr: this.version.descr !== '' ? this.version.descr : 'sbiNoDescription' },
{ headers: { Accept: 'application/json, text/plain, */*', 'Content-Type': 'application/json;charset=UTF-8', 'X-Disable-Errors': 'true' } }
)
.then(() => {
.then((response: AxiosResponse<any>) => {
this.$store.commit('setInfo', {
title: this.$t('common.toast.createTitle'),
msg: this.$t('common.toast.success')
})
this.$emit('newVersionSaved', response.data)
this.close()
})
.catch((error: any) =>
......
......@@ -51,7 +51,7 @@
{{ $t('common.info.dataLoading') }}
</template>
<Column v-for="col of columns" :field="col.field" :header="$t(col.header)" :key="col.field" :sortable="true" :style="col.style" class="kn-truncated">
<Column v-for="col of columns" :field="col.field" :header="$t(col.header)" :key="col.field" :sortable="true" :style="[col.style, [col.field == 'valueCheck' ? 'max-width: 200px' : '']]" class="kn-truncated">
<template #filter="{ filterModel }">
<InputText type="text" v-model="filterModel.value" class="p-column-filter"></InputText>
</template>
......@@ -74,106 +74,106 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { iConfiguration } from './ConfigurationManagement'
import { FilterOperator } from 'primevue/api'
import { filterDefault } from '@/helpers/commons/filterHelper'
import configurationManagementDescriptor from './ConfigurationManagementDescriptor.json'
import { AxiosResponse } from 'axios'
import Column from 'primevue/column'
import DataTable from 'primevue/datatable'
import KnFabButton from '@/components/UI/KnFabButton.vue'
import ConfigurationManagementDialog from './ConfigurationManagementDialog.vue'
import { defineComponent } from 'vue'
import { iConfiguration } from './ConfigurationManagement'
import { FilterOperator } from 'primevue/api'
import { filterDefault } from '@/helpers/commons/filterHelper'
import configurationManagementDescriptor from './ConfigurationManagementDescriptor.json'
import { AxiosResponse } from 'axios'
import Column from 'primevue/column'
import DataTable from 'primevue/datatable'
import KnFabButton from '@/components/UI/KnFabButton.vue'
import ConfigurationManagementDialog from './ConfigurationManagementDialog.vue'
export default defineComponent({
name: 'configuration-management',
components: {
Column,
DataTable,
KnFabButton,
ConfigurationManagementDialog
},
data() {
return {
configurationManagementDescriptor: configurationManagementDescriptor,
configurations: [] as iConfiguration[],
selectedConfiguration: null as iConfiguration | null,
columns: configurationManagementDescriptor.columns,
formVisible: false,
loading: false,
export default defineComponent({
name: 'configuration-management',
components: {
Column,
DataTable,
KnFabButton,
ConfigurationManagementDialog
},
data() {
return {
configurationManagementDescriptor: configurationManagementDescriptor,
configurations: [] as iConfiguration[],
selectedConfiguration: null as iConfiguration | null,
columns: configurationManagementDescriptor.columns,
formVisible: false,
loading: false,
filters: {
global: [filterDefault],
label: {
operator: FilterOperator.AND,
constraints: [filterDefault]
},
name: {
operator: FilterOperator.AND,
constraints: [filterDefault]
},
category: {
operator: FilterOperator.AND,
constraints: [filterDefault]
},
valueCheck: {
operator: FilterOperator.AND,
constraints: [filterDefault]
},
active: {
operator: FilterOperator.AND,
constraints: [filterDefault]
}
} as Object
}
filters: {
global: [filterDefault],
label: {
operator: FilterOperator.AND,
constraints: [filterDefault]
},
name: {
operator: FilterOperator.AND,
constraints: [filterDefault]
},
category: {
operator: FilterOperator.AND,
constraints: [filterDefault]
},
valueCheck: {
operator: FilterOperator.AND,
constraints: [filterDefault]
},
active: {
operator: FilterOperator.AND,
constraints: [filterDefault]
}
} as Object
}
},
created() {
this.loadConfigurations()
},
methods: {
async loadConfigurations() {
this.loading = true
await this.$http
.get(process.env.VUE_APP_RESTFUL_SERVICES_PATH + '2.0/configs')
.then((response: AxiosResponse<any>) => {
this.configurations = response.data
})
.finally(() => (this.loading = false))
},
created() {
this.loadConfigurations()
showDeleteDialog(configurationId: number) {
this.$confirm.require({
message: this.$t('common.toast.deleteMessage'),
header: this.$t('common.toast.deleteConfirmTitle'),
icon: 'pi pi-exclamation-triangle',
accept: () => this.deleteConfiguration(configurationId)
})
},
methods: {
async loadConfigurations() {
this.loading = true
await this.$http
.get(process.env.VUE_APP_RESTFUL_SERVICES_PATH + '2.0/configs')
.then((response: AxiosResponse<any>) => {
this.configurations = response.data
})
.finally(() => (this.loading = false))
},
showDeleteDialog(configurationId: number) {
this.$confirm.require({
message: this.$t('common.toast.deleteMessage'),
header: this.$t('common.toast.deleteConfirmTitle'),
icon: 'pi pi-exclamation-triangle',
accept: () => this.deleteConfiguration(configurationId)
})
},
async deleteConfiguration(configurationId: number) {
await this.$http.delete(process.env.VUE_APP_RESTFUL_SERVICES_PATH + '2.0/configs/' + configurationId).then(() => {
this.$store.commit('setInfo', {
title: this.$t('common.toast.deleteTitle'),
msg: this.$t('common.toast.deleteSuccess')
})
this.loadConfigurations()
async deleteConfiguration(configurationId: number) {
await this.$http.delete(process.env.VUE_APP_RESTFUL_SERVICES_PATH + '2.0/configs/' + configurationId).then(() => {
this.$store.commit('setInfo', {
title: this.$t('common.toast.deleteTitle'),
msg: this.$t('common.toast.deleteSuccess')
})
},
showForm(event) {
if (event) {
this.selectedConfiguration = event.data
}
this.formVisible = true
},
closeForm() {
this.selectedConfiguration = null
this.formVisible = false
},
reload() {
this.formVisible = false
this.loadConfigurations()
})
},
showForm(event) {
if (event) {
this.selectedConfiguration = event.data
}
this.formVisible = true
},
closeForm() {
this.selectedConfiguration = null
this.formVisible = false
},
reload() {
this.formVisible = false
this.loadConfigurations()
}
})
}
})
</script>
<style lang="scss" scoped></style>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment