Skip to content

Commit

Permalink
backport of commit d349434
Browse files Browse the repository at this point in the history
  • Loading branch information
philrenaud authored Jun 12, 2024
1 parent 0e91d63 commit 5084269
Show file tree
Hide file tree
Showing 14 changed files with 112 additions and 94 deletions.
3 changes: 3 additions & 0 deletions .changelog/23290.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
ui: shorten client/node metadata/attributes display and make parent-terminal attributes show up
```
19 changes: 19 additions & 0 deletions ui/app/components/job-page/parts/stats-box.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,23 @@ import { inject as service } from '@ember/service';

export default class StatsBox extends Component {
@service system;

get packDetails() {
let packMeta = this.args.job?.meta?.structured.root.children.pack;
if (!packMeta) {
return null;
} else {
return packMeta.files
.map((file) => {
return {
key: file.name,
value: file.variable.value,
};
})
.reduce((acc, file) => {
acc[file.key] = file.value;
return acc;
}, {});
}
}
}
8 changes: 5 additions & 3 deletions ui/app/models/node-driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import classic from 'ember-classic-decorator';
import Fragment from 'ember-data-model-fragments/fragment';
import { get, computed } from '@ember/object';
import { computed } from '@ember/object';
import { attr } from '@ember-data/model';
import { fragmentOwner } from 'ember-data-model-fragments/attributes';
import { fragment } from 'ember-data-model-fragments/attributes';
Expand All @@ -18,8 +18,10 @@ export default class NodeDriver extends Fragment {

@computed('name', 'attributes.structured')
get attributesShort() {
const attributes = this.get('attributes.structured');
return get(attributes, `driver.${this.name}`);
const attributes = this.get(
`attributes.structured.root.children.driver.children.${this.name}`
);
return attributes;
}

@attr('string') name;
Expand Down
11 changes: 6 additions & 5 deletions ui/app/models/structured-attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import { set } from '@ember/object';
import { get, computed } from '@ember/object';
import { attr } from '@ember-data/model';
import Fragment from 'ember-data-model-fragments/fragment';
import flat from 'flat';

const { unflatten } = flat;
import PathTree from 'nomad-ui/utils/path-tree';

export default class StructuredAttributes extends Fragment {
@attr() raw;
Expand All @@ -26,14 +24,17 @@ export default class StructuredAttributes extends Fragment {
return undefined;
}

// `unflatten` doesn't sort keys before unflattening, so manual preprocessing is necessary.
const attrs = Object.keys(original)
.sort()
.reduce((obj, key) => {
obj[key] = original[key];
return obj;
}, {});
return unflatten(attrs, { overwrite: true });
let pathValueArray = Object.entries(attrs).map(([path, value]) => {
return { path, value };
});
let pathTree = new PathTree(pathValueArray, { delimiter: '.' });
return pathTree;
}

unknownProperty(key) {
Expand Down
2 changes: 1 addition & 1 deletion ui/app/styles/core/table.scss
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@
}

.is-faded {
color: $grey-light;
color: darken($grey-light, 10%);
}
}

Expand Down
8 changes: 4 additions & 4 deletions ui/app/templates/clients/client/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@
{{capitalize a.item.name}}
Attributes
</div>
{{#if a.item.attributes.structured}}
{{#if a.item.attributesShort}}
<div class="boxed-section-body is-full-bleed">
<AttributesTable
@attributePairs={{a.item.attributesShort}}
Expand Down Expand Up @@ -821,7 +821,7 @@
<div class="boxed-section-body is-full-bleed">
<AttributesTable
data-test-attributes
@attributePairs={{this.model.attributes.structured}}
@attributePairs={{this.model.attributes.structured.root}}
@class="attributes-table"
@copyable={{true}}
/>
Expand All @@ -835,7 +835,7 @@
<div class="boxed-section-body is-full-bleed">
<AttributesTable
data-test-meta
@attributePairs={{this.model.meta.structured}}
@attributePairs={{this.model.meta.structured.root}}
@editable={{can "write client"}}
@onKVSave={{this.addDynamicMetaData}}
@onKVEdit={{this.validateMetadata}}
Expand Down Expand Up @@ -907,4 +907,4 @@
{{/if}}
{{/if}}
</div>
</section>
</section>
32 changes: 19 additions & 13 deletions ui/app/templates/components/attributes-section.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,23 @@
SPDX-License-Identifier: BUSL-1.1
~}}

{{#each-in this.attributes as |key value|}}
{{#if (is-object value)}}
<tr data-test-attributes-section>
<td data-test-heading class="is-subheading" colspan="2">
{{#if this.prefix}}<span class="is-faded" data-test-prefix>{{this.prefix}}.</span>{{/if}}{{key}}
</td>
</tr>
<AttributesSection @prefix={{if this.prefix (concat this.prefix "." key) key}} @attributes={{value}}
@key={{key}} @value={{value}} @editable={{@editable}} @onKVSave={{@onKVSave}} @copyable={{@copyable}} />
{{else}}
<MetadataKv @prefix={{this.prefix}}
@key={{key}} @value={{value}} @editable={{@editable}} @onKVSave={{@onKVSave}} @copyable={{@copyable}} />
{{/if}}
{{#each this.attributes.files as |file|}}
<MetadataKv
@prefix={{file.prefix}}
@key={{file.name}}
@value={{file.variable.value}}
@editable={{@editable}}
@onKVSave={{@onKVSave}}
@copyable={{@copyable}}
/>
{{/each}}
{{#each-in this.attributes.children as |key value|}}
<AttributesSection
@attributes={{value}}
@key={{key}}
@value={{value}}
@editable={{@editable}}
@onKVSave={{@onKVSave}}
@copyable={{@copyable}}
/>
{{/each-in}}
4 changes: 2 additions & 2 deletions ui/app/templates/components/job-page/parts/meta.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
<div class="boxed-section-body is-full-bleed">
<AttributesTable
data-test-meta
@attributePairs={{@job.meta.structured}}
@attributePairs={{@job.meta.structured.root}}
@class="attributes-table" />
</div>
</div>
{{/if}}
{{/if}}
16 changes: 8 additions & 8 deletions ui/app/templates/components/job-page/parts/stats-box.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -38,29 +38,29 @@
{{yield to="after-namespace"}}
</div>

{{#if @job.meta.structured.pack.name}}
{{#if this.packDetails.name}}
<div class="boxed-section-body inline-definitions">
<span class="label" style="width: 6.125rem;">Pack Details</span>
<span class="pair" data-test-pack-stat="name">
<span class="term">Name</span>
{{@job.meta.structured.pack.name}}
{{this.packDetails.name}}
</span>
{{#if @job.meta.structured.pack.registry}}
{{#if this.packDetails.registry}}
<span class="pair" data-test-pack-stat="registry">
<span class="term">Registry</span>
{{@job.meta.structured.pack.registry}}
{{this.packDetails.registry}}
</span>
{{/if}}
{{#if @job.meta.structured.pack.version}}
{{#if this.packDetails.version}}
<span class="pair" data-test-pack-stat="version">
<span class="term">Version</span>
{{@job.meta.structured.pack.version}}
{{this.packDetails.version}}
</span>
{{/if}}
{{#if @job.meta.structured.pack.revision}}
{{#if this.packDetails.revision}}
<span class="pair" data-test-pack-stat="revision">
<span class="term">Revision</span>
{{@job.meta.structured.pack.revision}}
{{this.packDetails.revision}}
</span>
{{/if}}
{{yield to="pack"}}
Expand Down
2 changes: 1 addition & 1 deletion ui/app/templates/components/job-page/parts/title.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Hds::PageHeader class="job-page-header" as |PH|>
<PH.Title data-test-job-name>
{{or this.title this.job.name}}
{{#if @job.meta.structured.pack}}
{{#if @job.meta.structured.root.children.pack}}
<span data-test-pack-tag class="tag is-hollow">
{{x-icon "box" class= "test"}}
<span>Pack</span>
Expand Down
13 changes: 9 additions & 4 deletions ui/app/utils/path-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { trimPath } from '../helpers/trim-path';
* @property {string} path - the folder path containing our "file", relative to parent
* @property {string} name - the variable "file" name
* @property {string} absoluteFilePath - the folder path containing our "file", absolute
* @property {string} prefix - the path prefix
* @property {VariableModel} variable - the variable itself
*/

Expand All @@ -39,11 +40,14 @@ export default class PathTree {
/**
* @param {MutableArray<VariableModel>} variables
*/
constructor(variables) {
constructor(variables, { delimiter = '/' } = {}) {
this.delimiter = delimiter;
this.variables = variables;
this.paths = this.generatePaths(variables);
}

delimiter = '/';

/**
* @type {VariableFolder}
*/
Expand All @@ -56,14 +60,15 @@ export default class PathTree {
*/
generatePaths = (variables) => {
variables.forEach((variable) => {
const path = trimPath([variable.path]).split('/');
const path = trimPath([variable.path]).split(this.delimiter);
path.reduce((acc, segment, index, arr) => {
if (index === arr.length - 1) {
// If it's a file (end of the segment array)
acc.files.push({
name: segment,
absoluteFilePath: path.join('/'),
path: arr.slice(0, index + 1).join('/'),
absoluteFilePath: path.join(this.delimiter),
path: arr.slice(0, index + 1).join(this.delimiter),
prefix: arr.slice(0, index).join(this.delimiter),
variable,
});
} else {
Expand Down
1 change: 0 additions & 1 deletion ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@
"eslint-plugin-prettier": "^3.4.1",
"eslint-plugin-qunit": "^6.2.0",
"faker": "^4.1.0",
"flat": "^5.0.2",
"fuse.js": "^3.4.4",
"glob": "^7.2.0",
"http-proxy": "^1.1.6",
Expand Down
78 changes: 33 additions & 45 deletions ui/tests/integration/components/attributes-table-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,49 @@ import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
import flat from 'flat';

const { flatten } = flat;
import PathTree from 'nomad-ui/utils/path-tree';

module('Integration | Component | attributes table', function (hooks) {
setupRenderingTest(hooks);

const commonAttributes = {
key: 'value',
nested: {
props: 'are',
supported: 'just',
fine: null,
const commonAttributes = [
{
path: 'key',
value: 'value',
},
{
path: 'nested.props',
value: 'are',
},
{
path: 'nested.supported',
value: 'just',
},
{
path: 'nested.fine',
value: null,
},
so: {
are: {
deeply: {
nested: 'properties',
like: 'these ones',
},
},
{
path: 'so.are.deeply.nested',
value: 'properties',
},
};
{
path: 'so.are.deeply.like',
value: 'these ones',
},
];

const commonAttributesTree = new PathTree(commonAttributes, {
delimiter: '.',
});

test('should render a row for each key/value pair in a deep object', async function (assert) {
assert.expect(2);

this.set('attributes', commonAttributes);
this.set('attributes', commonAttributesTree.root);
await render(hbs`<AttributesTable @attributePairs={{attributes}} />`);

const rowsCount = Object.keys(flatten(commonAttributes)).length;
const rowsCount = commonAttributes.length;
assert.equal(
this.element.querySelectorAll(
'[data-test-attributes-section] [data-test-value]'
Expand All @@ -51,7 +63,7 @@ module('Integration | Component | attributes table', function (hooks) {
});

test('should render the full path of key/value pair from the root of the object', async function (assert) {
this.set('attributes', commonAttributes);
this.set('attributes', commonAttributesTree.root);
await render(hbs`<AttributesTable @attributePairs={{attributes}} />`);

assert.equal(
Expand All @@ -64,8 +76,7 @@ module('Integration | Component | attributes table', function (hooks) {
'value',
'Row renders the value'
);

const deepRow = findAll('[data-test-attributes-section]')[8];
const deepRow = findAll('[data-test-attributes-section]')[4];
assert.equal(
deepRow.querySelector('[data-test-key]').textContent.trim(),
'so.are.deeply.nested',
Expand All @@ -81,27 +92,4 @@ module('Integration | Component | attributes table', function (hooks) {
'properties'
);
});

test('should render a row for key/value pairs even when the value is another object', async function (assert) {
this.set('attributes', commonAttributes);
await render(hbs`<AttributesTable @attributePairs={{attributes}} />`);

const countOfParentRows = countOfParentKeys(commonAttributes);
assert.equal(
findAll('[data-test-heading]').length,
countOfParentRows,
'Each key for a nested object gets a row with no value'
);
});

function countOfParentKeys(obj) {
return Object.keys(obj).reduce((count, key) => {
const value = obj[key];
return isObject(value) ? count + 1 + countOfParentKeys(value) : count;
}, 0);
}

function isObject(value) {
return !Array.isArray(value) && value != null && typeof value === 'object';
}
});
Loading

0 comments on commit 5084269

Please sign in to comment.