<!-- @component Properties: - metrics: [String] (changes from inside, needs to be initialised, list of selected metrics) - isOpen: Boolean (can change from inside and outside) - configName: String (constant) --> <script> import { Modal, ModalBody, ModalHeader, ModalFooter, Button, ListGroup } from 'sveltestrap' import { getContext } from 'svelte' import { gql, getContextClient , mutationStore } from '@urql/svelte' export let metrics export let isOpen export let configName export let allMetrics = null export let cluster = null export let showFootprint export let view = 'job' const clusters = getContext('clusters'), onInit = getContext('on-init') let newMetricsOrder = [] let unorderedMetrics = [...metrics] let pendingShowFootprint = !!showFootprint onInit(() => { if (allMetrics == null) allMetrics = new Set() for (let c of clusters) for (let metric of c.metricConfig) allMetrics.add(metric.name) }) $: { if (allMetrics != null) { if (cluster == null) { // console.log('Reset to full metric list') for (let c of clusters) for (let metric of c.metricConfig) allMetrics.add(metric.name) } else { // console.log('Recalculate available metrics for ' + cluster) allMetrics.clear() for (let c of clusters) if (c.name == cluster) for (let metric of c.metricConfig) allMetrics.add(metric.name) } newMetricsOrder = [...allMetrics].filter(m => !metrics.includes(m)) newMetricsOrder.unshift(...metrics.filter(m => allMetrics.has(m))) unorderedMetrics = unorderedMetrics.filter(m => allMetrics.has(m)) } } const client = getContextClient(); const updateConfigurationMutation = ({ name, value }) => { return mutationStore({ client: client, query: gql` mutation($name: String!, $value: String!) { updateConfiguration(name: $name, value: $value) } `, variables: { name, value } })} let columnHovering = null function columnsDragStart(event, i) { event.dataTransfer.effectAllowed = 'move' event.dataTransfer.dropEffect = 'move' event.dataTransfer.setData('text/plain', i) } function columnsDrag(event, target) { event.dataTransfer.dropEffect = 'move' const start = Number.parseInt(event.dataTransfer.getData("text/plain")) if (start < target) { newMetricsOrder.splice(target + 1, 0, newMetricsOrder[start]) newMetricsOrder.splice(start, 1) } else { newMetricsOrder.splice(target, 0, newMetricsOrder[start]) newMetricsOrder.splice(start + 1, 1) } columnHovering = null } function closeAndApply() { metrics = newMetricsOrder.filter(m => unorderedMetrics.includes(m)) isOpen = false showFootprint = !!pendingShowFootprint updateConfigurationMutation({ name: cluster == null ? configName : `${configName}:${cluster}`, value: JSON.stringify(metrics) }).subscribe(res => { if (res.fetching === false && res.error) { throw res.error // console.log('Error on subscription: ' + res.error) } }) updateConfigurationMutation({ name: cluster == null ? 'plot_list_showFootprint' : `plot_list_showFootprint:${cluster}`, value: JSON.stringify(showFootprint) }).subscribe(res => { if (res.fetching === false && res.error) { console.log('Error on footprint subscription: ' + res.error) throw res.error } }) } </script> <style> li.cc-config-column { display: block; cursor: grab; } li.cc-config-column.is-active { background-color: #3273dc; color: #fff; cursor: grabbing; } </style> <Modal isOpen={isOpen} toggle={() => (isOpen = !isOpen)}> <ModalHeader> Configure columns (Metric availability shown) </ModalHeader> <ModalBody> <ListGroup> {#if view === 'list'} <li class="list-group-item"> <input type="checkbox" bind:checked={pendingShowFootprint}> Show Footprint </li> <hr/> {/if} {#each newMetricsOrder as metric, index (metric)} <li class="cc-config-column list-group-item" draggable={true} ondragover="return false" on:dragstart={event => columnsDragStart(event, index)} on:drop|preventDefault={event => columnsDrag(event, index)} on:dragenter={() => columnHovering = index} class:is-active={columnHovering === index}> {#if unorderedMetrics.includes(metric)} <input type="checkbox" bind:group={unorderedMetrics} value={metric} checked> {:else} <input type="checkbox" bind:group={unorderedMetrics} value={metric}> {/if} {metric} <span style="float: right;"> {cluster == null ? clusters // No single cluster specified: List Clusters with Metric .filter(c => c.metricConfig.find(m => m.name == metric) != null) .map(c => c.name).join(', ') : clusters // Single cluster requested: List Subclusters with do not have metric remove flag .filter(c => c.name == cluster) .filter(c => c.metricConfig.find(m => m.name == metric) != null) .map(function(c) { let scNames = c.subClusters.map(sc => sc.name) scNames.forEach(function(scName){ let met = c.metricConfig.find(m => m.name == metric) let msc = met.subClusters.find(msc => msc.name == scName) if (msc != null) { if (msc.remove == true) { scNames = scNames.filter(scn => scn != msc.name) } } }) return scNames }) .join(', ')} </span> </li> {/each} </ListGroup> </ModalBody> <ModalFooter> <Button color="primary" on:click={closeAndApply}>Close & Apply</Button> </ModalFooter> </Modal>