mirror of
https://github.com/kemko/nomad.git
synced 2026-01-06 10:25:42 +03:00
Merge pull request #17691 from hashicorp/f/missing-chart-stories
[UI] Missing chart stories
This commit is contained in:
116
ui/stories/charts/recommendation-chart.stories.js
Normal file
116
ui/stories/charts/recommendation-chart.stories.js
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import DelayedTruth from '../utils/delayed-truth';
|
||||
import {
|
||||
withKnobs,
|
||||
optionsKnob,
|
||||
number,
|
||||
boolean,
|
||||
} from '@storybook/addon-knobs';
|
||||
|
||||
export default {
|
||||
title: 'Charts/Recomendation Chart',
|
||||
decorators: [withKnobs],
|
||||
};
|
||||
|
||||
export let Configurable = () => {
|
||||
return {
|
||||
template: hbs`
|
||||
<SvgPatterns />
|
||||
{{#if delayedTruth.complete}}
|
||||
<Das::RecommendationChart
|
||||
@resource={{resource}}
|
||||
@currentValue={{current}}
|
||||
@recommendedValue={{recommendedValue}}
|
||||
@stats={{stats}}
|
||||
@disabled={{disabled}}
|
||||
/>
|
||||
{{/if}}
|
||||
`,
|
||||
context: contextFactory(),
|
||||
};
|
||||
};
|
||||
|
||||
export let Standard = () => {
|
||||
return {
|
||||
template: hbs`
|
||||
<SvgPatterns />
|
||||
<div style="max-width: 500px">
|
||||
{{#if delayedTruth.complete}}
|
||||
<Das::RecommendationChart
|
||||
@resource="CPU"
|
||||
@currentValue={{cpu.current}}
|
||||
@recommendedValue={{cpu.recommendedValue}}
|
||||
@stats={{cpu.stats}}
|
||||
/>
|
||||
<Das::RecommendationChart
|
||||
@resource="MemoryMB"
|
||||
@currentValue={{mem.current}}
|
||||
@recommendedValue={{mem.recommendedValue}}
|
||||
@stats={{mem.stats}}
|
||||
/>
|
||||
<hr/>
|
||||
<Das::RecommendationChart
|
||||
@resource="CPU"
|
||||
@currentValue={{cpu.current}}
|
||||
@recommendedValue={{cpu.recommendedValue}}
|
||||
@stats={{cpu.stats}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
<Das::RecommendationChart
|
||||
@resource="MemoryMB"
|
||||
@currentValue={{mem.current}}
|
||||
@recommendedValue={{mem.recommendedValue}}
|
||||
@stats={{mem.stats}}
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
`,
|
||||
context: {
|
||||
delayedTruth: DelayedTruth.create(),
|
||||
cpu: {
|
||||
current: 100,
|
||||
recommendedValue: 600,
|
||||
stats: {
|
||||
mean: 300,
|
||||
p99: 500,
|
||||
max: 525,
|
||||
},
|
||||
},
|
||||
mem: {
|
||||
current: 2048,
|
||||
recommendedValue: 256,
|
||||
stats: {
|
||||
mean: 140,
|
||||
p99: 215,
|
||||
max: 225,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
function contextFactory() {
|
||||
const numberConfig = { range: true, min: 0, max: 1000, step: 1 };
|
||||
return {
|
||||
delayedTruth: DelayedTruth.create(),
|
||||
resource: optionsKnob(
|
||||
'Resource',
|
||||
{ Cpu: 'CPU', Memory: 'MemoryMB' },
|
||||
'CPU',
|
||||
{ display: 'inline-radio' }
|
||||
),
|
||||
current: number('Current', 100, numberConfig),
|
||||
recommendedValue: number('Recommendation', 300, numberConfig),
|
||||
stats: {
|
||||
mean: number('Stat: mean', 150, numberConfig),
|
||||
p99: number('Stat: p99', 600, numberConfig),
|
||||
max: number('Stat: max', 650, numberConfig),
|
||||
},
|
||||
disabled: boolean('Disabled', false),
|
||||
};
|
||||
}
|
||||
195
ui/stories/charts/topo-viz.stories.js
Normal file
195
ui/stories/charts/topo-viz.stories.js
Normal file
@@ -0,0 +1,195 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import DelayedTruth from '../utils/delayed-truth';
|
||||
import { withKnobs, boolean } from '@storybook/addon-knobs';
|
||||
import { getOwner } from '@ember/application';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { scaleLinear } from 'd3-scale';
|
||||
import faker from 'faker';
|
||||
|
||||
export default {
|
||||
title: 'Charts/Topo Viz',
|
||||
decorators: [withKnobs],
|
||||
};
|
||||
|
||||
const nodeGen = (name, datacenter, memory, cpu, allocations = []) => ({
|
||||
datacenter,
|
||||
memory,
|
||||
cpu,
|
||||
node: { name, isEligible: true, isDraining: false },
|
||||
allocations: allocations.map((alloc) => ({
|
||||
memory: alloc.memory,
|
||||
cpu: alloc.cpu,
|
||||
memoryPercent: alloc.memory / memory,
|
||||
cpuPercent: alloc.cpu / cpu,
|
||||
allocation: {
|
||||
id: faker.random.uuid(),
|
||||
isScheduled: true,
|
||||
clientStatus: alloc.clientStatus,
|
||||
},
|
||||
})),
|
||||
});
|
||||
|
||||
const nodeModelGen = (datacenter, id, name, resources = '2000/1000') => {
|
||||
const [cpu, memory] = resources.split('/');
|
||||
return {
|
||||
datacenter,
|
||||
id,
|
||||
name,
|
||||
isEligible: true,
|
||||
isDraining: false,
|
||||
resources: { cpu, memory },
|
||||
};
|
||||
};
|
||||
|
||||
const allocModelGen = (
|
||||
id,
|
||||
taskGroupName,
|
||||
clientStatus,
|
||||
nodeId,
|
||||
jobId,
|
||||
resources = '100/100'
|
||||
) => {
|
||||
const [cpu, memory] = resources.split('/');
|
||||
return {
|
||||
id,
|
||||
taskGroupName,
|
||||
clientStatus,
|
||||
isScheduled: true,
|
||||
allocatedResources: { cpu, memory },
|
||||
belongsTo(t) {
|
||||
return {
|
||||
id() {
|
||||
return t === 'node' ? nodeId : jobId;
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export let Node = () => ({
|
||||
template: hbs`
|
||||
<SvgPatterns />
|
||||
{{#if delayedTruth.complete}}
|
||||
<TopoViz::Node
|
||||
@node={{node}}
|
||||
@isDense={{isDense}}
|
||||
@heightScale={{heightScale}}
|
||||
/>
|
||||
{{/if}}
|
||||
`,
|
||||
context: {
|
||||
delayedTruth: DelayedTruth.create(),
|
||||
isDense: boolean('isDense', false),
|
||||
heightScale: scaleLinear().range([15, 40]).domain([100, 1000]),
|
||||
node: nodeGen('Node One', 'dc1', 1000, 1000, [
|
||||
{ memory: 100, cpu: 100, clientStatus: 'pending' },
|
||||
{ memory: 250, cpu: 300, clientStatus: 'running' },
|
||||
{ memory: 300, cpu: 200, clientStatus: 'running' },
|
||||
]),
|
||||
},
|
||||
});
|
||||
|
||||
export let Datacenter = () => ({
|
||||
template: hbs`
|
||||
<SvgPatterns />
|
||||
{{#if delayedTruth.complete}}
|
||||
<TopoViz::Datacenter
|
||||
@datacenter={{dc}}
|
||||
@isSingleColumn={{isSingleColumn}}
|
||||
@isDense={{isDense}}
|
||||
@heightScale={{heightScale}}
|
||||
/>
|
||||
{{/if}}
|
||||
`,
|
||||
context: {
|
||||
delayedTruth: DelayedTruth.create(),
|
||||
isSingleColumn: boolean('isSingleColumn', false),
|
||||
isDense: boolean('isDense', false),
|
||||
heightScale: scaleLinear().range([15, 40]).domain([100, 1000]),
|
||||
dc: {
|
||||
name: 'dc1',
|
||||
nodes: [
|
||||
nodeGen('Node One', 'dc1', 1000, 1000, [
|
||||
{ memory: 100, cpu: 100, clientStatus: 'pending' },
|
||||
{ memory: 250, cpu: 300, clientStatus: 'running' },
|
||||
{ memory: 300, cpu: 200, clientStatus: 'running' },
|
||||
]),
|
||||
nodeGen('And Two', 'dc1', 500, 1000, [
|
||||
{ memory: 100, cpu: 100, clientStatus: 'pending' },
|
||||
{ memory: 250, cpu: 300, clientStatus: 'running' },
|
||||
{ memory: 100, cpu: 100, clientStatus: 'running' },
|
||||
{ memory: 100, cpu: 100, clientStatus: 'running' },
|
||||
{ memory: 100, cpu: 100, clientStatus: 'running' },
|
||||
]),
|
||||
nodeGen('Three', 'dc1', 500, 500, [
|
||||
{ memory: 100, cpu: 300, clientStatus: 'running' },
|
||||
{ memory: 300, cpu: 200, clientStatus: 'pending' },
|
||||
]),
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export let FullViz = () => ({
|
||||
template: hbs`
|
||||
{{#if delayedTruth.complete}}
|
||||
<TopoViz
|
||||
@nodes={{nodes}}
|
||||
@allocations={{allocations}}
|
||||
/>
|
||||
{{/if}}
|
||||
`,
|
||||
context: {
|
||||
delayedTruth: DelayedTruth.create(),
|
||||
nodes: [
|
||||
nodeModelGen('dc1', '1', 'pdx-1', '2000/1000'),
|
||||
nodeModelGen('dc1', '2', 'pdx-2', '2000/1000'),
|
||||
nodeModelGen('dc1', '3', 'pdx-3', '2000/3000'),
|
||||
nodeModelGen('dc2', '4', 'yyz-1', '2000/1000'),
|
||||
nodeModelGen('dc2', '5', 'yyz-2', '2000/2000'),
|
||||
],
|
||||
allocations: [
|
||||
allocModelGen('1', 'name', 'running', '1', 'job-1', '200/500'),
|
||||
allocModelGen('1', 'name', 'running', '5', 'job-1', '200/500'),
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
export let EmberData = () => ({
|
||||
template: hbs`
|
||||
<div class="notification is-info">
|
||||
<h3 class='title is-4'>This visualization uses data from mirage.</h3>
|
||||
<p>Change the mirage scenario to see different cluster states visualized.</p>
|
||||
</div>
|
||||
{{#if (and delayedTruth.complete nodes allocations)}}
|
||||
<TopoViz
|
||||
@nodes={{nodes}}
|
||||
@allocations={{allocations}}
|
||||
/>
|
||||
{{/if}}
|
||||
`,
|
||||
context: {
|
||||
delayedTruth: DelayedTruth.create(),
|
||||
nodes: tracked([]),
|
||||
allocations: tracked([]),
|
||||
|
||||
async init() {
|
||||
this._super(...arguments);
|
||||
|
||||
const owner = getOwner(this);
|
||||
const store = owner.lookup('service:store');
|
||||
|
||||
this.nodes = await store.query('node', { resources: true });
|
||||
this.allocations = await store.query('allocation', {
|
||||
resources: true,
|
||||
task_states: false,
|
||||
namespace: '*',
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user