Merge pull request #4541 from hashicorp/f-ui-new-json-viewer
UI: New JSON viewer
This commit is contained in:
commit
efa90d96f2
|
@ -1,33 +1,11 @@
|
|||
import Component from '@ember/component';
|
||||
import { computed } from '@ember/object';
|
||||
import { run } from '@ember/runloop';
|
||||
import { copy } from '@ember/object/internals';
|
||||
import JSONFormatter from 'json-formatter-js';
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ['json-viewer'],
|
||||
|
||||
json: null,
|
||||
expandDepth: Infinity,
|
||||
|
||||
formatter: computed('json', 'expandDepth', function() {
|
||||
return new JSONFormatter(copy(this.get('json'), true), this.get('expandDepth'), {
|
||||
theme: 'nomad',
|
||||
});
|
||||
jsonStr: computed('json', function() {
|
||||
return JSON.stringify(this.get('json'), null, 2);
|
||||
}),
|
||||
|
||||
didReceiveAttrs() {
|
||||
const json = this.get('json');
|
||||
if (!json) {
|
||||
return;
|
||||
}
|
||||
|
||||
run.scheduleOnce('afterRender', this, embedViewer);
|
||||
},
|
||||
});
|
||||
|
||||
function embedViewer() {
|
||||
this.$()
|
||||
.empty()
|
||||
.append(this.get('formatter').render());
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
@import './components/accordion';
|
||||
@import './components/badge';
|
||||
@import './components/boxed-section';
|
||||
@import './components/codemirror';
|
||||
@import './components/cli-window';
|
||||
@import './components/dropdown';
|
||||
@import './components/ember-power-select';
|
||||
|
@ -10,7 +11,6 @@
|
|||
@import './components/gutter-toggle';
|
||||
@import './components/inline-definitions';
|
||||
@import './components/job-diff';
|
||||
@import './components/json-viewer';
|
||||
@import './components/loading-spinner';
|
||||
@import './components/metrics';
|
||||
@import './components/node-status-light';
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
}
|
||||
|
||||
&.is-dark {
|
||||
background: darken($dark, 5%);
|
||||
background: $dark-2;
|
||||
border-color: lighten($dark, 30%);
|
||||
color: $white;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
$dark-bright: lighten($dark, 15%);
|
||||
|
||||
.CodeMirror {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.cm-s-hashi,
|
||||
.cm-s-hashi-read-only {
|
||||
&.CodeMirror {
|
||||
background-color: $dark-3;
|
||||
color: $grey-blue;
|
||||
border: none;
|
||||
font-family: $family-monospace;
|
||||
-webkit-font-smoothing: auto;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.CodeMirror-gutters {
|
||||
background-color: $dark-2;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.CodeMirror-cursor {
|
||||
border-left: solid thin $white-ter;
|
||||
}
|
||||
|
||||
.CodeMirror-linenumber {
|
||||
color: $dark-bright;
|
||||
}
|
||||
|
||||
&.CodeMirror-focused div.CodeMirror-selected {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.CodeMirror-line::selection,
|
||||
.CodeMirror-line > span::selection,
|
||||
.CodeMirror-line > span > span::selection {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
span.cm-comment {
|
||||
color: $grey-light;
|
||||
}
|
||||
|
||||
span.cm-string,
|
||||
span.cm-string-2 {
|
||||
color: $nomad-green;
|
||||
}
|
||||
|
||||
span.cm-number {
|
||||
color: $serf-red;
|
||||
}
|
||||
|
||||
span.cm-variable {
|
||||
color: $packer-blue;
|
||||
}
|
||||
|
||||
span.cm-variable-2 {
|
||||
color: $packer-blue;
|
||||
}
|
||||
|
||||
span.cm-def {
|
||||
color: $nomad-green;
|
||||
}
|
||||
|
||||
span.cm-operator {
|
||||
color: $grey;
|
||||
}
|
||||
span.cm-keyword {
|
||||
color: $yellow;
|
||||
}
|
||||
|
||||
span.cm-atom {
|
||||
color: $terraform-purple-bright;
|
||||
}
|
||||
|
||||
span.cm-meta {
|
||||
color: $nomad-green;
|
||||
}
|
||||
|
||||
span.cm-tag {
|
||||
color: $nomad-green;
|
||||
}
|
||||
|
||||
span.cm-attribute {
|
||||
color: $consul-pink;
|
||||
}
|
||||
|
||||
span.cm-qualifier {
|
||||
color: $consul-pink;
|
||||
}
|
||||
|
||||
span.cm-property {
|
||||
color: $nomad-green;
|
||||
}
|
||||
|
||||
span.cm-variable-3 {
|
||||
color: $consul-pink;
|
||||
}
|
||||
|
||||
span.cm-builtin {
|
||||
color: $consul-pink;
|
||||
}
|
||||
|
||||
.CodeMirror-activeline-background {
|
||||
background: $black-ter;
|
||||
}
|
||||
|
||||
.CodeMirror-matchingbracket {
|
||||
text-decoration: underline;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
.cm-s-auto-height.CodeMirror {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.cm-s-hashi-read-only {
|
||||
&.CodeMirror {
|
||||
background-color: $dark-2;
|
||||
}
|
||||
|
||||
.CodeMirror-gutters {
|
||||
background-color: $dark-2;
|
||||
}
|
||||
}
|
|
@ -1,146 +0,0 @@
|
|||
@mixin theme(
|
||||
$default-color: black,
|
||||
$string-color: green,
|
||||
$number-color: blue,
|
||||
$boolean-color: red,
|
||||
$null-color: #855A00,
|
||||
$undefined-color: rgb(202, 11, 105),
|
||||
$function-color: #FF20ED,
|
||||
$toggler-opacity: 0.6,
|
||||
$toggler-color: #45376F,
|
||||
$bracket-color: blue,
|
||||
$key-color: #00008B,
|
||||
$url-color: blue
|
||||
) {
|
||||
font-family: monospace;
|
||||
&,
|
||||
a,
|
||||
a:hover {
|
||||
color: $default-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.json-formatter-row {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.json-formatter-children {
|
||||
&.json-formatter-empty {
|
||||
opacity: 0.5;
|
||||
margin-left: 1rem;
|
||||
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
&.json-formatter-object:after {
|
||||
content: 'No properties';
|
||||
}
|
||||
&.json-formatter-array:after {
|
||||
content: '[]';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.json-formatter-string {
|
||||
color: $string-color;
|
||||
white-space: pre;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.json-formatter-number {
|
||||
color: $number-color;
|
||||
}
|
||||
.json-formatter-boolean {
|
||||
color: $boolean-color;
|
||||
}
|
||||
.json-formatter-null {
|
||||
color: $null-color;
|
||||
}
|
||||
.json-formatter-undefined {
|
||||
color: $undefined-color;
|
||||
}
|
||||
.json-formatter-function {
|
||||
color: $function-color;
|
||||
}
|
||||
.json-formatter-date {
|
||||
background-color: fade($default-color, 5%);
|
||||
}
|
||||
.json-formatter-url {
|
||||
text-decoration: underline;
|
||||
color: $url-color;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.json-formatter-bracket {
|
||||
color: $bracket-color;
|
||||
}
|
||||
.json-formatter-key {
|
||||
color: $key-color;
|
||||
cursor: pointer;
|
||||
padding-right: 0.2rem;
|
||||
}
|
||||
|
||||
.json-formatter-constructor-name {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.json-formatter-toggler {
|
||||
line-height: 1rem;
|
||||
font-size: 1rem;
|
||||
vertical-align: baseline;
|
||||
opacity: $toggler-opacity;
|
||||
cursor: pointer;
|
||||
padding-right: 0.3rem;
|
||||
|
||||
&:after {
|
||||
display: inline-block;
|
||||
transition: none;
|
||||
content: '+';
|
||||
}
|
||||
}
|
||||
|
||||
// Inline preview on hover (optional)
|
||||
> a > .json-formatter-preview-text {
|
||||
opacity: 0;
|
||||
transition: opacity 0.15s ease-in;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
&:hover > a > .json-formatter-preview-text {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
// Open state
|
||||
&.json-formatter-open {
|
||||
> .json-formatter-toggler-link .json-formatter-toggler:after {
|
||||
transform: none;
|
||||
content: '-';
|
||||
}
|
||||
> .json-formatter-children:after {
|
||||
display: inline-block;
|
||||
}
|
||||
> a > .json-formatter-preview-text {
|
||||
display: none;
|
||||
}
|
||||
&.json-formatter-empty:after {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.json-formatter-nomad.json-formatter-row {
|
||||
@include theme(
|
||||
$grey,
|
||||
$nomad-green,
|
||||
$packer-blue,
|
||||
$consul-pink,
|
||||
$terraform-purple,
|
||||
$terraform-purple-dark,
|
||||
$white,
|
||||
0.6,
|
||||
$black,
|
||||
$grey-dark,
|
||||
$white,
|
||||
$blue
|
||||
);
|
||||
}
|
|
@ -11,6 +11,8 @@ $warning-invert: $white;
|
|||
$danger: $red;
|
||||
$info: $blue;
|
||||
$dark: #234;
|
||||
$dark-2: darken($dark, 5%);
|
||||
$dark-3: darken($dark, 10%);
|
||||
|
||||
$radius: 2px;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ $consul-pink-dark: #c62a71;
|
|||
$packer-blue: #1daeff;
|
||||
$packer-blue-dark: #1d94dd;
|
||||
|
||||
$terraform-purple-bright: #807dea;
|
||||
$terraform-purple: #5c4ee5;
|
||||
$terraform-purple-dark: #4040b2;
|
||||
|
||||
|
@ -13,3 +14,5 @@ $vagrant-blue-dark: #104eb2;
|
|||
$nomad-green: #25ba81;
|
||||
$nomad-green-dark: #1d9467;
|
||||
$nomad-green-darker: #16704d;
|
||||
|
||||
$serf-red: #dd4e58;
|
||||
|
|
|
@ -13,19 +13,3 @@
|
|||
</div>
|
||||
</div>
|
||||
{{/freestyle-usage}}
|
||||
|
||||
{{#freestyle-collection defaultKey=0 as |collection|}}
|
||||
{{#each (array 0 1 2 3 4 5) as |depth|}}
|
||||
{{#collection.variant key=depth}}
|
||||
{{#freestyle-usage
|
||||
(concat "json-viewer-truncated-" depth)
|
||||
title=(concat "JSON Viewer Expand Depth " depth)}}
|
||||
<div class="boxed-section">
|
||||
<div class="boxed-section-body is-dark">
|
||||
{{json-viewer json=jsonLarge expandDepth=depth}}
|
||||
</div>
|
||||
</div>
|
||||
{{/freestyle-usage}}
|
||||
{{/collection.variant}}
|
||||
{{/each}}
|
||||
{{/freestyle-collection}}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
{{ivy-codemirror
|
||||
value=jsonStr
|
||||
options=(hash
|
||||
mode="javascript"
|
||||
theme="hashi-read-only"
|
||||
tabSize=2
|
||||
lineNumbers=true
|
||||
readOnly=true
|
||||
)}}
|
|
@ -1,7 +1,7 @@
|
|||
{{partial "jobs/job/subnav"}}
|
||||
<section class="section">
|
||||
<div class="boxed-section">
|
||||
<div class="boxed-section-body is-dark">
|
||||
<div class="boxed-section-body is-full-bleed">
|
||||
{{json-viewer data-test-definition-view json=model.definition}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -12,6 +12,10 @@ module.exports = function(defaults) {
|
|||
svg: {
|
||||
paths: ['public/images/icons'],
|
||||
},
|
||||
codemirror: {
|
||||
themes: ['solarized'],
|
||||
modes: ['javascript'],
|
||||
},
|
||||
funnel: {
|
||||
enabled: isProd,
|
||||
exclude: [
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
"flat": "^4.0.0",
|
||||
"fuse.js": "~3.2.0",
|
||||
"husky": "^0.14.3",
|
||||
"json-formatter-js": "^2.2.0",
|
||||
"ivy-codemirror": "^2.1.0",
|
||||
"lint-staged": "^6.0.0",
|
||||
"loader.js": "^4.2.3",
|
||||
"lodash.intersection": "^4.4.0",
|
||||
|
|
16
ui/yarn.lock
16
ui/yarn.lock
|
@ -2256,6 +2256,10 @@ code-point-at@^1.0.0:
|
|||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
|
||||
codemirror@~5.15.0:
|
||||
version "5.15.2"
|
||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.15.2.tgz#58b3dc732c6d10d7aae806f4c7cdd56a9b87fe8f"
|
||||
|
||||
coffee-script@^1.10.0:
|
||||
version "1.12.7"
|
||||
resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.12.7.tgz#c05dae0cb79591d05b3070a8433a98c9a89ccc53"
|
||||
|
@ -5374,6 +5378,14 @@ istextorbinary@2.1.0:
|
|||
editions "^1.1.1"
|
||||
textextensions "1 || 2"
|
||||
|
||||
ivy-codemirror@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ivy-codemirror/-/ivy-codemirror-2.1.0.tgz#c06f1606c375610bf62b007a21a9e63f5854175e"
|
||||
dependencies:
|
||||
codemirror "~5.15.0"
|
||||
ember-cli-babel "^6.0.0"
|
||||
ember-cli-node-assets "^0.2.2"
|
||||
|
||||
jest-get-type@^21.2.0:
|
||||
version "21.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.2.0.tgz#f6376ab9db4b60d81e39f30749c6c466f40d4a23"
|
||||
|
@ -5457,10 +5469,6 @@ jsmin@1.x:
|
|||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/jsmin/-/jsmin-1.0.1.tgz#e7bd0dcd6496c3bf4863235bf461a3d98aa3b98c"
|
||||
|
||||
json-formatter-js@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/json-formatter-js/-/json-formatter-js-2.2.0.tgz#1ed987223ef2f1d945304597faae78b580a8212b"
|
||||
|
||||
json-parse-better-errors@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
|
||||
|
|
Loading…
Reference in New Issue