diff --git a/ui/app/components/json-viewer.js b/ui/app/components/json-viewer.js index 092491917229..95e27c6db84a 100644 --- a/ui/app/components/json-viewer.js +++ b/ui/app/components/json-viewer.js @@ -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()); -} diff --git a/ui/app/styles/components.scss b/ui/app/styles/components.scss index 93bbf906e0cb..3b99ae2aea0b 100644 --- a/ui/app/styles/components.scss +++ b/ui/app/styles/components.scss @@ -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'; diff --git a/ui/app/styles/components/boxed-section.scss b/ui/app/styles/components/boxed-section.scss index 31e205f8d697..b8f84f0a9ad4 100644 --- a/ui/app/styles/components/boxed-section.scss +++ b/ui/app/styles/components/boxed-section.scss @@ -65,7 +65,7 @@ } &.is-dark { - background: darken($dark, 5%); + background: $dark-2; border-color: lighten($dark, 30%); color: $white; } diff --git a/ui/app/styles/components/codemirror.scss b/ui/app/styles/components/codemirror.scss new file mode 100644 index 000000000000..59f4d755b322 --- /dev/null +++ b/ui/app/styles/components/codemirror.scss @@ -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; + } +} diff --git a/ui/app/styles/components/json-viewer.scss b/ui/app/styles/components/json-viewer.scss deleted file mode 100644 index 4c6b1431fcb5..000000000000 --- a/ui/app/styles/components/json-viewer.scss +++ /dev/null @@ -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 - ); -} diff --git a/ui/app/styles/core/variables.scss b/ui/app/styles/core/variables.scss index 63d90c700e01..cee22b48fe4e 100644 --- a/ui/app/styles/core/variables.scss +++ b/ui/app/styles/core/variables.scss @@ -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; diff --git a/ui/app/styles/utils/product-colors.scss b/ui/app/styles/utils/product-colors.scss index bbf4b63aa181..2697f81a2ff2 100644 --- a/ui/app/styles/utils/product-colors.scss +++ b/ui/app/styles/utils/product-colors.scss @@ -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; diff --git a/ui/app/templates/components/freestyle/sg-json-viewer.hbs b/ui/app/templates/components/freestyle/sg-json-viewer.hbs index 88f3b975757c..ee6b3d3d56f5 100644 --- a/ui/app/templates/components/freestyle/sg-json-viewer.hbs +++ b/ui/app/templates/components/freestyle/sg-json-viewer.hbs @@ -13,19 +13,3 @@ {{/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)}} -
-
- {{json-viewer json=jsonLarge expandDepth=depth}} -
-
- {{/freestyle-usage}} - {{/collection.variant}} - {{/each}} -{{/freestyle-collection}} diff --git a/ui/app/templates/components/json-viewer.hbs b/ui/app/templates/components/json-viewer.hbs new file mode 100644 index 000000000000..4406c7e5a662 --- /dev/null +++ b/ui/app/templates/components/json-viewer.hbs @@ -0,0 +1,9 @@ +{{ivy-codemirror + value=jsonStr + options=(hash + mode="javascript" + theme="hashi-read-only" + tabSize=2 + lineNumbers=true + readOnly=true + )}} diff --git a/ui/app/templates/jobs/job/definition.hbs b/ui/app/templates/jobs/job/definition.hbs index 2265ecdbe28c..2e4280af27fa 100644 --- a/ui/app/templates/jobs/job/definition.hbs +++ b/ui/app/templates/jobs/job/definition.hbs @@ -1,7 +1,7 @@ {{partial "jobs/job/subnav"}}
-
+
{{json-viewer data-test-definition-view json=model.definition}}
diff --git a/ui/ember-cli-build.js b/ui/ember-cli-build.js index 121823950fa4..447069309516 100644 --- a/ui/ember-cli-build.js +++ b/ui/ember-cli-build.js @@ -12,6 +12,10 @@ module.exports = function(defaults) { svg: { paths: ['public/images/icons'], }, + codemirror: { + themes: ['solarized'], + modes: ['javascript'], + }, funnel: { enabled: isProd, exclude: [ diff --git a/ui/package.json b/ui/package.json index b8c4f58392f9..b7579331c1b1 100644 --- a/ui/package.json +++ b/ui/package.json @@ -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", diff --git a/ui/yarn.lock b/ui/yarn.lock index ff3b1fc8f67d..5414f4bd4a3c 100644 --- a/ui/yarn.lock +++ b/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"