Rework tag and tag edit placement, add other feedback

- admin message shown primarily if exists
- comment demo summary tab
This commit is contained in:
Christoph Kluge 2024-09-18 17:23:29 +02:00
parent 6367c1ab4d
commit d7a8bbf40b
5 changed files with 217 additions and 199 deletions

View File

@ -25,7 +25,6 @@
CardHeader, CardHeader,
CardTitle, CardTitle,
Button, Button,
Icon,
} from "@sveltestrap/sveltestrap"; } from "@sveltestrap/sveltestrap";
import { getContext } from "svelte"; import { getContext } from "svelte";
import { import {
@ -35,7 +34,6 @@
transformDataForRoofline, transformDataForRoofline,
} from "./generic/utils.js"; } from "./generic/utils.js";
import Metric from "./job/Metric.svelte"; import Metric from "./job/Metric.svelte";
import TagManagement from "./job/TagManagement.svelte";
import StatsTable from "./job/StatsTable.svelte"; import StatsTable from "./job/StatsTable.svelte";
import JobSummary from "./job/JobSummary.svelte"; import JobSummary from "./job/JobSummary.svelte";
import ConcurrentJobs from "./generic/helper/ConcurrentJobs.svelte"; import ConcurrentJobs from "./generic/helper/ConcurrentJobs.svelte";
@ -54,12 +52,10 @@
const ccconfig = getContext("cc-config") const ccconfig = getContext("cc-config")
let isMetricsSelectionOpen = false, let isMetricsSelectionOpen = false,
showFootprint = !!ccconfig[`job_view_showFootprint`],
selectedMetrics = [], selectedMetrics = [],
selectedScopes = []; selectedScopes = [];
let plots = {}, let plots = {},
jobTags,
roofWidth roofWidth
let missingMetrics = [], let missingMetrics = [],
@ -240,14 +236,22 @@
{:else if $initq.data} {:else if $initq.data}
<Card class="overflow-auto" style="height: 400px;"> <Card class="overflow-auto" style="height: 400px;">
<TabContent> <!-- on:tab={(e) => (status = e.detail)} --> <TabContent> <!-- on:tab={(e) => (status = e.detail)} -->
<TabPane tabId="meta-info" tab="Job Info" active> {#if $initq.data?.job?.metaData?.message}
<CardBody class="pb-2"> <TabPane tabId="admin-msg" tab="Admin Note" active>
<JobInfo job={$initq.data.job} {jobTags} /> <CardBody>
<Card body class="mb-2" color="warning">
<h5>Job {$initq.data?.job?.jobId} ({$initq.data?.job?.cluster})</h5>
The following note was added by administrators:
</Card>
<Card body>
{@html $initq.data.job.metaData.message}
</Card>
</CardBody> </CardBody>
</TabPane> </TabPane>
<TabPane tabId="job-tags" tab="Job Tags"> {/if}
<CardBody> <TabPane tabId="meta-info" tab="Job Info" active={$initq.data?.job?.metaData?.message?false:true}>
<TagManagement job={$initq.data.job} {username} {authlevel} {roles} bind:jobTags renderModal={false}/> <CardBody class="pb-2">
<JobInfo job={$initq.data.job} {username} {authlevel} {roles} showTags={false} showTagedit/>
</CardBody> </CardBody>
</TabPane> </TabPane>
{#if $initq.data.job.concurrentJobs != null && $initq.data.job.concurrentJobs.items.length != 0} {#if $initq.data.job.concurrentJobs != null && $initq.data.job.concurrentJobs.items.length != 0}
@ -260,15 +264,6 @@
</CardBody> </CardBody>
</TabPane> </TabPane>
{/if} {/if}
{#if $initq.data?.job?.metaData?.message}
<TabPane tabId="admin-msg" tab="Admin Note">
<CardBody>
<p>This note was added by administrators:</p>
<hr/>
<p>{@html $initq.data.job.metaData.message}</p>
</CardBody>
</TabPane>
{/if}
</TabContent> </TabContent>
</Card> </Card>
{:else} {:else}
@ -276,8 +271,7 @@
{/if} {/if}
</Col> </Col>
<!-- If enabled: Column 2: Job Footprint, Polar Representation, Heuristic Summary --> <!-- Column 2: Job Footprint, Polar Representation, Heuristic Summary -->
{#if showFootprint}
<Col xs={12} md={6} xl={4} xxl={3} class="mb-3 mb-xxl-0"> <Col xs={12} md={6} xl={4} xxl={3} class="mb-3 mb-xxl-0">
{#if $initq.error} {#if $initq.error}
<Card body color="danger">{$initq.error.message}</Card> <Card body color="danger">{$initq.error.message}</Card>
@ -287,10 +281,9 @@
<Spinner secondary /> <Spinner secondary />
{/if} {/if}
</Col> </Col>
{/if}
<!-- Column 3: Job Roofline; If footprint Enabled: full width, else half width --> <!-- Column 3: Job Roofline; If footprint Enabled: full width, else half width -->
<Col xs={12} md={showFootprint ? 12 : 6} xl={showFootprint ? 5 : 6} xxl={6}> <Col xs={12} md={12} xl={5} xxl={6}>
{#if $initq.error || $jobMetrics.error} {#if $initq.error || $jobMetrics.error}
<Card body color="danger"> <Card body color="danger">
<p>Initq Error: {$initq.error?.message}</p> <p>Initq Error: {$initq.error?.message}</p>

View File

@ -23,12 +23,22 @@
if ($initialized && tag == null) if ($initialized && tag == null)
tag = allTags.find(tag => tag.id == id) tag = allTags.find(tag => tag.id == id)
} }
function getScopeColor(scope) {
switch (scope) {
case "admin":
return "#19e5e6";
case "global":
return "#c85fc8";
default:
return "#ffc107";
}
}
</script> </script>
<style> <style>
a { a {
margin-left: 0.5rem; margin-right: 0.5rem;
line-height: 2;
} }
span { span {
font-size: 0.9rem; font-size: 0.9rem;
@ -37,13 +47,7 @@
<a target={clickable ? "_blank" : null} href={clickable ? `/monitoring/jobs/?tag=${id}` : null}> <a target={clickable ? "_blank" : null} href={clickable ? `/monitoring/jobs/?tag=${id}` : null}>
{#if tag} {#if tag}
{#if tag?.scope === "global"} <span style="background-color:{getScopeColor(tag?.scope)};" class="my-1 badge text-dark">{tag.type}: {tag.name}</span>
<span style="background-color:#c85fc8;" class="badge text-dark">{tag.type}: {tag.name}</span>
{:else if tag?.scope === "admin"}
<span style="background-color:#19e5e6;" class="badge text-dark">{tag.type}: {tag.name}</span>
{:else}
<span class="badge bg-warning text-dark">{tag.type}: {tag.name}</span>
{/if}
{:else} {:else}
Loading... Loading...
{/if} {/if}

View File

@ -1,5 +1,5 @@
<!-- <!--
@component Job View Subcomponent; allows management of job tags by deletion or new entries @component Job Info Subcomponent; allows management of job tags by deletion or new entries
Properties: Properties:
- `job Object`: The job object - `job Object`: The job object
@ -30,8 +30,8 @@
Alert, Alert,
Tooltip, Tooltip,
} from "@sveltestrap/sveltestrap"; } from "@sveltestrap/sveltestrap";
import { fuzzySearchTags } from "../generic/utils.js"; import { fuzzySearchTags } from "../utils.js";
import Tag from "../generic/helper/Tag.svelte"; import Tag from "./Tag.svelte";
export let job; export let job;
export let jobTags = job.tags; export let jobTags = job.tags;
@ -178,12 +178,7 @@
{#if renderModal} {#if renderModal}
<Modal {isOpen} toggle={() => (isOpen = !isOpen)}> <Modal {isOpen} toggle={() => (isOpen = !isOpen)}>
<ModalHeader> <ModalHeader>
Manage Tags Manage Tags <Icon name="tags"/>
{#if pendingChange !== false}
<Spinner size="sm" secondary />
{:else}
<Icon name="tags" />
{/if}
</ModalHeader> </ModalHeader>
<ModalBody> <ModalBody>
<InputGroup class="mb-3"> <InputGroup class="mb-3">
@ -317,8 +312,8 @@
</ModalFooter> </ModalFooter>
</Modal> </Modal>
<Button outline on:click={() => (isOpen = true)}> <Button outline on:click={() => (isOpen = true)} size="sm" color="primary">
Manage Tags <Icon name="tags" /> Manage {jobTags?.length ? jobTags.length : ''} Tags
</Button> </Button>
{:else} {:else}

View File

@ -10,9 +10,14 @@
import { Badge, Icon } from "@sveltestrap/sveltestrap"; import { Badge, Icon } from "@sveltestrap/sveltestrap";
import { scrambleNames, scramble } from "../utils.js"; import { scrambleNames, scramble } from "../utils.js";
import Tag from "../helper/Tag.svelte"; import Tag from "../helper/Tag.svelte";
import TagManagement from "../helper/TagManagement.svelte";
export let job; export let job;
export let jobTags = job.tags; export let jobTags = job.tags;
export let showTagedit = false;
export let username = null;
export let authlevel= null;
export let roles = null;
function formatDuration(duration) { function formatDuration(duration) {
const hours = Math.floor(duration / 3600); const hours = Math.floor(duration / 3600);
@ -36,7 +41,7 @@
</script> </script>
<div> <div>
<p> <p class="mb-2">
<span class="fw-bold" <span class="fw-bold"
><a href="/monitoring/job/{job.id}" target="_blank">{job.jobId}</a> ><a href="/monitoring/job/{job.id}" target="_blank">{job.jobId}</a>
({job.cluster})</span ({job.cluster})</span
@ -63,7 +68,7 @@
{/if} {/if}
</p> </p>
<p> <p class="mb-2">
<Icon name="person-fill" /> <Icon name="person-fill" />
<a class="fst-italic" href="/monitoring/user/{job.user}" target="_blank"> <a class="fst-italic" href="/monitoring/user/{job.user}" target="_blank">
{scrambleNames ? scramble(job.user) : job.user} {scrambleNames ? scramble(job.user) : job.user}
@ -84,7 +89,7 @@
{/if} {/if}
</p> </p>
<p> <p class="mb-2">
{#if job.numNodes == 1} {#if job.numNodes == 1}
{job.resources[0].hostname} {job.resources[0].hostname}
{:else} {:else}
@ -104,7 +109,7 @@
{job.subCluster} {job.subCluster}
</p> </p>
<p> <p class="mb-2">
Start: <span class="fw-bold" Start: <span class="fw-bold"
>{new Date(job.startTime).toLocaleString()}</span >{new Date(job.startTime).toLocaleString()}</span
> >
@ -117,11 +122,25 @@
{/if} {/if}
</p> </p>
<p class="mb-2"> {#if showTagedit}
<hr class="mt-0 mb-2"/>
<p class="mb-1">
<TagManagement bind:jobTags {job} {username} {authlevel} {roles} renderModal/> :
{#if jobTags?.length > 0}
{#each jobTags as tag}
<Tag {tag}/>
{/each}
{:else}
<span style="font-size: 0.9rem; background-color: lightgray;" class="my-1 badge text-dark">No Tags</span>
{/if}
</p>
{:else}
<p class="mb-1">
{#each jobTags as tag} {#each jobTags as tag}
<Tag {tag} /> <Tag {tag} />
{/each} {/each}
</p> </p>
{/if}
</div> </div>
<style> <style>

View File

@ -68,6 +68,7 @@
export let height = "400px"; export let height = "400px";
const ccconfig = getContext("cc-config") const ccconfig = getContext("cc-config")
const showFootprint = !!ccconfig[`job_view_showFootprint`];
const footprintData = job?.footprint?.map((jf) => { const footprintData = job?.footprint?.map((jf) => {
const fmc = getContext("getMetricConfig")(job.cluster, job.subCluster, jf.name); const fmc = getContext("getMetricConfig")(job.cluster, job.subCluster, jf.name);
@ -165,6 +166,7 @@
} }
} }
/*
function writeSummary(fpd) { function writeSummary(fpd) {
// Hardcoded! Needs to be retrieved from globalMetrics // Hardcoded! Needs to be retrieved from globalMetrics
const performanceMetrics = ['flops_any', 'mem_bw']; const performanceMetrics = ['flops_any', 'mem_bw'];
@ -225,10 +227,12 @@
}; };
$: summaryMessages = writeSummary(footprintData) $: summaryMessages = writeSummary(footprintData)
*/
</script> </script>
<Card class="overflow-auto" style="width: {width}; height: {height}"> <Card class="overflow-auto" style="width: {width}; height: {height}">
<TabContent> <!-- on:tab={(e) => (status = e.detail)} --> <TabContent> <!-- on:tab={(e) => (status = e.detail)} -->
{#if showFootprint}
<TabPane tabId="foot" tab="Footprint" active> <TabPane tabId="foot" tab="Footprint" active>
<CardBody> <CardBody>
{#each footprintData as fpd, index} {#each footprintData as fpd, index}
@ -309,7 +313,8 @@
{/each} {/each}
</CardBody> </CardBody>
</TabPane> </TabPane>
<TabPane tabId="polar" tab="Polar"> {/if}
<TabPane tabId="polar" tab="Polar" active={!showFootprint}>
<CardBody> <CardBody>
<Polar <Polar
{footprintData} {footprintData}
@ -317,6 +322,7 @@
/> />
</CardBody> </CardBody>
</TabPane> </TabPane>
<!--
<TabPane tabId="summary" tab="Summary"> <TabPane tabId="summary" tab="Summary">
<CardBody> <CardBody>
<p>Based on footprint data, this job performs as follows:</p> <p>Based on footprint data, this job performs as follows:</p>
@ -330,6 +336,7 @@
</ul> </ul>
</CardBody> </CardBody>
</TabPane> </TabPane>
-->
</TabContent> </TabContent>
</Card> </Card>