diff --git a/ui-v2/app/components/confirmation-alert/action/index.hbs b/ui-v2/app/components/confirmation-alert/action/index.hbs new file mode 100644 index 0000000000..bb711add68 --- /dev/null +++ b/ui-v2/app/components/confirmation-alert/action/index.hbs @@ -0,0 +1,3 @@ +
  • + +
  • diff --git a/ui-v2/app/components/confirmation-alert/action/index.js b/ui-v2/app/components/confirmation-alert/action/index.js new file mode 100644 index 0000000000..4798652642 --- /dev/null +++ b/ui-v2/app/components/confirmation-alert/action/index.js @@ -0,0 +1,5 @@ +import Component from '@ember/component'; + +export default Component.extend({ + tagName: '', +}); diff --git a/ui-v2/app/components/confirmation-alert/index.hbs b/ui-v2/app/components/confirmation-alert/index.hbs new file mode 100644 index 0000000000..24e553ae5d --- /dev/null +++ b/ui-v2/app/components/confirmation-alert/index.hbs @@ -0,0 +1,22 @@ +{{yield}} +
    +
    +
    + {{yield}} +
    + {{yield}} +
    + +
    \ No newline at end of file diff --git a/ui-v2/app/components/confirmation-alert/index.js b/ui-v2/app/components/confirmation-alert/index.js new file mode 100644 index 0000000000..4798652642 --- /dev/null +++ b/ui-v2/app/components/confirmation-alert/index.js @@ -0,0 +1,5 @@ +import Component from '@ember/component'; + +export default Component.extend({ + tagName: '', +}); diff --git a/ui-v2/app/components/consul-policy-list/README.mdx b/ui-v2/app/components/consul-policy-list/README.mdx new file mode 100644 index 0000000000..185b91a4c9 --- /dev/null +++ b/ui-v2/app/components/consul-policy-list/README.mdx @@ -0,0 +1,24 @@ +## ConsulPolicyList + +``` + +``` + +A presentational component for rendering Consul ACL policies + +### Arguments + +| Argument/Attribute | Type | Default | Description | +| --- | --- | --- | --- | +| `items` | `array` | | An array of ACL policies | +| `ondelete` | `function` | | An action to execute when the `Delete` action is clicked | + +### See + +- [Component Source Code](./index.js) +- [TemplateSource Code](./index.hbs) + +--- diff --git a/ui-v2/app/components/consul-policy-list/index.hbs b/ui-v2/app/components/consul-policy-list/index.hbs new file mode 100644 index 0000000000..cf5985f11d --- /dev/null +++ b/ui-v2/app/components/consul-policy-list/index.hbs @@ -0,0 +1,67 @@ +{{#if (gt items.length 0)}} + + +{{#if (eq (policy/typeof item) 'policy-management')}} +
    +
    + + Global Management Policy + +
    +
    +{{/if}} + {{item.Name}} +
    + +
    +
    + Datacenters +
    +
    + {{join ', ' (policy/datacenters item)}} +
    +
    +
    +
    Description
    +
    + {{item.Description}} +
    +
    +
    + + + + +{{#if (eq (policy/typeof item) 'policy-management')}} + View +{{else}} + Edit +{{/if}} + + +{{#if (not-eq (policy/typeof item) 'policy-management')}} + + + Delete + + + + + Confirm delete + + +

    + Are you sure you want to delete this policy? +

    +
    + + Delete + +
    +
    +
    +{{/if}} +
    +
    +
    +{{/if}} \ No newline at end of file diff --git a/ui-v2/app/components/consul-policy-list/index.js b/ui-v2/app/components/consul-policy-list/index.js new file mode 100644 index 0000000000..4798652642 --- /dev/null +++ b/ui-v2/app/components/consul-policy-list/index.js @@ -0,0 +1,5 @@ +import Component from '@ember/component'; + +export default Component.extend({ + tagName: '', +}); diff --git a/ui-v2/app/components/consul-policy-list/pageobject.js b/ui-v2/app/components/consul-policy-list/pageobject.js new file mode 100644 index 0000000000..529c9d5014 --- /dev/null +++ b/ui-v2/app/components/consul-policy-list/pageobject.js @@ -0,0 +1,8 @@ +export default (collection, clickable, attribute, text, actions) => () => { + return collection('.consul-policy-list li:not(:first-child)', { + name: attribute('data-test-policy', '[data-test-policy]'), + description: text('[data-test-description]'), + policy: clickable('a'), + ...actions(['edit', 'delete']), + }); +}; diff --git a/ui-v2/app/components/consul-role-list/README.mdx b/ui-v2/app/components/consul-role-list/README.mdx new file mode 100644 index 0000000000..f7c4edc58b --- /dev/null +++ b/ui-v2/app/components/consul-role-list/README.mdx @@ -0,0 +1,24 @@ +## ConsulRoleList + +``` + +``` + +A presentational component for rendering Consul ACL roles + +### Arguments + +| Argument/Attribute | Type | Default | Description | +| --- | --- | --- | --- | +| `items` | `array` | | An array of ACL roles | +| `ondelete` | `function` | | An action to execute when the `Delete` action is clicked | + +### See + +- [Component Source Code](./index.js) +- [TemplateSource Code](./index.hbs) + +--- diff --git a/ui-v2/app/components/consul-role-list/index.hbs b/ui-v2/app/components/consul-role-list/index.hbs new file mode 100644 index 0000000000..ac3d734c87 --- /dev/null +++ b/ui-v2/app/components/consul-role-list/index.hbs @@ -0,0 +1,45 @@ +{{#if (gt items.length 0)}} + + + {{item.Name}} + + + +
    +
    Description
    +
    + {{item.Description}} +
    +
    +
    + + + + + Edit + + + + + Delete + + + + + Confirm delete + + +

    + Are you sure you want to delete this role? +

    +
    + + Delete + +
    +
    +
    +
    +
    +
    +{{/if}} \ No newline at end of file diff --git a/ui-v2/app/components/consul-role-list/index.js b/ui-v2/app/components/consul-role-list/index.js new file mode 100644 index 0000000000..4798652642 --- /dev/null +++ b/ui-v2/app/components/consul-role-list/index.js @@ -0,0 +1,5 @@ +import Component from '@ember/component'; + +export default Component.extend({ + tagName: '', +}); diff --git a/ui-v2/app/components/consul-role-list/pageobject.js b/ui-v2/app/components/consul-role-list/pageobject.js new file mode 100644 index 0000000000..9650a8f98e --- /dev/null +++ b/ui-v2/app/components/consul-role-list/pageobject.js @@ -0,0 +1,9 @@ +export default (collection, clickable, attribute, text, actions) => () => { + return collection('.consul-role-list li:not(:first-child)', { + name: attribute('data-test-role', '[data-test-role]'), + description: text('[data-test-description]'), + policy: text('[data-test-policy].policy', { multiple: true }), + serviceIdentity: text('[data-test-policy].policy-service-identity', { multiple: true }), + ...actions(['edit', 'delete']), + }); +}; diff --git a/ui-v2/app/components/consul-token-list/index.hbs b/ui-v2/app/components/consul-token-list/index.hbs index a82b84237c..cdf2509ba8 100644 --- a/ui-v2/app/components/consul-token-list/index.hbs +++ b/ui-v2/app/components/consul-token-list/index.hbs @@ -1,10 +1,10 @@ {{#if (gt items.length 0)}} - + {{#if (eq item.AccessorID token.AccessorID)}}
    - + Your token
    @@ -19,50 +19,7 @@ {{if item.Local 'local' 'global' }}
    -{{#let (policy/group item.Policies) as |policies|}} - {{#let (get policies 'management') as |management|}} - {{#if (gt management.length 0)}} -
    -
    - Management -
    -
    - {{#each (get policies 'management') as |item|}} - {{item.Name}} - {{/each}} -
    -
    - {{/if}} - {{/let}} - {{#let (get policies 'identities') as |identities|}} - {{#if (gt identities.length 0)}} -
    -
    Identities
    -
    - {{#each identities as |item|}} - {{if (eq item.template 'service-identity') 'Service' 'Node'}} Identity: {{item.Name}} - {{/each}} -
    -
    - {{/if}} - {{/let}} - {{#let (append (get policies 'policies') item.Roles) as |policies|}} - {{#if (gt policies.length 0)}} -
    -
    Rules
    -
    - {{#if (token/is-legacy item) }} - Legacy tokens have embedded rules. - {{ else }} - {{#each policies as |item|}} - {{item.Name}} - {{/each}} - {{/if}} -
    -
    - {{/if}} - {{/let}} -{{/let}} +
    Description
    @@ -70,98 +27,86 @@
    - -
    - - - More - - -
  • - Edit -
  • -{{#if (not (token/is-legacy item))}} -
  • - -
  • -{{/if}} -{{#if (eq item.AccessorID token.AccessorID) }} -
  • - -
    -
    -
    -
    - Confirm logout -
    -

    - Are you sure you want to stop using this ACL token? This will log you out. -

    -
    -
      -
    • - -
    • -
    • - -
    • -
    -
    -
    -
  • -{{else}} -
  • - -
    -
    -
    -
    - Confirm use -
    -

    - Are you sure you want to use this ACL token? -

    -
    -
      -
    • - -
    • -
    • - -
    • -
    -
    -
    -
  • -{{/if}} -{{#unless (or (token/is-anonymous item) (eq item.AccessorID token.AccessorID)) }} -
  • - -
    -
    -
    -
    - Confirm Delete -
    -

    - Are you sure you want to delete this token? -

    -
    -
      -
    • - -
    • -
    • - -
    • -
    -
    -
    -
  • -{{/unless}} -
    -
    -
    + + + + + Edit + + + {{#if (not (token/is-legacy item))}} + + + Duplicate + + + {{/if}} + {{#if (eq item.AccessorID token.AccessorID)}} + + + Logout + + + + + Confirm logout + + +

    + Are you sure you want to stop using this ACL token? This will log you out. +

    +
    + + Logout + +
    +
    +
    + {{else}} + + + Use + + + + + Confirm use + + +

    + Are you sure you want to use this ACL token? +

    +
    + + Use + +
    +
    +
    + {{/if}} + {{#if (not (or (token/is-anonymous item) (eq item.AccessorID token.AccessorID)))}} + + + Delete + + + + + Confirm delete + + +

    + Are you sure you want to delete this token? +

    +
    + + Delete + +
    +
    +
    + {{/if}} +
    {{/if}} \ No newline at end of file diff --git a/ui-v2/app/components/consul-token-list/pageobject.js b/ui-v2/app/components/consul-token-list/pageobject.js index f03055cfc0..ba09453859 100644 --- a/ui-v2/app/components/consul-token-list/pageobject.js +++ b/ui-v2/app/components/consul-token-list/pageobject.js @@ -1,4 +1,4 @@ -export default (collection, clickable, attribute, text, deletable) => () => { +export default (collection, clickable, attribute, text, actions) => () => { return collection('.consul-token-list li:not(:first-child)', { id: attribute('data-test-token', '[data-test-token]'), description: text('[data-test-description]'), @@ -6,10 +6,6 @@ export default (collection, clickable, attribute, text, deletable) => () => { role: text('[data-test-policy].role', { multiple: true }), serviceIdentity: text('[data-test-policy].policy-service-identity', { multiple: true }), token: clickable('a'), - actions: clickable('label'), - use: clickable('[data-test-use]'), - confirmUse: clickable('[data-test-confirm-use]'), - clone: clickable('[data-test-clone]'), - ...deletable(), + ...actions(['edit', 'delete', 'use', 'logout', 'clone']), }); }; diff --git a/ui-v2/app/components/consul-token-ruleset-list/README.mdx b/ui-v2/app/components/consul-token-ruleset-list/README.mdx new file mode 100644 index 0000000000..43da3ed93e --- /dev/null +++ b/ui-v2/app/components/consul-token-ruleset-list/README.mdx @@ -0,0 +1,22 @@ +## ConsulTokenRulesetList + +``` + +``` + +A presentational component for rendering Consul ACL token 'rulesets'. Rulesets are the various 'rule-type' things that belong to a token such as policies, identities and roles, and in the case of legacy tokens, the old style string based rules property. + +### Arguments + +| Argument/Attribute | Type | Default | Description | +| --- | --- | --- | --- | +| `item` | `array` | | An ACL token | + +### See + +- [Component Source Code](./index.js) +- [TemplateSource Code](./index.hbs) + +--- diff --git a/ui-v2/app/components/consul-token-ruleset-list/index.hbs b/ui-v2/app/components/consul-token-ruleset-list/index.hbs new file mode 100644 index 0000000000..036276b2fb --- /dev/null +++ b/ui-v2/app/components/consul-token-ruleset-list/index.hbs @@ -0,0 +1,49 @@ +{{#let (policy/group item.Policies) as |policies|}} + {{#let (get policies 'management') as |management|}} + {{#if (gt management.length 0)}} +
    +
    + Management +
    +
    + {{#each (get policies 'management') as |item|}} + {{item.Name}} + {{/each}} +
    +
    + {{/if}} + {{/let}} + {{#let (get policies 'identities') as |identities|}} + {{#if (gt identities.length 0)}} +
    +
    Identities
    +
    + {{#each identities as |item|}} + {{item.Name}} + {{/each}} +
    +
    + {{/if}} + {{/let}} + {{#if (token/is-legacy item) }} +
    +
    Rules
    +
    + Legacy tokens have embedded rules. +
    +
    + {{else}} + {{#let (append (get policies 'policies') (or item.Roles (array))) as |policies|}} + {{#if (gt policies.length 0)}} +
    +
    Rules
    +
    + {{#each policies as |item|}} + {{item.Name}} + {{/each}} +
    +
    + {{/if}} + {{/let}} + {{/if}} +{{/let}} diff --git a/ui-v2/app/components/consul-token-ruleset-list/index.js b/ui-v2/app/components/consul-token-ruleset-list/index.js new file mode 100644 index 0000000000..4798652642 --- /dev/null +++ b/ui-v2/app/components/consul-token-ruleset-list/index.js @@ -0,0 +1,5 @@ +import Component from '@ember/component'; + +export default Component.extend({ + tagName: '', +}); diff --git a/ui-v2/app/components/list-collection/index.hbs b/ui-v2/app/components/list-collection/index.hbs index 9a759031f7..d83b07604b 100644 --- a/ui-v2/app/components/list-collection/index.hbs +++ b/ui-v2/app/components/list-collection/index.hbs @@ -11,9 +11,17 @@
  • {{~#each _cells as |cell|~}}
  • -
    {{yield cell.item cell.index checked (action "change")}}
    -
    {{yield cell.item cell.index checked (action "change")}}
    -
    {{yield cell.item cell.index checked (action "change")}}
    +
    {{yield cell.item cell.index}}
    +
    {{yield cell.item cell.index}}
    + +
    + {{yield cell.item cell.index}} +
    +
  • {{~/each~}} \ No newline at end of file diff --git a/ui-v2/app/components/menu-panel/index.hbs b/ui-v2/app/components/menu-panel/index.hbs index c0188e052d..a07a628660 100644 --- a/ui-v2/app/components/menu-panel/index.hbs +++ b/ui-v2/app/components/menu-panel/index.hbs @@ -1,15 +1,21 @@ {{yield}} +{{#let (hash + change=(action "change") +) as |api|}} \ No newline at end of file + +{{/let}} \ No newline at end of file diff --git a/ui-v2/app/components/menu-panel/index.js b/ui-v2/app/components/menu-panel/index.js index 3d0b05e3bf..01c78ed689 100644 --- a/ui-v2/app/components/menu-panel/index.js +++ b/ui-v2/app/components/menu-panel/index.js @@ -1,7 +1,26 @@ import Component from '@ember/component'; +import { inject as service } from '@ember/service'; import Slotted from 'block-slots'; export default Component.extend(Slotted, { tagName: '', + dom: service('dom'), + actions: { + change: function(e) { + const id = e.target.getAttribute('id'); + const $trigger = this.dom.element(`[for='${id}']`); + const $panel = this.dom.element('[role=menu]', $trigger.parentElement); + const $menuPanel = this.dom.closest('.menu-panel', $panel); + if (e.target.checked) { + $panel.style.display = 'block'; + const height = $panel.offsetHeight + 2; + $menuPanel.style.maxHeight = $menuPanel.style.minHeight = `${height}px`; + } else { + $panel.style.display = null; + $menuPanel.style.maxHeight = null; + $menuPanel.style.minHeight = '0'; + } + }, + }, }); diff --git a/ui-v2/app/components/more-popover-menu/action/index.hbs b/ui-v2/app/components/more-popover-menu/action/index.hbs new file mode 100644 index 0000000000..c56b2ee2f0 --- /dev/null +++ b/ui-v2/app/components/more-popover-menu/action/index.hbs @@ -0,0 +1,28 @@ +{{yield}} +
  • +{{#if hasConfirmation}} + +
    + {{yield}} +
    +{{else if href}} + + + {{yield}} + + +{{else}} + +{{/if}} +
  • diff --git a/ui-v2/app/components/more-popover-menu/action/index.js b/ui-v2/app/components/more-popover-menu/action/index.js new file mode 100644 index 0000000000..e98665c1a0 --- /dev/null +++ b/ui-v2/app/components/more-popover-menu/action/index.js @@ -0,0 +1,26 @@ +import Component from '@ember/component'; +import { inject as service } from '@ember/service'; +import { set } from '@ember/object'; + +import Slotted from 'block-slots'; + +export default Component.extend(Slotted, { + tagName: '', + dom: service('dom'), + init: function() { + this._super(...arguments); + this.guid = this.dom.guid(this); + }, + didInsertElement: function() { + this._super(...arguments); + this.menu.addSubmenu(this.guid); + }, + didDestroyElement: function() { + this._super(...arguments); + this.menu.removeSubmenu(this.guid); + }, + willRender: function() { + this._super(...arguments); + set(this, 'hasConfirmation', this._isRegistered('confirmation')); + }, +}); diff --git a/ui-v2/app/components/more-popover-menu/index.hbs b/ui-v2/app/components/more-popover-menu/index.hbs new file mode 100644 index 0000000000..4ff23e8858 --- /dev/null +++ b/ui-v2/app/components/more-popover-menu/index.hbs @@ -0,0 +1,15 @@ +
    + + + More + + + {{yield (component 'more-popover-menu/action' menu=(hash + addSubmenu=api.addSubmenu + removeSubmenu=api.removeSubmenu + confirm=confirm + keypressClick=keypressClick + ))}} + + +
    diff --git a/ui-v2/app/components/more-popover-menu/index.js b/ui-v2/app/components/more-popover-menu/index.js new file mode 100644 index 0000000000..4798652642 --- /dev/null +++ b/ui-v2/app/components/more-popover-menu/index.js @@ -0,0 +1,5 @@ +import Component from '@ember/component'; + +export default Component.extend({ + tagName: '', +}); diff --git a/ui-v2/app/components/more-popover-menu/pageobject.js b/ui-v2/app/components/more-popover-menu/pageobject.js new file mode 100644 index 0000000000..2198b2a753 --- /dev/null +++ b/ui-v2/app/components/more-popover-menu/pageobject.js @@ -0,0 +1,17 @@ +export default (clickable, confirmation) => (actions, scope) => { + return actions.reduce( + (prev, item) => { + const itemScope = `[data-test-${item}-action]`; + return { + ...prev, + [item]: clickable(`${itemScope} [role='menuitem']`), + [`confirm${item.charAt(0).toUpperCase()}${item.substr(1)}`]: clickable( + `${itemScope} [role='menu'] button` + ), + }; + }, + { + actions: clickable('label'), + } + ); +}; diff --git a/ui-v2/app/components/popover-menu/index.hbs b/ui-v2/app/components/popover-menu/index.hbs index c1442e8564..080ae2f331 100644 --- a/ui-v2/app/components/popover-menu/index.hbs +++ b/ui-v2/app/components/popover-menu/index.hbs @@ -1,4 +1,4 @@ -{{yield (concat 'popover-menu-' guid)}} +{{yield}} - + - {{#each submenus as |sub|}} - - {{/each}} + {{#each submenus as |sub|}} + + {{/each}} {{#if hasHeader}} - {{#yield-slot name="header"}}{{yield}}{{else}}{{/yield-slot}} + {{yield (hash + addSubmenu=(action 'addSubmenu') + removeSubmenu=(action 'removeSubmenu') + )}} + {{#yield-slot name="header"}}{{else}}{{/yield-slot}} {{/if}} - {{yield}} + {{yield (hash + addSubmenu=(action 'addSubmenu') + removeSubmenu=(action 'removeSubmenu') + )}} diff --git a/ui-v2/app/components/popover-menu/index.js b/ui-v2/app/components/popover-menu/index.js index 9f68520ed0..2229e9f4ee 100644 --- a/ui-v2/app/components/popover-menu/index.js +++ b/ui-v2/app/components/popover-menu/index.js @@ -16,11 +16,22 @@ export default Component.extend(Slotted, { init: function() { this._super(...arguments); this.guid = this.dom.guid(this); + this.submenus = []; }, willRender: function() { set(this, 'hasHeader', this._isRegistered('header')); }, actions: { + addSubmenu: function(name) { + set(this, 'submenus', this.submenus.concat(name)); + }, + removeSubmenu: function(name) { + const pos = this.submenus.indexOf(name); + if (pos !== -1) { + this.submenus.splice(pos, 1); + set(this, 'submenus', this.submenus); + } + }, change: function(e) { if (!e.target.checked) { [...this.dom.elements(`[id^=popover-menu-${this.guid}]`)].forEach(function($item) { diff --git a/ui-v2/app/helpers/policy/typeof.js b/ui-v2/app/helpers/policy/typeof.js index ec4b5e441a..87c0591e3d 100644 --- a/ui-v2/app/helpers/policy/typeof.js +++ b/ui-v2/app/helpers/policy/typeof.js @@ -3,13 +3,16 @@ import { get } from '@ember/object'; const MANAGEMENT_ID = '00000000-0000-0000-0000-000000000001'; export function typeOf(params, hash) { const item = params[0]; + const template = get(item, 'template'); switch (true) { + case typeof template === 'undefined': + return 'role'; + case template === 'service-identity': + return 'policy-service-identity'; + case template === 'node-identity': + return 'policy-node-identity'; case get(item, 'ID') === MANAGEMENT_ID: return 'policy-management'; - case typeof get(item, 'template') === 'undefined': - return 'role'; - case get(item, 'template') !== '': - return 'policy-service-identity'; default: return 'policy'; } diff --git a/ui-v2/app/styles/base/components/confirmation-alert/skin.scss b/ui-v2/app/styles/base/components/confirmation-alert/skin.scss index 6f6c0d933d..0684daed5e 100644 --- a/ui-v2/app/styles/base/components/confirmation-alert/skin.scss +++ b/ui-v2/app/styles/base/components/confirmation-alert/skin.scss @@ -6,6 +6,7 @@ background-color: $yellow-050; border-top-left-radius: $decor-radius-200; border-top-right-radius: $decor-radius-200; + cursor: default; } %confirmation-alert > ul { list-style: none; diff --git a/ui-v2/app/styles/base/components/menu-panel/layout.scss b/ui-v2/app/styles/base/components/menu-panel/layout.scss index 7614f3aeb0..9dcf2fa6ba 100644 --- a/ui-v2/app/styles/base/components/menu-panel/layout.scss +++ b/ui-v2/app/styles/base/components/menu-panel/layout.scss @@ -4,15 +4,16 @@ %menu-panel [type='checkbox'] { display: none; } -%menu-panel [type='checkbox'] ~ * { - transition: transform 150ms, min-height 150ms, max-height 150ms; +%menu-panel { + overflow: hidden; + transition: min-height 150ms, max-height 150ms; min-height: 0; } +%menu-panel [type='checkbox'] ~ * { + transition: transform 150ms; +} %menu-panel [type='checkbox']:checked ~ * { transform: translateX(calc(-100% - 10px)); - /* this needs to autocalculate */ - /* or be hardcoded */ - /* min-height: 143px; */ } %menu-panel [role='menuitem'] { display: flex; @@ -27,7 +28,19 @@ position: absolute; top: 0; left: calc(100% + 10px); + display: none; } +/* TODO: once everything is using ListCollection */ +/* this can go */ +%menu-panel [type='checkbox']:checked ~ * { + /* this needs to autocalculate */ + min-height: 143px; + max-height: 143px; +} +%menu-panel [id$='-']:first-child:checked ~ ul label[for$='-'] + [role='menu'] { + display: block; +} +/**/ %menu-panel dl { padding: 0.9em 1em; } diff --git a/ui-v2/app/styles/base/components/popover-menu/index.scss b/ui-v2/app/styles/base/components/popover-menu/index.scss index f8731956bc..3e513da575 100644 --- a/ui-v2/app/styles/base/components/popover-menu/index.scss +++ b/ui-v2/app/styles/base/components/popover-menu/index.scss @@ -1,18 +1,17 @@ @import './skin'; @import './layout'; -%with-popover-menu > input { +%with-popover-menu > [type='checkbox'] { @extend %popover-menu; } %popover-menu { @extend %display-toggle-siblings; } -%popover-menu + label + div { - @extend %popover-menu-panel; -} %popover-menu + label > * { @extend %toggle-button; } -%more-popover-menu-panel, +%popover-menu + label + div { + @extend %popover-menu-panel; +} %popover-menu-panel { @extend %menu-panel; } diff --git a/ui-v2/app/styles/base/components/popover-menu/layout.scss b/ui-v2/app/styles/base/components/popover-menu/layout.scss index 012d2a8c75..862ca79818 100644 --- a/ui-v2/app/styles/base/components/popover-menu/layout.scss +++ b/ui-v2/app/styles/base/components/popover-menu/layout.scss @@ -1,56 +1,12 @@ %with-popover-menu { position: relative; } -%with-popover-menu > [type='checkbox'] { - @extend %popover-menu; -} -%more-popover-menu { - @extend %display-toggle-siblings; -} -%more-popover-menu + label > * { - @extend %toggle-button; -} -%more-popover-menu-panel { - overflow: hidden; - width: 192px; -} -%more-popover-menu + label + div { - @extend %more-popover-menu-panel; -} -%more-popover-menu-panel:not(.above) { - top: 48px; -} -%more-popover-menu-panel:not(.left) { - right: 10px; -} -%more-popover-menu-panel li [role='menu'] { - display: none; -} -%more-popover-menu-panel [id$='-']:first-child:checked ~ ul label[for$='-'] + [role='menu'] { - display: block; -} -%popover-menu { - @extend %display-toggle-siblings; -} -%popover-menu + label > * { - @extend %toggle-button; -} %popover-menu-panel { - @extend %menu-panel; width: 192px; } -%popover-menu + label + div { - @extend %popover-menu-panel; -} %popover-menu-panel:not(.above) { top: 38px; } %popover-menu-panel:not(.left) { - right: 10px; -} -%popover-menu-panel li [role='menu'] { - display: none; -} -%popover-menu-panel [id$='-']:first-child:checked ~ ul label[for$='-'] + [role='menu'] { - display: block; + right: 5px; } diff --git a/ui-v2/app/styles/base/components/popover-menu/skin.scss b/ui-v2/app/styles/base/components/popover-menu/skin.scss index df9b801f8e..fdda44399f 100644 --- a/ui-v2/app/styles/base/components/popover-menu/skin.scss +++ b/ui-v2/app/styles/base/components/popover-menu/skin.scss @@ -4,13 +4,3 @@ height: 16px; margin-left: 16px; } -%more-popover-menu + label > *::after { - @extend %with-more-horizontal-icon, %as-pseudo; - opacity: 0.7; - width: 16px; - height: 16px; -} -%more-popover-menu + label > * { - font-size: 0; - background-color: $transparent; -} diff --git a/ui-v2/app/styles/components/composite-row.scss b/ui-v2/app/styles/components/composite-row.scss index 0ae43420b5..e60110cacc 100644 --- a/ui-v2/app/styles/components/composite-row.scss +++ b/ui-v2/app/styles/components/composite-row.scss @@ -10,28 +10,23 @@ .consul-gateway-service-list > ul > li:not(:first-child), .consul-service-instance-list > ul > li:not(:first-child), .consul-service-list > ul > li:not(:first-child), -.consul-token-list > ul > li:not(:first-child) { +.consul-token-list > ul > li:not(:first-child), +.consul-policy-list > ul > li:not(:first-child), +.consul-role-list > ul > li:not(:first-child) { @extend %with-composite-row-intent; } /*TODO: This hides the icons-less dt's in the below lists as */ /* they don't have tooltips */ -.consul-token-list > ul > li:not(:first-child) dt { +.consul-token-list > ul > li:not(:first-child) dt, +.consul-policy-list > ul li:not(:first-child) dl:not(.datacenter) dt, +.consul-role-list > ul > li:not(:first-child) dt { display: none; } /* TODO: the service list has a 1px offset */ +.consul-policy-list dl.datacenter dt, .consul-service-list li > div:first-child > dl:first-child dd { margin-top: 1px; } -.proxy-exposed-paths tbody tr { - cursor: default !important; -} -.proxy-exposed-paths tbody tr:hover { - box-shadow: none !important; -} -.proxy-exposed-paths tbody tr .combined-address button:hover { - // In this case we do not need a background on the icon - background-color: $transparent !important; -} .proxy-exposed-paths > ul, .proxy-upstreams > ul { border-top: 1px solid $gray-200; diff --git a/ui-v2/app/styles/components/composite-row/skin.scss b/ui-v2/app/styles/components/composite-row/skin.scss index 59ed63e6f9..45589a5a74 100644 --- a/ui-v2/app/styles/components/composite-row/skin.scss +++ b/ui-v2/app/styles/components/composite-row/skin.scss @@ -33,9 +33,12 @@ margin-right: 3px; } %composite-row-detail .policy-management::before { + margin-right: 3px; +} +%composite-row-detail .policy-management::before, +%composite-row-header .policy-management dd::before { @extend %with-star-fill-mask, %as-pseudo; background-color: var(--brand-600); - margin-right: 3px; } // Health Checks %composite-row-detail li.passing::before, diff --git a/ui-v2/app/styles/components/more-popover-menu.scss b/ui-v2/app/styles/components/more-popover-menu.scss index 7d7fb6f0f6..951c344acb 100644 --- a/ui-v2/app/styles/components/more-popover-menu.scss +++ b/ui-v2/app/styles/components/more-popover-menu.scss @@ -1,18 +1,24 @@ -.more-popover-menu > [type='checkbox'] { +.more-popover-menu { @extend %more-popover-menu; } -%more-popover-menu-panel [type='checkbox']:checked ~ * { - /* this needs to autocalculate */ - min-height: 143px; - max-height: 143px; +%more-popover-menu { + @extend %with-popover-menu; } -%more-popover-menu-panel [id$='logout']:checked ~ * { - /* this needs to autocalculate */ - min-height: 183px; - max-height: 183px; +%more-popover-menu > [type='checkbox'] + label { + @extend %more-popover-menu-trigger; } -%more-popover-menu-panel [id$='delete']:checked ~ ul label[for$='delete'] + [role='menu'], -%more-popover-menu-panel [id$='logout']:checked ~ ul label[for$='logout'] + [role='menu'], -%more-popover-menu-panel [id$='use']:checked ~ ul label[for$='use'] + [role='menu'] { +/* This gives the trigger a slightly larger invisible hit area */ +%more-popover-menu-trigger { + padding: 7px; display: block; } +%more-popover-menu-trigger > * { + font-size: 0; + background-color: $transparent; + padding: 0; +} +%more-popover-menu-trigger > *::after { + @extend %with-more-horizontal-mask, %as-pseudo; + background-color: $gray-900; + margin: 0; +} diff --git a/ui-v2/app/styles/components/pill.scss b/ui-v2/app/styles/components/pill.scss index 4094f5e16c..0d2f09f6d5 100644 --- a/ui-v2/app/styles/components/pill.scss +++ b/ui-v2/app/styles/components/pill.scss @@ -2,44 +2,21 @@ td strong { @extend %pill; margin-right: 3px; } -// For the moment pills with classes are iconed ones -%pill:not([class]) { - @extend %frame-gray-900; -} -%pill[class] { - padding-left: 0; - margin-right: 16px; -} -%pill[class]::before { - @extend %as-pseudo; - margin-right: 3px; -} -%pill.policy::before { - @extend %with-file-fill-icon; - opacity: 0.3; -} -%pill.policy-management::before { - @extend %with-star-icon; -} -%pill.role::before { - @extend %with-user-plain-icon; - opacity: 0.3; -} - -// TODO: These are related to the pill icons, but also to the tables -// All of this icon assigning stuff should probably go in the eventual -// refactored /components/icons.scss file - -span.policy-management a::after { - @extend %with-star-icon, %as-pseudo; - margin-left: 3px; -} span.policy-service-identity, +span.policy-node-identity, .consul-external-source, .consul-kind { @extend %reduced-pill; } -span.policy-service-identity::before { - width: 0; +span.policy-service-identity::before, +span.policy-node-identity::before { + display: inline-block; + width: auto; +} +span.policy-node-identity::before { + content: 'Node Identity: '; +} +span.policy-service-identity::before { + content: 'Service Identity: '; } diff --git a/ui-v2/app/styles/components/table.scss b/ui-v2/app/styles/components/table.scss index 1bc25d71d6..e86da93025 100644 --- a/ui-v2/app/styles/components/table.scss +++ b/ui-v2/app/styles/components/table.scss @@ -1,19 +1,13 @@ %main-content table { @extend %table; } -%table-actions > [type='checkbox'] { +%table-actions { @extend %more-popover-menu; -} -%table-actions .confirmation-alert { - @extend %confirmation-alert; + overflow: visible; } %table-actions > [type='checkbox'] + label { position: absolute; - top: 8px; - right: 15px; -} -%table-actions .menu-panel:not(.above) { - top: 38px !important; + right: 5px; } /*TODO: Rename this to %app-view-brand-icon or similar */ diff --git a/ui-v2/app/templates/dc/acls/policies/-view.hbs b/ui-v2/app/templates/dc/acls/policies/-view.hbs index 19464f922b..bbdfe74222 100644 --- a/ui-v2/app/templates/dc/acls/policies/-view.hbs +++ b/ui-v2/app/templates/dc/acls/policies/-view.hbs @@ -1,5 +1,5 @@

    Management This global-management token is built into Consul's policy system. You can apply this special policy to tokens for full access. This policy is not editable or removeable, but can be ignored by not applying it to any tokens. Learn more in our documentation.

    -
    +
    Name
    {{item.Name}}
    diff --git a/ui-v2/app/templates/dc/acls/policies/index.hbs b/ui-v2/app/templates/dc/acls/policies/index.hbs index bfc2284ee2..c1baae4103 100644 --- a/ui-v2/app/templates/dc/acls/policies/index.hbs +++ b/ui-v2/app/templates/dc/acls/policies/index.hbs @@ -40,66 +40,10 @@ {{/if}} - - - Name - Datacenters - Description - - - - {{item.Name}} - - - {{join ', ' (policy/datacenters item)}} - - -

    {{item.Description}}

    - -
    - - - - More - - -{{#if (eq (policy/typeof item) 'policy-management')}} -
  • - View -
  • -{{else}} - -
  • - Edit -
  • -
  • - -
    -
    -
    -
    - Confirm Delete -
    -

    - Are you sure you want to delete this policy? -

    -
    -
      -
    • - -
    • -
    • - -
    • -
    -
    -
    -
  • -{{/if}} -
    -
    -
    -
    +
    diff --git a/ui-v2/app/templates/dc/acls/roles/index.hbs b/ui-v2/app/templates/dc/acls/roles/index.hbs index 2cab993c32..9fe9de7612 100644 --- a/ui-v2/app/templates/dc/acls/roles/index.hbs +++ b/ui-v2/app/templates/dc/acls/roles/index.hbs @@ -40,61 +40,10 @@ {{/if}} - - - Name - Description - Policies - - - - {{item.Name}} - - -

    {{item.Description}}

    - - - {{#each item.Policies as |item|}} - {{item.Name}} - {{/each}} - -
    - - - - More - - -
  • - Edit -
  • -
  • - -
    -
    -
    -
    - Confirm Delete -
    -

    - Are you sure you want to delete this role? -

    -
    -
      -
    • - -
    • -
    • - -
    • -
    -
    -
    -
  • -
    -
    -
    -
    +
    diff --git a/ui-v2/tests/acceptance/dc/acls/tokens/index.feature b/ui-v2/tests/acceptance/dc/acls/tokens/index.feature index 16377e4535..5645f9c473 100644 --- a/ui-v2/tests/acceptance/dc/acls/tokens/index.feature +++ b/ui-v2/tests/acceptance/dc/acls/tokens/index.feature @@ -77,7 +77,7 @@ Feature: dc / acls / tokens / index: ACL Token List s: Si-Search --- And I see 1 token model - And I see 1 token model with the serviceIdentity "Service Identity: Si-Search" + And I see 1 token model with the serviceIdentity "Si-Search" Scenario: I see the legacy message if I have one legacy token Given 1 datacenter model with the value "dc-1" And 3 token models from yaml diff --git a/ui-v2/tests/pages.js b/ui-v2/tests/pages.js index 4d56644e85..33bd491537 100644 --- a/ui-v2/tests/pages.js +++ b/ui-v2/tests/pages.js @@ -33,8 +33,13 @@ import policyFormFactory from 'consul-ui/components/policy-form/pageobject'; import policySelectorFactory from 'consul-ui/components/policy-selector/pageobject'; import roleFormFactory from 'consul-ui/components/role-form/pageobject'; import roleSelectorFactory from 'consul-ui/components/role-selector/pageobject'; + +import morePopoverMenuFactory from 'consul-ui/components/more-popover-menu/pageobject'; + import tokenListFactory from 'consul-ui/components/token-list/pageobject'; import consulTokenListFactory from 'consul-ui/components/consul-token-list/pageobject'; +import consulRoleListFactory from 'consul-ui/components/consul-role-list/pageobject'; +import consulPolicyListFactory from 'consul-ui/components/consul-policy-list/pageobject'; import consulIntentionListFactory from 'consul-ui/components/consul-intention-list/pageobject'; // pages @@ -86,8 +91,31 @@ const policyForm = policyFormFactory(submitable, cancelable, radiogroup, text); const policySelector = policySelectorFactory(clickable, deletable, collection, alias, policyForm); const roleForm = roleFormFactory(submitable, cancelable, policySelector); const roleSelector = roleSelectorFactory(clickable, deletable, collection, alias, roleForm); + +const morePopoverMenu = morePopoverMenuFactory(clickable); + const consulIntentionList = consulIntentionListFactory(collection, clickable, attribute, deletable); -const consulTokenList = consulTokenListFactory(collection, clickable, attribute, text, deletable); +const consulTokenList = consulTokenListFactory( + collection, + clickable, + attribute, + text, + morePopoverMenu +); +const consulRoleList = consulRoleListFactory( + collection, + clickable, + attribute, + text, + morePopoverMenu +); +const consulPolicyList = consulPolicyListFactory( + collection, + clickable, + attribute, + text, + morePopoverMenu +); const page = pageFactory(clickable, attribute, is, authForm); @@ -115,22 +143,9 @@ export default { kv: create(kv(visitable, attribute, submitable, deletable, cancelable, clickable)), acls: create(acls(visitable, deletable, creatable, clickable, attribute, collection, aclFilter)), acl: create(acl(visitable, submitable, deletable, cancelable, clickable)), - policies: create( - policies( - visitable, - deletable, - creatable, - clickable, - attribute, - collection, - text, - freetextFilter - ) - ), + policies: create(policies(visitable, creatable, consulPolicyList, freetextFilter)), policy: create(policy(visitable, submitable, deletable, cancelable, clickable, tokenList)), - roles: create( - roles(visitable, deletable, creatable, clickable, attribute, collection, text, freetextFilter) - ), + roles: create(roles(visitable, creatable, consulRoleList, freetextFilter)), // TODO: This needs a policyList role: create(role(visitable, submitable, deletable, cancelable, policySelector, tokenList)), tokens: create(tokens(visitable, creatable, text, consulTokenList, freetextFilter)), diff --git a/ui-v2/tests/pages/dc/acls/policies/index.js b/ui-v2/tests/pages/dc/acls/policies/index.js index 3bf96bf1a4..7b196ba345 100644 --- a/ui-v2/tests/pages/dc/acls/policies/index.js +++ b/ui-v2/tests/pages/dc/acls/policies/index.js @@ -1,24 +1,7 @@ -export default function( - visitable, - deletable, - creatable, - clickable, - attribute, - collection, - text, - filter -) { +export default function(visitable, creatable, policies, filter) { return creatable({ visit: visitable('/:dc/acls/policies'), - policies: collection( - '[data-test-tabular-row]', - deletable({ - name: attribute('data-test-policy', '[data-test-policy]'), - description: text('[data-test-description]'), - policy: clickable('a'), - actions: clickable('label'), - }) - ), + policies: policies(), filter: filter(), }); } diff --git a/ui-v2/tests/pages/dc/acls/roles/index.js b/ui-v2/tests/pages/dc/acls/roles/index.js index 35b6659929..b226f708a6 100644 --- a/ui-v2/tests/pages/dc/acls/roles/index.js +++ b/ui-v2/tests/pages/dc/acls/roles/index.js @@ -1,25 +1,8 @@ -export default function( - visitable, - deletable, - creatable, - clickable, - attribute, - collection, - text, - filter -) { - return creatable({ +export default function(visitable, creatable, roles, filter) { + return { visit: visitable('/:dc/acls/roles'), - roles: collection( - '[data-test-tabular-row]', - deletable({ - name: attribute('data-test-role', '[data-test-role]'), - description: text('[data-test-description]'), - policy: text('[data-test-policy].policy', { multiple: true }), - serviceIdentity: text('[data-test-policy].policy-service-identity', { multiple: true }), - actions: clickable('label'), - }) - ), + roles: roles(), filter: filter(), - }); + ...creatable(), + }; }