@ax2/xms-dashboard-module
Advanced tools
| <template> | ||
| <WidgetTemplate | ||
| :title="title" | ||
| :loading="$apolloData.queries.datas.loading" | ||
| :filters="filters" | ||
| @updateFilters="updateFilters" | ||
| > | ||
| <apexchart | ||
| v-if="!$apolloData.queries.datas.loading" | ||
| :options="datas.options" | ||
| :series="datas.series" | ||
| :height="options.style ? '100%' : 'auto'" | ||
| /> | ||
| </WidgetTemplate> | ||
| </template> | ||
| <script> | ||
| import gql from 'graphql-tag'; | ||
| import VueApexCharts from 'vue-apexcharts'; | ||
| import { get } from 'lodash'; | ||
| import filterMixins from '../mixins/filter'; | ||
| import WidgetTemplate from './WidgetTemplate'; | ||
| export default { | ||
| name: 'ChartsArea', | ||
| components: { | ||
| 'apexchart': VueApexCharts, | ||
| WidgetTemplate, | ||
| }, | ||
| mixins: [ | ||
| filterMixins, | ||
| ], | ||
| props: { | ||
| title: { | ||
| type: String, | ||
| required: false, | ||
| default: null, | ||
| }, | ||
| options: { | ||
| type: Object, | ||
| required: true, | ||
| }, | ||
| }, | ||
| data () { | ||
| return { | ||
| show: false, | ||
| loading: true, | ||
| responsive: [ | ||
| { | ||
| breakpoint: 2000, | ||
| options: { | ||
| legend: { | ||
| position: "bottom" | ||
| } | ||
| } | ||
| } | ||
| ], | ||
| query: ` | ||
| query Query($query: String, $chartType: String, $groupByVariable: String, $labels: [String]){ | ||
| datas: chart(query: $query, chartType: $chartType, groupByVariable: $groupByVariable, labels: $labels) { | ||
| options { | ||
| chart { type }, | ||
| labels, | ||
| xaxis { categories } | ||
| } | ||
| series | ||
| } | ||
| } | ||
| `, | ||
| }; | ||
| }, | ||
| apollo: { | ||
| datas: { | ||
| query () { | ||
| return gql(this.query); | ||
| }, | ||
| variables () { | ||
| return this.gqlVariables; | ||
| }, | ||
| result (data) { | ||
| data.data.datas.options = { ...data.data.datas.options, ...{ legend: { position: 'bottom'} } }; | ||
| return data.data.datas; | ||
| } | ||
| }, | ||
| }, | ||
| computed: { | ||
| gqlVariables () { | ||
| let filter = this.options.filter ? this.options.filter : null; | ||
| if (Object.keys(this.selectedFilters).length > 0) { | ||
| filter = filter ? `${filter},${this.getFilterValue()}` : this.getFilterValue(); | ||
| } | ||
| let query = ` | ||
| query { | ||
| datas: ${this.options.id} ${filter ? `(queryInput: { filter: "${filter}" })`: ''} { | ||
| id, | ||
| ${this.options.related} | ||
| } | ||
| } | ||
| `; | ||
| if (this.options.filterValue) { | ||
| query = query.replace(`\${${this.options.filterValue.key}}`, get(this, this.options.filterValue.value)); | ||
| } | ||
| return { | ||
| query, | ||
| chartType: this.options.type, | ||
| groupByVariable: this.options.groupBy, | ||
| labels: this.options.labels | ||
| }; | ||
| }, | ||
| }, | ||
| beforeDestroy () { | ||
| this.$apollo.queries.datas.stop(); | ||
| }, | ||
| }; | ||
| </script> |
| <template> | ||
| <WidgetTemplate | ||
| :title="title" | ||
| :loading="$apolloData.queries.datas.loading" | ||
| :filters="filters" | ||
| @updateFilters="updateFilters" | ||
| > | ||
| <v-data-table | ||
| v-if="!$apolloData.queries.datas.loading" | ||
| :headers="headers" | ||
| :items="datas" | ||
| :items-per-page="5" | ||
| class="elevation-1" | ||
| /> | ||
| </WidgetTemplate> | ||
| </template> | ||
| <script> | ||
| import gql from 'graphql-tag'; | ||
| import filterMixins from '../mixins/filter'; | ||
| import WidgetTemplate from './WidgetTemplate'; | ||
| export default { | ||
| name: 'DataTable', | ||
| components: { | ||
| WidgetTemplate, | ||
| }, | ||
| mixins: [ | ||
| filterMixins, | ||
| ], | ||
| props: { | ||
| title: { | ||
| type: String, | ||
| required: false, | ||
| default: null, | ||
| }, | ||
| query: { | ||
| type: String, | ||
| required: true, | ||
| }, | ||
| }, | ||
| data () { | ||
| return { | ||
| show: false, | ||
| }; | ||
| }, | ||
| apollo: { | ||
| datas: { | ||
| query () { | ||
| return gql(`query { datas: ${this.formatedQuery} }`); | ||
| }, | ||
| variables () { | ||
| return this.gqlVariables; | ||
| }, | ||
| skip () { | ||
| return false; | ||
| }, | ||
| }, | ||
| }, | ||
| computed: { | ||
| formatedQuery () { | ||
| return this.query.replaceAll("${filter}", this.getFilterValue()); | ||
| }, | ||
| headers () { | ||
| return Object.keys(this.datas[0]).map(header => { | ||
| return { | ||
| text: header, | ||
| value: header | ||
| }; | ||
| }); | ||
| }, | ||
| }, | ||
| beforeDestroy () { | ||
| this.$apollo.queries.datas.stop(); | ||
| }, | ||
| methods: { | ||
| }, | ||
| }; | ||
| </script> |
| <template> | ||
| <v-card> | ||
| <v-card-title v-t="title" /> | ||
| <v-card-text> | ||
| <filters-form | ||
| v-if="filtersWithOptions.length > 0" | ||
| :items="filtersWithOptions" | ||
| :value="selectedFilters" | ||
| :search="false" | ||
| :type-name="'typeName'" | ||
| class="mb-4" | ||
| @update:value="$emit('updateFilters', $event)" | ||
| /> | ||
| <slot v-if="!loading"/> | ||
| <!-- Loading spinner --> | ||
| <BaseSpinner v-else /> | ||
| </v-card-text> | ||
| </v-card> | ||
| </template> | ||
| <script> | ||
| import filterMixins from '../mixins/filter'; | ||
| export default { | ||
| name: 'WidgetTemplate', | ||
| mixins: [ | ||
| filterMixins, | ||
| ], | ||
| props: { | ||
| title: { | ||
| type: String, | ||
| required: false, | ||
| default: null, | ||
| }, | ||
| loading: { | ||
| type: Boolean, | ||
| required: false, | ||
| default: true, | ||
| }, | ||
| }, | ||
| data () { | ||
| return { | ||
| show: false, | ||
| }; | ||
| }, | ||
| }; | ||
| </script> |
| import gql from 'graphql-tag'; | ||
| export default { | ||
| props: { | ||
| filters: { | ||
| type: Array, | ||
| required: false, | ||
| default: () => [], | ||
| } | ||
| }, | ||
| data () { | ||
| return { | ||
| selectedFilters: {}, | ||
| }; | ||
| }, | ||
| apollo: { | ||
| filtersOptions: { | ||
| query () { | ||
| return this.createFiltersOptionsQuery(this.filters); | ||
| }, | ||
| skip () { | ||
| // Skip query if no gql query is returned | ||
| return !this.createFiltersOptionsQuery(this.filters); | ||
| }, | ||
| update (data) { | ||
| return data; | ||
| } | ||
| }, | ||
| }, | ||
| methods: { | ||
| updateFilters ({ key, value }) { | ||
| const newFilter = {}; | ||
| newFilter[key] = value; | ||
| this.selectedFilters[key] = value; | ||
| this.selectedFilters = { | ||
| ... this.selectedFilters, | ||
| ...newFilter | ||
| }; | ||
| }, | ||
| getFilterValue () { | ||
| // Build array of all filters selected by user | ||
| const selectedFiltersArray = Object.keys(this.selectedFilters) | ||
| .map(selectedFilterId => { | ||
| const filterValue = this.selectedFilters[selectedFilterId]; | ||
| const filterConfig = this.filters.find(filter => filter.id === selectedFilterId); | ||
| if (selectedFilterId === 'dates' && this.selectedFilters[selectedFilterId].length > 0) { | ||
| // Handle filter dates with range values | ||
| let result = `${filterConfig.whereClause[0]}:${this.selectedFilters[selectedFilterId][0]}`; | ||
| if (this.selectedFilters[selectedFilterId][1]) { | ||
| result = `${result},${filterConfig.whereClause[1]}:${this.selectedFilters[selectedFilterId][1]} 23-59-59`; | ||
| } | ||
| return result; | ||
| } else if (typeof filterValue === 'object') { | ||
| // Handle multiple filter values | ||
| const { clauseSeparator } = filterConfig; | ||
| const separator = clauseSeparator !== undefined ? clauseSeparator : '(&&)'; | ||
| const concatValues = filterValue.map(item => { | ||
| return item.value; | ||
| }).join(separator); | ||
| return `${filterConfig.whereClause}:${concatValues}`; | ||
| } | ||
| if (filterValue === undefined || filterConfig == null) { | ||
| return null; | ||
| } | ||
| return `${filterConfig.whereClause}:${filterValue}`; | ||
| }) | ||
| .filter(filterItem => filterItem !== null); | ||
| return selectedFiltersArray.filter(filter => filter).join(','); | ||
| }, | ||
| createFiltersOptionsQuery (filters = []) { | ||
| // Get only filters that require options | ||
| const requestFilters = filters.filter(filter => { | ||
| // Won't request filters that have static options set | ||
| return filter.type === 'select' && !filter.options; | ||
| }); | ||
| if (!requestFilters.length) { | ||
| return false; | ||
| } | ||
| // Create a query for every one | ||
| const queries = requestFilters.map(filter => { | ||
| return `${filter.id}: filter (key: "${filter.id}") { | ||
| value: key, | ||
| text: value, | ||
| }`; | ||
| }); | ||
| return gql`{ ${queries.join(',')} }`; | ||
| }, | ||
| }, | ||
| computed: { | ||
| filtersWithOptions () { | ||
| /** | ||
| * Translate option function | ||
| */ | ||
| const translateOption = option => ({ | ||
| value: option.value, | ||
| text: this.$t(option.text) | ||
| }); | ||
| if (!Array.isArray(this.filters)) return []; | ||
| return this.filters.map(filterConfig => { | ||
| const filter = { ...filterConfig }; | ||
| // Fetched options take priority over static options | ||
| if (this.filtersOptions && this.filtersOptions[filter.id]) { | ||
| filter.options = this.filtersOptions[filter.id].map(translateOption); | ||
| } else if (filter.options) { | ||
| filter.options = filter.options.map(translateOption); | ||
| } | ||
| return filter; | ||
| }); | ||
| }, | ||
| }, | ||
| }; |
| import Vue from 'vue'; | ||
| const ChartsArea = () => import('../components/ChartsArea'); | ||
| function installGlobalComponents (Vue) { | ||
| Vue.component('ChartsArea', ChartsArea); | ||
| } | ||
| export default function useGlobalComponents () { | ||
| Vue.use(installGlobalComponents); | ||
| } |
+2
-2
| { | ||
| "name": "@ax2/xms-dashboard-module", | ||
| "version": "0.2.4-alpha.55+5389037", | ||
| "version": "0.2.4-alpha.68+1e94eb3", | ||
| "main": "src/main.js", | ||
@@ -43,3 +43,3 @@ "publishConfig": { | ||
| }, | ||
| "gitHead": "53890374fcdd098d67411f3a8df72b3e8266ef20" | ||
| "gitHead": "1e94eb369661bcafa1f5a076303b1a51fe5e2297" | ||
| } |
@@ -77,3 +77,6 @@ <template> | ||
| }, | ||
| destroyed () { | ||
| this.$_apollo.queries.details.stop(); | ||
| } | ||
| }; | ||
| </script> |
+2
-0
@@ -5,2 +5,3 @@ import useConfig from './plugins/config'; | ||
| import registerRoutes from './router'; | ||
| import useGlobalComponents from './plugins/global-components'; | ||
@@ -11,3 +12,4 @@ export default function loadModule (context) { | ||
| useI18n(context); | ||
| useGlobalComponents(context); | ||
| registerRoutes(context); | ||
| }; |
@@ -23,2 +23,4 @@ <template> | ||
| import Charts from '../components/Charts'; | ||
| import ChartsArea from '../components/ChartsArea'; | ||
| import DataTable from '../components/DataTable'; | ||
@@ -31,2 +33,4 @@ export default { | ||
| Charts, | ||
| ChartsArea, | ||
| DataTable, | ||
| }, | ||
@@ -33,0 +37,0 @@ computed: { |
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
19348
93.42%24
26.32%229
110.09%