-
Line Width
-
-
Width of the lines in the timeseries plots.
+
+
+
+
-
+ {/if}
+
+
+
+
Line Width
+
+
+ Width of the lines in the timeseries plots.
+
+
+
Submit
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
diff --git a/web/frontend/src/config/admin/AddUser.svelte b/web/frontend/src/config/admin/AddUser.svelte
index 2712e175..43f08de1 100644
--- a/web/frontend/src/config/admin/AddUser.svelte
+++ b/web/frontend/src/config/admin/AddUser.svelte
@@ -1,103 +1,156 @@
-
+
+
Role:
+ {#each roles as role, i}
+ {#if i == 0}
+
+
+ {role.toUpperCase()} (Allowed to interact with REST API.)
+
+ {:else if i == 1}
+
+
+ {role.charAt(0).toUpperCase() + role.slice(1)} (Same as if created
+ via LDAP sync.)
+
+ {:else}
+
+
+ {role.charAt(0).toUpperCase() + role.slice(1)}
+
+ {/if}
+ {/each}
+
+
+ Submit
+ {#if displayMessage}
+ {message.msg}
+
{/if}
+
+
diff --git a/web/frontend/src/config/admin/EditProject.svelte b/web/frontend/src/config/admin/EditProject.svelte
index 857f7dbd..a4a8d75a 100644
--- a/web/frontend/src/config/admin/EditProject.svelte
+++ b/web/frontend/src/config/admin/EditProject.svelte
@@ -1,97 +1,129 @@
-
- Edit Project Managed By User (Manager Only)
-
-
-
-
-
- Add
- Remove
-
-
- {#if displayMessage}Update: {message.msg}
{/if}
-
-
+
+ Edit Project Managed By User (Manager Only)
+
+
+
+
+
+ Add
+ Remove
+
+
+ {#if displayMessage}Update: {message.msg}
{/if}
+
+
diff --git a/web/frontend/src/config/admin/EditRole.svelte b/web/frontend/src/config/admin/EditRole.svelte
index ca146992..f201f384 100644
--- a/web/frontend/src/config/admin/EditRole.svelte
+++ b/web/frontend/src/config/admin/EditRole.svelte
@@ -1,104 +1,131 @@
-
- Edit User Roles
-
-
-
- Role...
- {#each roles as role}
- {role.charAt(0).toUpperCase() + role.slice(1)}
- {/each}
-
-
-
- Add
- Remove
-
-
- {#if displayMessage}Update: {message.msg}
{/if}
-
-
+
+ Edit User Roles
+
+
+
+ Role...
+ {#each roles as role}
+ {role.charAt(0).toUpperCase() + role.slice(1)}
+ {/each}
+
+
+
+ Add
+ Remove
+
+
+ {#if displayMessage}Update: {message.msg}
{/if}
+
+
diff --git a/web/frontend/src/config/admin/Options.svelte b/web/frontend/src/config/admin/Options.svelte
index 44f9650e..8ad3c44b 100644
--- a/web/frontend/src/config/admin/Options.svelte
+++ b/web/frontend/src/config/admin/Options.svelte
@@ -1,29 +1,34 @@
-
- Scramble Names / Presentation Mode
-
- Active?
-
+
+ Scramble Names / Presentation Mode
+
+ Active?
+
diff --git a/web/frontend/src/config/admin/ShowUsers.svelte b/web/frontend/src/config/admin/ShowUsers.svelte
index 439bebb8..be9b146f 100644
--- a/web/frontend/src/config/admin/ShowUsers.svelte
+++ b/web/frontend/src/config/admin/ShowUsers.svelte
@@ -1,68 +1,87 @@
-
- Special Users
-
- Not created by an LDAP sync and/or having a role other than user
- Reload
-
-
-
-
-
- Username
- Name
- Project(s)
- Email
- Roles
- JWT
- Delete
-
-
-
- {#each userList as user}
-
-
- Delete
-
- {:else}
-
-
- Loading...
-
-
- {/each}
-
-
-
-
+
+ Special Users
+
+ Not created by an LDAP sync and/or having a role other than user
+ Reload
+
+
+
+
+
+ Username
+ Name
+ Project(s)
+ Email
+ Roles
+ JWT
+ Delete
+
+
+
+ {#each userList as user}
+
+
+ Delete
+
+ {:else}
+
+
+
+ Loading...
+
+
+
+ {/each}
+
+
+
+
diff --git a/web/frontend/src/config/admin/ShowUsersRow.svelte b/web/frontend/src/config/admin/ShowUsersRow.svelte
index 34b22404..9845241e 100644
--- a/web/frontend/src/config/admin/ShowUsersRow.svelte
+++ b/web/frontend/src/config/admin/ShowUsersRow.svelte
@@ -1,28 +1,32 @@
{user.username}
{user.name}
{user.projects}
{user.email}
-
{user.roles.join(', ')}
+
{user.roles.join(", ")}
- {#if ! jwt}
- Gen. JWT
- {:else}
-
- {/if}
+ {#if !jwt}
+ Gen. JWT
+ {:else}
+
+ {/if}
diff --git a/web/frontend/src/filters/Cluster.svelte b/web/frontend/src/filters/Cluster.svelte
index 2740b74a..9c823210 100644
--- a/web/frontend/src/filters/Cluster.svelte
+++ b/web/frontend/src/filters/Cluster.svelte
@@ -1,77 +1,95 @@
-
(isOpen = !isOpen)}>
-
- Select Cluster & Slurm Partition
-
-
- {#if $initialized}
- Cluster
-
- (pendingCluster = null, pendingPartition = null)}>
- Any Cluster
-
- {#each clusters as cluster}
- (pendingCluster = cluster.name, pendingPartition = null)}>
- {cluster.name}
-
- {/each}
-
- {/if}
- {#if $initialized && pendingCluster != null}
-
- Partiton
-
- (pendingPartition = null)}>
- Any Partition
-
- {#each clusters.find(c => c.name == pendingCluster).partitions as partition}
- (pendingPartition = partition)}>
- {partition}
-
- {/each}
-
- {/if}
-
-
- {
- isOpen = false
- cluster = pendingCluster
- partition = pendingPartition
- dispatch('update', { cluster, partition })
- }}>Close & Apply
- {
- isOpen = false
- cluster = pendingCluster = null
- partition = pendingPartition = null
- dispatch('update', { cluster, partition })
- }}>Reset
- (isOpen = false)}>Close
-
+ (isOpen = !isOpen)}>
+ Select Cluster & Slurm Partition
+
+ {#if $initialized}
+ Cluster
+
+ ((pendingCluster = null), (pendingPartition = null))}
+ >
+ Any Cluster
+
+ {#each clusters as cluster}
+ (
+ (pendingCluster = cluster.name), (pendingPartition = null)
+ )}
+ >
+ {cluster.name}
+
+ {/each}
+
+ {/if}
+ {#if $initialized && pendingCluster != null}
+
+ Partiton
+
+ (pendingPartition = null)}
+ >
+ Any Partition
+
+ {#each clusters.find((c) => c.name == pendingCluster).partitions as partition}
+ (pendingPartition = partition)}
+ >
+ {partition}
+
+ {/each}
+
+ {/if}
+
+
+ {
+ isOpen = false;
+ cluster = pendingCluster;
+ partition = pendingPartition;
+ dispatch("update", { cluster, partition });
+ }}>Close & Apply
+ {
+ isOpen = false;
+ cluster = pendingCluster = null;
+ partition = pendingPartition = null;
+ dispatch("update", { cluster, partition });
+ }}>Reset
+ (isOpen = false)}>Close
+
diff --git a/web/frontend/src/filters/Duration.svelte b/web/frontend/src/filters/Duration.svelte
index ca2ce453..132ce05e 100644
--- a/web/frontend/src/filters/Duration.svelte
+++ b/web/frontend/src/filters/Duration.svelte
@@ -1,158 +1,244 @@
- (isOpen = !isOpen)}>
-
- Select Job Duration
-
-
- Duration more than
-
-
-
-
-
-
-
-
-
+ (isOpen = !isOpen)}>
+ Select Job Duration
+
+ Duration more than
+
+
+
+
+
+
+
+
+
- Duration less than
-
-
-
-
-
-
-
-
-
+ Duration less than
+
+
+
+
+
+
+
+
+
- Duration between
-
-
-
-
-
-
-
-
- and
-
-
-
-
-
-
-
-
-
-
- {
- isOpen = false
- lessThan = hoursAndMinsToSecs(pendingLessThan)
- moreThan = hoursAndMinsToSecs(pendingMoreThan)
- from = hoursAndMinsToSecs(pendingFrom)
- to = hoursAndMinsToSecs(pendingTo)
- dispatch('update', { lessThan, moreThan, from, to })
- }}>
- Close & Apply
-
- {
- lessThan = null
- moreThan = null
- from = null
- to = null
- reset()
- }}>Reset Values
- {
- isOpen = false
- lessThan = null
- moreThan = null
- from = null
- to = null
- reset()
- dispatch('update', { lessThan, moreThan, from, to })
- }}>Reset Filter
- (isOpen = false)}>Close
-
+ Duration between
+
+
+
+
+
+
+
+
+ and
+
+
+
+
+
+
+
+
+
+
+ {
+ isOpen = false;
+ lessThan = hoursAndMinsToSecs(pendingLessThan);
+ moreThan = hoursAndMinsToSecs(pendingMoreThan);
+ from = hoursAndMinsToSecs(pendingFrom);
+ to = hoursAndMinsToSecs(pendingTo);
+ dispatch("update", { lessThan, moreThan, from, to });
+ }}
+ >
+ Close & Apply
+
+ {
+ lessThan = null;
+ moreThan = null;
+ from = null;
+ to = null;
+ reset();
+ }}>Reset Values
+ {
+ isOpen = false;
+ lessThan = null;
+ moreThan = null;
+ from = null;
+ to = null;
+ reset();
+ dispatch("update", { lessThan, moreThan, from, to });
+ }}>Reset Filter
+ (isOpen = false)}>Close
+
diff --git a/web/frontend/src/filters/Filters.svelte b/web/frontend/src/filters/Filters.svelte
index 49eaed61..8e7a8ef6 100644
--- a/web/frontend/src/filters/Filters.svelte
+++ b/web/frontend/src/filters/Filters.svelte
@@ -10,373 +10,418 @@
- void update(additionalFilters: Object?): Triggers an update
-->
-
-
-
-
- Filters
-
-
-
- Manage Filters
-
- {#if menuText}
- {menuText}
-
- {/if}
- (isClusterOpen = true)}>
- Cluster/Partition
-
- (isJobStatesOpen = true)}>
- Job States
-
- (isStartTimeOpen = true)}>
- Start Time
-
- (isDurationOpen = true)}>
- Duration
-
- (isTagsOpen = true)}>
- Tags
-
- (isResourcesOpen = true)}>
- Resources
-
- (isStatsOpen = true)}>
- (isStatsOpen = true)}/> Statistics
-
- {#if startTimeQuickSelect}
-
- Start Time Qick Selection
- {#each [
- { text: 'Last 6hrs', url: 'last6h', seconds: 6*60*60 },
- // { text: 'Last 12hrs', seconds: 12*60*60 },
- { text: 'Last 24hrs', url: 'last24h', seconds: 24*60*60 },
- // { text: 'Last 48hrs', seconds: 48*60*60 },
- { text: 'Last 7 days', url: 'last7d', seconds: 7*24*60*60 },
- { text: 'Last 30 days', url: 'last30d', seconds: 30*24*60*60 }
- ] as {text, url, seconds}}
- {
- filters.startTime.from = (new Date(Date.now() - seconds * 1000)).toISOString()
- filters.startTime.to = (new Date(Date.now())).toISOString()
- filters.startTime.text = text,
- filters.startTime.url = url
- update()
- }}>
- {text}
-
- {/each}
- {/if}
-
-
-
-
- {#if filters.cluster}
- (isClusterOpen = true)}>
- {filters.cluster}
- {#if filters.partition}
- ({filters.partition})
- {/if}
-
+
+
+
+
+ Filters
+
+
+ Manage Filters
+ {#if menuText}
+ {menuText}
+
{/if}
-
- {#if filters.states.length != allJobStates.length}
- (isJobStatesOpen = true)}>
- {filters.states.join(', ')}
-
+ (isClusterOpen = true)}>
+ Cluster/Partition
+
+ (isJobStatesOpen = true)}>
+ Job States
+
+ (isStartTimeOpen = true)}>
+ Start Time
+
+ (isDurationOpen = true)}>
+ Duration
+
+ (isTagsOpen = true)}>
+ Tags
+
+ (isResourcesOpen = true)}>
+ Resources
+
+ (isStatsOpen = true)}>
+ (isStatsOpen = true)} /> Statistics
+
+ {#if startTimeQuickSelect}
+
+ Start Time Qick Selection
+ {#each [{ text: "Last 6hrs", url: "last6h", seconds: 6 * 60 * 60 }, { text: "Last 24hrs", url: "last24h", seconds: 24 * 60 * 60 }, { text: "Last 7 days", url: "last7d", seconds: 7 * 24 * 60 * 60 }, { text: "Last 30 days", url: "last30d", seconds: 30 * 24 * 60 * 60 }] as { text, url, seconds }}
+ {
+ filters.startTime.from = new Date(
+ Date.now() - seconds * 1000,
+ ).toISOString();
+ filters.startTime.to = new Date(Date.now()).toISOString();
+ (filters.startTime.text = text), (filters.startTime.url = url);
+ update();
+ }}
+ >
+
+ {text}
+
+ {/each}
{/if}
-
- {#if filters.startTime.from || filters.startTime.to}
- (isStartTimeOpen = true)}>
- {#if filters.startTime.text}
- {filters.startTime.text}
- {:else}
- {new Date(filters.startTime.from).toLocaleString()} - {new Date(filters.startTime.to).toLocaleString()}
- {/if}
-
+
+
+
+
+ {#if filters.cluster}
+ (isClusterOpen = true)}>
+ {filters.cluster}
+ {#if filters.partition}
+ ({filters.partition})
{/if}
-
- {#if filters.duration.from || filters.duration.to}
- (isDurationOpen = true)}>
- {Math.floor(filters.duration.from / 3600)}h:{Math.floor(filters.duration.from % 3600 / 60)}m
- -
- {Math.floor(filters.duration.to / 3600)}h:{Math.floor(filters.duration.to % 3600 / 60)}m
-
- {/if}
-
- {#if filters.duration.lessThan}
- (isDurationOpen = true)}>
- Duration less than {Math.floor(filters.duration.lessThan / 3600)}h:{Math.floor(filters.duration.lessThan % 3600 / 60)}m
-
+
+ {/if}
+
+ {#if filters.states.length != allJobStates.length}
+ (isJobStatesOpen = true)}>
+ {filters.states.join(", ")}
+
+ {/if}
+
+ {#if filters.startTime.from || filters.startTime.to}
+ (isStartTimeOpen = true)}>
+ {#if filters.startTime.text}
+ {filters.startTime.text}
+ {:else}
+ {new Date(filters.startTime.from).toLocaleString()} - {new Date(
+ filters.startTime.to,
+ ).toLocaleString()}
{/if}
-
- {#if filters.duration.moreThan}
- (isDurationOpen = true)}>
- Duration more than {Math.floor(filters.duration.moreThan / 3600)}h:{Math.floor(filters.duration.moreThan % 3600 / 60)}m
-
+
+ {/if}
+
+ {#if filters.duration.from || filters.duration.to}
+ (isDurationOpen = true)}>
+ {Math.floor(filters.duration.from / 3600)}h:{Math.floor(
+ (filters.duration.from % 3600) / 60,
+ )}m -
+ {Math.floor(filters.duration.to / 3600)}h:{Math.floor(
+ (filters.duration.to % 3600) / 60,
+ )}m
+
+ {/if}
+
+ {#if filters.duration.lessThan}
+ (isDurationOpen = true)}>
+ Duration less than {Math.floor(
+ filters.duration.lessThan / 3600,
+ )}h:{Math.floor((filters.duration.lessThan % 3600) / 60)}m
+
+ {/if}
+
+ {#if filters.duration.moreThan}
+ (isDurationOpen = true)}>
+ Duration more than {Math.floor(
+ filters.duration.moreThan / 3600,
+ )}h:{Math.floor((filters.duration.moreThan % 3600) / 60)}m
+
+ {/if}
+
+ {#if filters.tags.length != 0}
+ (isTagsOpen = true)}>
+ {#each filters.tags as tagId}
+
+ {/each}
+
+ {/if}
+
+ {#if filters.numNodes.from != null || filters.numNodes.to != null || filters.numHWThreads.from != null || filters.numHWThreads.to != null || filters.numAccelerators.from != null || filters.numAccelerators.to != null}
+ (isResourcesOpen = true)}>
+ {#if isNodesModified}
+ Nodes: {filters.numNodes.from} - {filters.numNodes.to}
{/if}
-
- {#if filters.tags.length != 0}
- (isTagsOpen = true)}>
- {#each filters.tags as tagId}
-
- {/each}
-
+ {#if isNodesModified && isHwthreadsModified},
{/if}
-
- {#if filters.numNodes.from != null || filters.numNodes.to != null ||
- filters.numHWThreads.from != null || filters.numHWThreads.to != null ||
- filters.numAccelerators.from != null || filters.numAccelerators.to != null }
- (isResourcesOpen = true)}>
- {#if isNodesModified } Nodes: {filters.numNodes.from} - {filters.numNodes.to} {/if}
- {#if isNodesModified && isHwthreadsModified }, {/if}
- {#if isHwthreadsModified } HWThreads: {filters.numHWThreads.from} - {filters.numHWThreads.to} {/if}
- {#if (isNodesModified || isHwthreadsModified) && isAccsModified }, {/if}
- {#if isAccsModified } Accelerators: {filters.numAccelerators.from} - {filters.numAccelerators.to} {/if}
-
+ {#if isHwthreadsModified}
+ HWThreads: {filters.numHWThreads.from} - {filters.numHWThreads.to}
{/if}
-
- {#if filters.node != null }
- (isResourcesOpen = true)}>
- Node: {filters.node}
-
+ {#if (isNodesModified || isHwthreadsModified) && isAccsModified},
{/if}
-
- {#if filters.stats.length > 0}
- (isStatsOpen = true)}>
- {filters.stats.map(stat => `${stat.text}: ${stat.from} - ${stat.to}`).join(', ')}
-
+ {#if isAccsModified}
+ Accelerators: {filters.numAccelerators.from} - {filters
+ .numAccelerators.to}
{/if}
-
+
+ {/if}
+
+ {#if filters.node != null}
+ (isResourcesOpen = true)}>
+ Node: {filters.node}
+
+ {/if}
+
+ {#if filters.stats.length > 0}
+ (isStatsOpen = true)}>
+ {filters.stats
+ .map((stat) => `${stat.text}: ${stat.from} - ${stat.to}`)
+ .join(", ")}
+
+ {/if}
+
update()} />
+ {disableClusterSelection}
+ bind:isOpen={isClusterOpen}
+ bind:cluster={filters.cluster}
+ bind:partition={filters.partition}
+ on:update={() => update()}
+/>
update()} />
+ bind:isOpen={isJobStatesOpen}
+ bind:states={filters.states}
+ on:update={() => update()}
+/>
{
- delete filters.startTime['text']
- delete filters.startTime['url']
- update()
- }} />
+ bind:isOpen={isStartTimeOpen}
+ bind:from={filters.startTime.from}
+ bind:to={filters.startTime.to}
+ on:update={() => {
+ delete filters.startTime["text"];
+ delete filters.startTime["url"];
+ update();
+ }}
+/>
update()} />
+ bind:isOpen={isDurationOpen}
+ bind:lessThan={filters.duration.lessThan}
+ bind:moreThan={filters.duration.moreThan}
+ bind:from={filters.duration.from}
+ bind:to={filters.duration.to}
+ on:update={() => update()}
+/>
update()} />
-
- update()} />
-
- update()} />
+ bind:isOpen={isTagsOpen}
+ bind:tags={filters.tags}
+ on:update={() => update()}
+/>
+
+ update()}
+/>
+
+ update()}
+/>
diff --git a/web/frontend/src/filters/InfoBox.svelte b/web/frontend/src/filters/InfoBox.svelte
index 58fc8a5c..8fe75ab6 100644
--- a/web/frontend/src/filters/InfoBox.svelte
+++ b/web/frontend/src/filters/InfoBox.svelte
@@ -1,11 +1,11 @@
-
-
-
+
+
+
diff --git a/web/frontend/src/filters/JobStates.svelte b/web/frontend/src/filters/JobStates.svelte
index 4e5db2e8..e22144fa 100644
--- a/web/frontend/src/filters/JobStates.svelte
+++ b/web/frontend/src/filters/JobStates.svelte
@@ -1,47 +1,76 @@
+
- (isOpen = !isOpen)}>
-
- Select Job States
-
-
-
- {#each allJobStates as state}
-
-
- {state}
-
- {/each}
-
-
-
- {
- isOpen = false
- states = [...pendingStates]
- dispatch('update', { states })
- }}>Close & Apply
- {
- isOpen = false
- states = [...allJobStates]
- pendingStates = [...allJobStates]
- dispatch('update', { states })
- }}>Reset
- (isOpen = false)}>Close
-
+ (isOpen = !isOpen)}>
+ Select Job States
+
+
+ {#each allJobStates as state}
+
+
+ {state}
+
+ {/each}
+
+
+
+ {
+ isOpen = false;
+ states = [...pendingStates];
+ dispatch("update", { states });
+ }}>Close & Apply
+ {
+ isOpen = false;
+ states = [...allJobStates];
+ pendingStates = [...allJobStates];
+ dispatch("update", { states });
+ }}>Reset
+ (isOpen = false)}>Close
+
diff --git a/web/frontend/src/filters/Resources.svelte b/web/frontend/src/filters/Resources.svelte
index be5995a5..01f1c57e 100644
--- a/web/frontend/src/filters/Resources.svelte
+++ b/web/frontend/src/filters/Resources.svelte
@@ -1,145 +1,242 @@
- (isOpen = !isOpen)}>
-
- Select number of utilized Resources
-
-
- Named Node
-
- Number of Nodes
- {
- pendingNumNodes = { from: detail[0], to: detail[1] }
- isNodesModified = true
- }}
- min={minNumNodes} max={maxNumNodes}
- firstSlider={pendingNumNodes.from} secondSlider={pendingNumNodes.to}
- inputFieldFrom={pendingNumNodes.from} inputFieldTo={pendingNumNodes.to}/>
- Number of HWThreads (Use for Single-Node Jobs)
- {
- pendingNumHWThreads = { from: detail[0], to: detail[1] }
- isHwthreadsModified = true
- }}
- min={minNumHWThreads} max={maxNumHWThreads}
- firstSlider={pendingNumHWThreads.from} secondSlider={pendingNumHWThreads.to}
- inputFieldFrom={pendingNumHWThreads.from} inputFieldTo={pendingNumHWThreads.to}/>
- {#if maxNumAccelerators != null && maxNumAccelerators > 1}
- Number of Accelerators
- {
- pendingNumAccelerators = { from: detail[0], to: detail[1] }
- isAccsModified = true
- }}
- min={minNumAccelerators} max={maxNumAccelerators}
- firstSlider={pendingNumAccelerators.from} secondSlider={pendingNumAccelerators.to}
- inputFieldFrom={pendingNumAccelerators.from} inputFieldTo={pendingNumAccelerators.to}/>
- {/if}
-
-
- {
- isOpen = false
- pendingNumNodes = isNodesModified ? pendingNumNodes : { from: null, to: null }
- pendingNumHWThreads = isHwthreadsModified ? pendingNumHWThreads : { from: null, to: null }
- pendingNumAccelerators = isAccsModified ? pendingNumAccelerators : { from: null, to: null }
- numNodes ={ from: pendingNumNodes.from, to: pendingNumNodes.to }
- numHWThreads = { from: pendingNumHWThreads.from, to: pendingNumHWThreads.to }
- numAccelerators = { from: pendingNumAccelerators.from, to: pendingNumAccelerators.to }
- namedNode = pendingNamedNode
- dispatch('update', { numNodes, numHWThreads, numAccelerators, namedNode })
- }}>
- Close & Apply
-
- {
- isOpen = false
- pendingNumNodes = { from: null, to: null }
- pendingNumHWThreads = { from: null, to: null }
- pendingNumAccelerators = { from: null, to: null }
- pendingNamedNode = null
- numNodes = { from: pendingNumNodes.from, to: pendingNumNodes.to }
- numHWThreads = { from: pendingNumHWThreads.from, to: pendingNumHWThreads.to }
- numAccelerators = { from: pendingNumAccelerators.from, to: pendingNumAccelerators.to }
- isNodesModified = false
- isHwthreadsModified = false
- isAccsModified = false
- namedNode = pendingNamedNode
- dispatch('update', { numNodes, numHWThreads, numAccelerators, namedNode})
- }}>Reset
- (isOpen = false)}>Close
-
+ (isOpen = !isOpen)}>
+ Select number of utilized Resources
+
+ Named Node
+
+ Number of Nodes
+ {
+ pendingNumNodes = { from: detail[0], to: detail[1] };
+ isNodesModified = true;
+ }}
+ min={minNumNodes}
+ max={maxNumNodes}
+ firstSlider={pendingNumNodes.from}
+ secondSlider={pendingNumNodes.to}
+ inputFieldFrom={pendingNumNodes.from}
+ inputFieldTo={pendingNumNodes.to}
+ />
+
+ Number of HWThreads (Use for Single-Node Jobs)
+
+ {
+ pendingNumHWThreads = { from: detail[0], to: detail[1] };
+ isHwthreadsModified = true;
+ }}
+ min={minNumHWThreads}
+ max={maxNumHWThreads}
+ firstSlider={pendingNumHWThreads.from}
+ secondSlider={pendingNumHWThreads.to}
+ inputFieldFrom={pendingNumHWThreads.from}
+ inputFieldTo={pendingNumHWThreads.to}
+ />
+ {#if maxNumAccelerators != null && maxNumAccelerators > 1}
+ Number of Accelerators
+ {
+ pendingNumAccelerators = { from: detail[0], to: detail[1] };
+ isAccsModified = true;
+ }}
+ min={minNumAccelerators}
+ max={maxNumAccelerators}
+ firstSlider={pendingNumAccelerators.from}
+ secondSlider={pendingNumAccelerators.to}
+ inputFieldFrom={pendingNumAccelerators.from}
+ inputFieldTo={pendingNumAccelerators.to}
+ />
+ {/if}
+
+
+ {
+ isOpen = false;
+ pendingNumNodes = isNodesModified
+ ? pendingNumNodes
+ : { from: null, to: null };
+ pendingNumHWThreads = isHwthreadsModified
+ ? pendingNumHWThreads
+ : { from: null, to: null };
+ pendingNumAccelerators = isAccsModified
+ ? pendingNumAccelerators
+ : { from: null, to: null };
+ numNodes = { from: pendingNumNodes.from, to: pendingNumNodes.to };
+ numHWThreads = {
+ from: pendingNumHWThreads.from,
+ to: pendingNumHWThreads.to,
+ };
+ numAccelerators = {
+ from: pendingNumAccelerators.from,
+ to: pendingNumAccelerators.to,
+ };
+ namedNode = pendingNamedNode;
+ dispatch("update", {
+ numNodes,
+ numHWThreads,
+ numAccelerators,
+ namedNode,
+ });
+ }}
+ >
+ Close & Apply
+
+ {
+ isOpen = false;
+ pendingNumNodes = { from: null, to: null };
+ pendingNumHWThreads = { from: null, to: null };
+ pendingNumAccelerators = { from: null, to: null };
+ pendingNamedNode = null;
+ numNodes = { from: pendingNumNodes.from, to: pendingNumNodes.to };
+ numHWThreads = {
+ from: pendingNumHWThreads.from,
+ to: pendingNumHWThreads.to,
+ };
+ numAccelerators = {
+ from: pendingNumAccelerators.from,
+ to: pendingNumAccelerators.to,
+ };
+ isNodesModified = false;
+ isHwthreadsModified = false;
+ isAccsModified = false;
+ namedNode = pendingNamedNode;
+ dispatch("update", {
+ numNodes,
+ numHWThreads,
+ numAccelerators,
+ namedNode,
+ });
+ }}>Reset
+ (isOpen = false)}>Close
+
diff --git a/web/frontend/src/filters/StartTime.svelte b/web/frontend/src/filters/StartTime.svelte
index 59f85134..1759b6eb 100644
--- a/web/frontend/src/filters/StartTime.svelte
+++ b/web/frontend/src/filters/StartTime.svelte
@@ -1,86 +1,121 @@
- (isOpen = !isOpen)}>
-
- Select Start Time
-
-
- From
-
-
-
-
-
-
-
-
- To
-
-
-
-
-
-
-
-
-
-
- {
- isOpen = false
- from = toRFC3339(pendingFrom)
- to = toRFC3339(pendingTo, '59')
- dispatch('update', { from, to })
- }}>
- Close & Apply
-
- {
- isOpen = false
- from = null
- to = null
- reset()
- dispatch('update', { from, to })
- }}>Reset
- (isOpen = false)}>Close
-
+ (isOpen = !isOpen)}>
+ Select Start Time
+
+ From
+
+
+
+
+
+
+
+
+ To
+
+
+
+
+
+
+
+
+
+
+ {
+ isOpen = false;
+ from = toRFC3339(pendingFrom);
+ to = toRFC3339(pendingTo, "59");
+ dispatch("update", { from, to });
+ }}
+ >
+ Close & Apply
+
+ {
+ isOpen = false;
+ from = null;
+ to = null;
+ reset();
+ dispatch("update", { from, to });
+ }}>Reset
+ (isOpen = false)}>Close
+
diff --git a/web/frontend/src/filters/Stats.svelte b/web/frontend/src/filters/Stats.svelte
index cf559da2..ee80a4b5 100644
--- a/web/frontend/src/filters/Stats.svelte
+++ b/web/frontend/src/filters/Stats.svelte
@@ -1,115 +1,137 @@
- (isOpen = !isOpen)}>
-
- Filter based on statistics (of non-running jobs)
-
-
- {#each statistics as stat}
- {stat.text}
- (stat.from = detail[0], stat.to = detail[1], stat.enabled = true)}
- min={0} max={stat.peak}
- firstSlider={stat.from} secondSlider={stat.to}
- inputFieldFrom={stat.from} inputFieldTo={stat.to}/>
- {/each}
-
-
- {
- isOpen = false
- stats = statistics.filter(stat => stat.enabled)
- dispatch('update', { stats })
- }}>Close & Apply
- {
- isOpen = false
- resetRange($initialized, cluster)
- statistics.forEach(stat => (stat.enabled = false))
- stats = []
- dispatch('update', { stats })
- }}>Reset
- (isOpen = false)}>Close
-
+ (isOpen = !isOpen)}>
+ Filter based on statistics (of non-running jobs)
+
+ {#each statistics as stat}
+ {stat.text}
+ (
+ (stat.from = detail[0]), (stat.to = detail[1]), (stat.enabled = true)
+ )}
+ min={0}
+ max={stat.peak}
+ firstSlider={stat.from}
+ secondSlider={stat.to}
+ inputFieldFrom={stat.from}
+ inputFieldTo={stat.to}
+ />
+ {/each}
+
+
+ {
+ isOpen = false;
+ stats = statistics.filter((stat) => stat.enabled);
+ dispatch("update", { stats });
+ }}>Close & Apply
+ {
+ isOpen = false;
+ resetRange($initialized, cluster);
+ statistics.forEach((stat) => (stat.enabled = false));
+ stats = [];
+ dispatch("update", { stats });
+ }}>Reset
+ (isOpen = false)}>Close
+
diff --git a/web/frontend/src/filters/Tags.svelte b/web/frontend/src/filters/Tags.svelte
index b5a145a3..06153ed6 100644
--- a/web/frontend/src/filters/Tags.svelte
+++ b/web/frontend/src/filters/Tags.svelte
@@ -1,67 +1,89 @@
- (isOpen = !isOpen)}>
-
- Select Tags
-
-
-
-
-
- {#if $initialized}
- {#each fuzzySearchTags(searchTerm, allTags) as tag (tag)}
-
- {#if pendingTags.includes(tag.id)}
- (pendingTags = pendingTags.filter(id => id != tag.id))}>
-
-
- {:else}
- (pendingTags = [...pendingTags, tag.id])}>
-
-
- {/if}
-
-
-
- {:else}
- No Tags
- {/each}
+ (isOpen = !isOpen)}>
+ Select Tags
+
+
+
+
+ {#if $initialized}
+ {#each fuzzySearchTags(searchTerm, allTags) as tag (tag)}
+
+ {#if pendingTags.includes(tag.id)}
+
+ (pendingTags = pendingTags.filter((id) => id != tag.id))}
+ >
+
+
+ {:else}
+ (pendingTags = [...pendingTags, tag.id])}
+ >
+
+
{/if}
-
-
-
- {
- isOpen = false
- tags = [...pendingTags]
- dispatch('update', { tags })
- }}>Close & Apply
- {
- isOpen = false
- tags = []
- pendingTags = []
- dispatch('update', { tags })
- }}>Reset
- (isOpen = false)}>Close
-
+
+
+
+ {:else}
+ No Tags
+ {/each}
+ {/if}
+
+
+
+ {
+ isOpen = false;
+ tags = [...pendingTags];
+ dispatch("update", { tags });
+ }}>Close & Apply
+ {
+ isOpen = false;
+ tags = [];
+ pendingTags = [];
+ dispatch("update", { tags });
+ }}>Reset
+ (isOpen = false)}>Close
+
diff --git a/web/frontend/src/filters/TimeSelection.svelte b/web/frontend/src/filters/TimeSelection.svelte
index c715b9c4..f9c230b4 100644
--- a/web/frontend/src/filters/TimeSelection.svelte
+++ b/web/frontend/src/filters/TimeSelection.svelte
@@ -1,81 +1,96 @@
-
-
-
- {#if customEnabled}
- Custom
- {/if}
- {#if anyEnabled}
- Any
- {/if}
- {#each Object.entries(options) as [name, seconds]}
- {name}
- {/each}
-
- {#if timeRange == -1}
- from
- updateExplicitTimeRange('from', event)}>
- to
- updateExplicitTimeRange('to', event)}>
+
+ {#if customEnabled}
+ Custom
+ {/if}
+ {#if anyEnabled}
+ Any
{/if}
+ {#each Object.entries(options) as [name, seconds]}
+ {name}
+ {/each}
+
+ {#if timeRange == -1}
+ from
+ updateExplicitTimeRange("from", event)}
+ >
+ to
+ updateExplicitTimeRange("to", event)}
+ >
+ {/if}
diff --git a/web/frontend/src/filters/UserOrProject.svelte b/web/frontend/src/filters/UserOrProject.svelte
index 82358632..983192cf 100644
--- a/web/frontend/src/filters/UserOrProject.svelte
+++ b/web/frontend/src/filters/UserOrProject.svelte
@@ -1,75 +1,84 @@
{#if authlevel >= roles.manager}
-
-
- Search User
- Search Project
-
- termChanged()} on:keyup={(event) => termChanged(event.key == 'Enter' ? 0 : throttle)}
- placeholder={mode == 'user' ? 'filter username...' : 'filter project...'} />
-
+
+
+ Search User
+ Search Project
+
+ termChanged()}
+ on:keyup={(event) => termChanged(event.key == "Enter" ? 0 : throttle)}
+ placeholder={mode == "user" ? "filter username..." : "filter project..."}
+ />
+
{:else}
-
-
- termChanged()} on:keyup={(event) => termChanged(event.key == 'Enter' ? 0 : throttle)} placeholder='filter project...'
- />
-
+
+
+ termChanged()}
+ on:keyup={(event) => termChanged(event.key == "Enter" ? 0 : throttle)}
+ placeholder="filter project..."
+ />
+
{/if}
diff --git a/web/frontend/src/joblist/JobInfo.svelte b/web/frontend/src/joblist/JobInfo.svelte
index b7ca32ac..a30d0584 100644
--- a/web/frontend/src/joblist/JobInfo.svelte
+++ b/web/frontend/src/joblist/JobInfo.svelte
@@ -6,115 +6,138 @@
- jobTags: Defaults to job.tags, usefull for dynamically updating the tags.
-->
+
-
- {job.jobId} ({job.cluster})
- {#if job.metaData?.jobName}
-
- {#if job.metaData?.jobName.length <= 25}
-
{job.metaData.jobName}
- {:else}
-
{job.metaData.jobName}
- {/if}
- {/if}
- {#if job.arrayJobId}
- Array Job:
#{job.arrayJobId}
- {/if}
-
+
+ {job.jobId}
+ ({job.cluster})
+ {#if job.metaData?.jobName}
+
+ {#if job.metaData?.jobName.length <= 25}
+
{job.metaData.jobName}
+ {:else}
+
+ {job.metaData.jobName}
+
+ {/if}
+ {/if}
+ {#if job.arrayJobId}
+ Array Job:
#{job.arrayJobId}
+ {/if}
+
-
-
-
- {scrambleNames ? scramble(job.user) : job.user}
-
- {#if job.userData && job.userData.name}
- ({scrambleNames ? scramble(job.userData.name) : job.userData.name})
- {/if}
- {#if job.project && job.project != 'no project'}
-
-
-
- {scrambleNames ? scramble(job.project) : job.project}
-
- {/if}
-
+
+
+
+ {scrambleNames ? scramble(job.user) : job.user}
+
+ {#if job.userData && job.userData.name}
+ ({scrambleNames ? scramble(job.userData.name) : job.userData.name})
+ {/if}
+ {#if job.project && job.project != "no project"}
+
+
+
+ {scrambleNames ? scramble(job.project) : job.project}
+
+ {/if}
+
-
- {#if job.numNodes == 1}
- {job.resources[0].hostname}
- {:else}
- {job.numNodes}
- {/if}
-
- {#if job.exclusive != 1}
- (shared)
- {/if}
- {#if job.numAcc > 0}
- , {job.numAcc}
- {/if}
- {#if job.numHWThreads > 0}
- , {job.numHWThreads}
- {/if}
-
- {job.subCluster}
-
+
+ {#if job.numNodes == 1}
+ {job.resources[0].hostname}
+ {:else}
+ {job.numNodes}
+ {/if}
+
+ {#if job.exclusive != 1}
+ (shared)
+ {/if}
+ {#if job.numAcc > 0}
+ , {job.numAcc}
+ {/if}
+ {#if job.numHWThreads > 0}
+ , {job.numHWThreads}
+ {/if}
+
+ {job.subCluster}
+
-
- Start: {(new Date(job.startTime)).toLocaleString()}
-
- Duration: {formatDuration(job.duration)} {job.state}
- {#if job.walltime}
-
- Walltime: {formatDuration(job.walltime)}
- {/if}
-
+
+ Start: {new Date(job.startTime).toLocaleString()}
+
+ Duration: {formatDuration(job.duration)}
+ {job.state}
+ {#if job.walltime}
+
+ Walltime: {formatDuration(job.walltime)}
+ {/if}
+
-
- {#each jobTags as tag}
-
- {/each}
-
+
+ {#each jobTags as tag}
+
+ {/each}
+
diff --git a/web/frontend/src/joblist/JobList.svelte b/web/frontend/src/joblist/JobList.svelte
index 5f8d89b8..3efe069b 100644
--- a/web/frontend/src/joblist/JobList.svelte
+++ b/web/frontend/src/joblist/JobList.svelte
@@ -9,284 +9,275 @@
- update(filters?: [JobFilter])
-->
-
-
-
-
-
- Job Info
-
- {#if showFootprint}
-
- Job Footprint
-
- {/if}
- {#each metrics as metric (metric)}
-
- {metric}
- {#if $initialized}
- ({clusters
- .map((cluster) =>
- cluster.metricConfig.find(
- (m) => m.name == metric
- )
- )
- .filter((m) => m != null)
- .map(
- (m) =>
- (m.unit?.prefix
- ? m.unit?.prefix
- : "") +
- (m.unit?.base ? m.unit?.base : "")
- ) // Build unitStr
- .reduce(
- (arr, unitStr) =>
- arr.includes(unitStr)
- ? arr
- : [...arr, unitStr],
- []
- ) // w/o this, output would be [unitStr, unitStr]
- .join(", ")})
- {/if}
-
- {/each}
-
-
-
- {#if $jobs.error}
-
-
- {$jobs.error.message}
-
-
- {:else if $jobs.fetching || !$jobs.data}
-
-
-
-
-
- {:else if $jobs.data && $initialized}
- {#each $jobs.data.jobs.items as job (job)}
-
- {:else}
-
-
- No jobs found
-
-
- {/each}
- {/if}
-
-
-
+
+
+
+
+
+ Job Info
+
+ {#if showFootprint}
+
+ Job Footprint
+
+ {/if}
+ {#each metrics as metric (metric)}
+
+ {metric}
+ {#if $initialized}
+ ({clusters
+ .map((cluster) =>
+ cluster.metricConfig.find((m) => m.name == metric),
+ )
+ .filter((m) => m != null)
+ .map(
+ (m) =>
+ (m.unit?.prefix ? m.unit?.prefix : "") +
+ (m.unit?.base ? m.unit?.base : ""),
+ ) // Build unitStr
+ .reduce(
+ (arr, unitStr) =>
+ arr.includes(unitStr) ? arr : [...arr, unitStr],
+ [],
+ ) // w/o this, output would be [unitStr, unitStr]
+ .join(", ")})
+ {/if}
+
+ {/each}
+
+
+
+ {#if $jobs.error}
+
+
+ {$jobs.error.message}
+
+
+ {:else if $jobs.fetching || !$jobs.data}
+
+
+
+
+
+ {:else if $jobs.data && $initialized}
+ {#each $jobs.data.jobs.items as job (job)}
+
+ {:else}
+
+ No jobs found
+
+ {/each}
+ {/if}
+
+
+
{
- if (detail.itemsPerPage != itemsPerPage) {
- updateConfiguration(
- detail.itemsPerPage.toString(),
- detail.page
- )
- } else {
- paging = { itemsPerPage: detail.itemsPerPage, page: detail.page }
- }
- }}
+ bind:page
+ {itemsPerPage}
+ itemText="Jobs"
+ totalItems={matchedJobs}
+ on:update={({ detail }) => {
+ if (detail.itemsPerPage != itemsPerPage) {
+ updateConfiguration(detail.itemsPerPage.toString(), detail.page);
+ } else {
+ paging = { itemsPerPage: detail.itemsPerPage, page: detail.page };
+ }
+ }}
/>
diff --git a/web/frontend/src/joblist/Refresher.svelte b/web/frontend/src/joblist/Refresher.svelte
index 25877111..635ffbe5 100644
--- a/web/frontend/src/joblist/Refresher.svelte
+++ b/web/frontend/src/joblist/Refresher.svelte
@@ -5,39 +5,46 @@
- 'reload': When fired, the parent component shoud refresh its contents
-->
- dispatch("reload")} disabled={refreshInterval != null}>
- Reload
-
-
- No periodic reload
- Update every 30 seconds
- Update every minute
- Update every two minutes
- Update every 5 minutes
-
-
\ No newline at end of file
+ dispatch("reload")}
+ disabled={refreshInterval != null}
+ >
+ Reload
+
+
+ No periodic reload
+ Update every 30 seconds
+ Update every minute
+ Update every two minutes
+ Update every 5 minutes
+
+
+
diff --git a/web/frontend/src/joblist/Row.svelte b/web/frontend/src/joblist/Row.svelte
index 4d9013c7..41caa539 100644
--- a/web/frontend/src/joblist/Row.svelte
+++ b/web/frontend/src/joblist/Row.svelte
@@ -9,168 +9,189 @@
-->
-
-
+
+
+
+ {#if job.monitoringStatus == 0 || job.monitoringStatus == 2}
+
+ Not monitored or archiving failed
- {#if job.monitoringStatus == 0 || job.monitoringStatus == 2}
-
- Not monitored or archiving failed
-
- {:else if $metricsQuery.fetching}
-
-
-
- {:else if $metricsQuery.error}
-
-
- {$metricsQuery.error.message.length > 500
- ? $metricsQuery.error.message.substring(0, 499) + "..."
- : $metricsQuery.error.message}
-
-
- {:else}
- {#if showFootprint}
-
-
-
- {/if}
- {#each sortAndSelectScope($metricsQuery.data.jobMetrics) as metric, i (metric || i)}
-
-
- {#if metric.disabled == false && metric.data}
-
- {:else if metric.disabled == true && metric.data}
- Metric disabled for subcluster {metric.data.name}:{job.subCluster}
- {:else}
- No dataset returned
- {/if}
-
- {/each}
+ {:else if $metricsQuery.fetching}
+
+
+
+ {:else if $metricsQuery.error}
+
+
+ {$metricsQuery.error.message.length > 500
+ ? $metricsQuery.error.message.substring(0, 499) + "..."
+ : $metricsQuery.error.message}
+
+
+ {:else}
+ {#if showFootprint}
+
+
+
{/if}
+ {#each sortAndSelectScope($metricsQuery.data.jobMetrics) as metric, i (metric || i)}
+
+
+ {#if metric.disabled == false && metric.data}
+
+ {:else if metric.disabled == true && metric.data}
+ Metric disabled for subcluster {metric.data.name}:{job.subCluster}
+ {:else}
+ No dataset returned
+ {/if}
+
+ {/each}
+ {/if}
diff --git a/web/frontend/src/joblist/SortSelection.svelte b/web/frontend/src/joblist/SortSelection.svelte
index 59419642..2cc86151 100644
--- a/web/frontend/src/joblist/SortSelection.svelte
+++ b/web/frontend/src/joblist/SortSelection.svelte
@@ -7,65 +7,94 @@
-->
- { isOpen = !isOpen }}>
-
- Sort rows
-
-
-
- {#each sortableColumns as col, i (col)}
-
- {
- if (activeColumnIdx == i) {
- col.order = col.order == 'DESC' ? 'ASC' : 'DESC'
- } else {
- sortableColumns[activeColumnIdx] = { ...sortableColumns[activeColumnIdx] }
- }
+ {
+ isOpen = !isOpen;
+ }}
+>
+ Sort rows
+
+
+ {#each sortableColumns as col, i (col)}
+
+ {
+ if (activeColumnIdx == i) {
+ col.order = col.order == "DESC" ? "ASC" : "DESC";
+ } else {
+ sortableColumns[activeColumnIdx] = {
+ ...sortableColumns[activeColumnIdx],
+ };
+ }
- sortableColumns[i] = { ...sortableColumns[i] }
- activeColumnIdx = i
- sortableColumns = [...sortableColumns]
- sorting = { field: col.field, order: col.order }
- }}>
-
-
+ sortableColumns[i] = { ...sortableColumns[i] };
+ activeColumnIdx = i;
+ sortableColumns = [...sortableColumns];
+ sorting = { field: col.field, order: col.order };
+ }}
+ >
+
+
- {col.text}
-
- {/each}
-
-
-
- { isOpen = false }}>Close
-
+ {col.text}
+
+ {/each}
+
+
+
+ {
+ isOpen = false;
+ }}>Close
+
\ No newline at end of file
+ .sort {
+ border: none;
+ margin: 0;
+ padding: 0;
+ background: 0 0;
+ transition: all 70ms;
+ }
+
+
diff --git a/web/frontend/src/plots/Histogram.svelte b/web/frontend/src/plots/Histogram.svelte
index 499ea4fa..83003843 100644
--- a/web/frontend/src/plots/Histogram.svelte
+++ b/web/frontend/src/plots/Histogram.svelte
@@ -5,221 +5,222 @@
-->
{#if data.length > 0}
-
+
{:else}
-
Cannot render histogram: No data!
+
Cannot render histogram: No data!
{/if}
-
-
diff --git a/web/frontend/src/plots/MetricPlot.svelte b/web/frontend/src/plots/MetricPlot.svelte
index 7bd264c3..af8f22a3 100644
--- a/web/frontend/src/plots/MetricPlot.svelte
+++ b/web/frontend/src/plots/MetricPlot.svelte
@@ -1,3 +1,120 @@
+
+
-
{#if series[0].data.length > 0}
-
+
{:else}
-
Cannot render plot: No series data returned for {metric}
+
Cannot render plot: No series data returned for {metric}
{/if}
diff --git a/web/frontend/src/plots/Roofline.svelte b/web/frontend/src/plots/Roofline.svelte
index d4ed5f6b..1e47f6f4 100644
--- a/web/frontend/src/plots/Roofline.svelte
+++ b/web/frontend/src/plots/Roofline.svelte
@@ -1,254 +1,339 @@
{#if data != null}
-
+
{:else}
-
Cannot render roofline: No data!
-{/if}
\ No newline at end of file
+
Cannot render roofline: No data!
+{/if}
+