ui: Adds unique-id helper (#9676)

This commit is contained in:
John Cowen 2021-02-02 10:03:46 +00:00 committed by GitHub
parent d94c3b9342
commit e0ff7080ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 265 additions and 261 deletions

View File

@ -1,274 +1,276 @@
<App {{#let (unique-id) as |guid|}}
class="hashicorp-consul" <App
...attributes class="hashicorp-consul"
> ...attributes
>
<:home-nav> <:home-nav>
<a <a
href={{href-to 'index'}} href={{href-to 'index'}}
><svg width="28" height="27" xmlns="http://www.w3.org/2000/svg"> ><svg width="28" height="27" xmlns="http://www.w3.org/2000/svg">
<title>Consul</title> <title>Consul</title>
<path <path
d="M13.284 16.178a2.876 2.876 0 1 1-.008-5.751 2.876 2.876 0 0 1 .008 5.75zm5.596-1.547a1.333 1.333 0 1 1 0-2.667 1.333 1.333 0 0 1 0 2.667zm4.853 1.249a1.271 1.271 0 1 1 .027-.107c0 .031 0 .067-.027.107zm-.937-3.436a1.333 1.333 0 1 1 .986-1.595c.033.172.033.348 0 .52-.07.53-.465.96-.986 1.075zm4.72 3.29a1.333 1.333 0 1 1-1.076-1.538 1.333 1.333 0 0 1 1.116 1.417.342.342 0 0 0-.027.12h-.013zm-1.08-3.33a1.333 1.333 0 1 1 1.088-1.524c.014.114.014.229 0 .342a1.333 1.333 0 0 1-1.102 1.182h.014zm-.925 7.925a1.333 1.333 0 1 1 .165-.547c-.01.193-.067.38-.165.547zm-.48-12.191a1.333 1.333 0 1 1 .507-1.814c.14.237.198.514.164.787-.038.438-.289.828-.67 1.045v-.018zM13.333 26.667C5.97 26.667 0 20.697 0 13.333 0 5.97 5.97 0 13.333 0c2.929-.01 5.778.955 8.098 2.742L19.8 4.89a10.667 10.667 0 0 0-17.133 8.444 10.667 10.667 0 0 0 17.137 8.471l1.627 2.13a13.218 13.218 0 0 1-8.098 2.733z"/> d="M13.284 16.178a2.876 2.876 0 1 1-.008-5.751 2.876 2.876 0 0 1 .008 5.75zm5.596-1.547a1.333 1.333 0 1 1 0-2.667 1.333 1.333 0 0 1 0 2.667zm4.853 1.249a1.271 1.271 0 1 1 .027-.107c0 .031 0 .067-.027.107zm-.937-3.436a1.333 1.333 0 1 1 .986-1.595c.033.172.033.348 0 .52-.07.53-.465.96-.986 1.075zm4.72 3.29a1.333 1.333 0 1 1-1.076-1.538 1.333 1.333 0 0 1 1.116 1.417.342.342 0 0 0-.027.12h-.013zm-1.08-3.33a1.333 1.333 0 1 1 1.088-1.524c.014.114.014.229 0 .342a1.333 1.333 0 0 1-1.102 1.182h.014zm-.925 7.925a1.333 1.333 0 1 1 .165-.547c-.01.193-.067.38-.165.547zm-.48-12.191a1.333 1.333 0 1 1 .507-1.814c.14.237.198.514.164.787-.038.438-.289.828-.67 1.045v-.018zM13.333 26.667C5.97 26.667 0 20.697 0 13.333 0 5.97 5.97 0 13.333 0c2.929-.01 5.778.955 8.098 2.742L19.8 4.89a10.667 10.667 0 0 0-17.133 8.444 10.667 10.667 0 0 0 17.137 8.471l1.627 2.13a13.218 13.218 0 0 1-8.098 2.733z"/>
</svg></a> </svg></a>
</:home-nav> </:home-nav>
<:main-nav> <:main-nav>
{{#if @dc}} {{#if @dc}}
<ul> <ul>
{{#let (or this.nspaces @nspaces) as |nspaces|}} {{#let (or this.nspaces @nspaces) as |nspaces|}}
{{#if (and (env 'CONSUL_NSPACES_ENABLED') (gt nspaces.length 0))}} {{#if (and (env 'CONSUL_NSPACES_ENABLED') (gt nspaces.length 0))}}
<li <li
class="nspaces" class="nspaces"
data-test-nspace-menu data-test-nspace-menu
> >
Namespace Namespace
<PopoverMenu @position="left" as |components api|> <PopoverMenu @position="left" as |components api|>
<BlockSlot @name="trigger"> <BlockSlot @name="trigger">
{{@nspace.Name}} {{@nspace.Name}}
</BlockSlot> </BlockSlot>
{{#if (is-href 'dc.nspaces')}} {{#if (is-href 'dc.nspaces')}}
<BlockSlot @name="header"> <BlockSlot @name="header">
<p> <p>
Namespaces themselves are not namespaced, so switching will not change the current view. Namespaces themselves are not namespaced, so switching will not change the current view.
</p> </p>
</BlockSlot> </BlockSlot>
{{/if}} {{/if}}
<BlockSlot @name="menu"> <BlockSlot @name="menu">
{{#let components.MenuItem components.MenuSeparator as |MenuItem MenuSeparator|}} {{#let components.MenuItem components.MenuSeparator as |MenuItem MenuSeparator|}}
<DataSource
@src="/*/*/namespaces"
@onchange={{action (mut this.nspaces) value="data"}}
@loading="lazy"
/>
{{#each (reject-by 'DeletedAt' nspaces) as |item|}}
<MenuItem
class={{if (eq @nspace.Name item.Name) 'is-active'}}
@href={{href-mut (hash nspace=(concat '~' item.Name))}}
>
<BlockSlot @name="label">
{{item.Name}}
</BlockSlot>
</MenuItem>
{{/each}}
{{#if this.canManageNspaces}}
<MenuSeparator />
<MenuItem
data-test-main-nav-nspaces
@href={{href-to 'dc.nspaces' @dc.Name}}
>
<BlockSlot @name="label">
Manage Namespaces
</BlockSlot>
</MenuItem>
{{/if}}
{{/let}}
</BlockSlot>
</PopoverMenu>
</li>
{{/if}}
{{/let}}
<li
class="dcs"
data-test-datacenter-menu
>
Datacenter
<PopoverMenu @position="left" as |components|>
<BlockSlot @name="trigger">
{{@dc.Name}}
</BlockSlot>
<BlockSlot @name="menu">
{{#let components.MenuItem components.MenuSeparator as |MenuItem MenuSeparator|}}
<DataSource <DataSource
@src="/*/*/namespaces" @src="/*/*/datacenters"
@onchange={{action (mut this.nspaces) value="data"}} @onchange={{action (mut @dcs) value="data"}}
@loading="lazy" @loading="lazy"
/> />
{{#each (reject-by 'DeletedAt' nspaces) as |item|}} {{#each (sort-by 'Name' @dcs) as |item|}}
<MenuItem <MenuItem
class={{if (eq @nspace.Name item.Name) 'is-active'}} data-test-datacenter-picker
@href={{href-mut (hash nspace=(concat '~' item.Name))}} class={{concat (if (eq @dc.Name item.Name) 'is-active') (if item.Local ' is-local') }}
> @href={{href-mut (hash dc=item.Name)}}
<BlockSlot @name="label"> >
{{item.Name}} <BlockSlot @name="label">
</BlockSlot> {{item.Name}}
</MenuItem> {{#if item.Local}}
{{/each}} <span>Local</span>
{{#if this.canManageNspaces}} {{/if}}
<MenuSeparator /> </BlockSlot>
<MenuItem </MenuItem>
data-test-main-nav-nspaces {{/each}}
@href={{href-to 'dc.nspaces' @dc.Name}} {{/let}}
> </BlockSlot>
<BlockSlot @name="label"> </PopoverMenu>
Manage Namespaces
</BlockSlot> </li>
</MenuItem> <li data-test-main-nav-services class={{if (is-href 'dc.services' @dc.Name) 'is-active'}}>
{{/if}} <a href={{href-to 'dc.services' @dc.Name}}>Services</a>
{{/let}} </li>
</BlockSlot> <li data-test-main-nav-nodes class={{if (is-href 'dc.nodes' @dc.Name) 'is-active'}}>
</PopoverMenu> <a href={{href-to 'dc.nodes' @dc.Name}}>Nodes</a>
</li> </li>
<li data-test-main-nav-kvs class={{if (is-href 'dc.kv' @dc.Name) 'is-active'}}>
<a href={{href-to 'dc.kv' @dc.Name}}>Key/Value</a>
</li>
<li data-test-main-nav-intentions class={{if (is-href 'dc.intentions' @dc.Name) 'is-active'}}>
<a href={{href-to 'dc.intentions' @dc.Name}}>Intentions</a>
</li>
<li role="separator">Access Controls</li>
<li data-test-main-nav-tokens class={{if (is-href 'dc.acls.tokens' @dc.Name) 'is-active'}}>
<a href={{href-to 'dc.acls.tokens' @dc.Name}}>Tokens</a>
</li>
<li data-test-main-nav-policies class={{if (is-href 'dc.acls.policies' @dc.Name) 'is-active'}}>
<a href={{href-to 'dc.acls.policies' @dc.Name}}>Policies</a>
</li>
<li data-test-main-nav-roles class={{if (is-href 'dc.acls.roles' @dc.Name) 'is-active'}}>
<a href={{href-to 'dc.acls.roles' @dc.Name}}>Roles</a>
</li>
</ul>
{{/if}} {{/if}}
{{/let}}
<li </:main-nav>
class="dcs"
data-test-datacenter-menu <:complementary-nav>
> <ul>
Datacenter <li data-test-main-nav-help>
<PopoverMenu @position="left" as |components|> <PopoverMenu @position="right" as |components|>
<BlockSlot @name="trigger"> <BlockSlot @name="trigger">
{{@dc.Name}} Help
</BlockSlot> </BlockSlot>
<BlockSlot @name="menu"> <BlockSlot @name="menu">
{{#let components.MenuItem components.MenuSeparator as |MenuItem MenuSeparator|}} {{#let components.MenuItem components.MenuSeparator as |MenuItem MenuSeparator|}}
<DataSource
@src="/*/*/datacenters"
@onchange={{action (mut @dcs) value="data"}}
@loading="lazy"
/>
{{#each (sort-by 'Name' @dcs) as |item|}}
<MenuItem <MenuItem
data-test-datacenter-picker class="docs-link"
class={{concat (if (eq @dc.Name item.Name) 'is-active') (if item.Local ' is-local') }} @href={{env 'CONSUL_DOCS_URL'}}
@href={{href-mut (hash dc=item.Name)}}
> >
<BlockSlot @name="label"> <BlockSlot @name="label">
{{item.Name}} Documentation
{{#if item.Local}} </BlockSlot>
<span>Local</span> </MenuItem>
{{/if}} <MenuItem
class="learn-link"
@href={{concat (env 'CONSUL_DOCS_LEARN_URL') '/consul'}}
>
<BlockSlot @name="label">
HashiCorp Learn
</BlockSlot>
</MenuItem>
<MenuSeparator />
<MenuItem
class="learn-link"
@href={{env 'CONSUL_REPO_ISSUES_URL'}}
>
<BlockSlot @name="label">
Provide Feedback
</BlockSlot> </BlockSlot>
</MenuItem> </MenuItem>
{{/each}}
{{/let}} {{/let}}
</BlockSlot> </BlockSlot>
</PopoverMenu> </PopoverMenu>
</li>
</li> <li data-test-main-nav-settings class={{if (is-href 'settings') 'is-active'}}>
<li data-test-main-nav-services class={{if (is-href 'dc.services' @dc.Name) 'is-active'}}> <a href={{href-to 'settings'}}>Settings</a>
<a href={{href-to 'dc.services' @dc.Name}}>Services</a> </li>
</li> {{#if (env 'CONSUL_ACLS_ENABLED')}}
<li data-test-main-nav-nodes class={{if (is-href 'dc.nodes' @dc.Name) 'is-active'}}> <li data-test-main-nav-auth>
<a href={{href-to 'dc.nodes' @dc.Name}}>Nodes</a> <AuthDialog
</li> @dc={{@dc.Name}}
<li data-test-main-nav-kvs class={{if (is-href 'dc.kv' @dc.Name) 'is-active'}}> @nspace={{@nspace.Name}}
<a href={{href-to 'dc.kv' @dc.Name}}>Key/Value</a> @onchange={{this.reauthorize}} as |authDialog components|
</li> >
<li data-test-main-nav-intentions class={{if (is-href 'dc.intentions' @dc.Name) 'is-active'}}> {{#let components.AuthForm components.AuthProfile as |AuthForm AuthProfile|}}
<a href={{href-to 'dc.intentions' @dc.Name}}>Intentions</a> <BlockSlot @name="unauthorized">
</li> <label tabindex="0" for={{concat guid "-login-toggle"}} onkeypress={{this.keypressClick}}>
<li role="separator">Access Controls</li> <span>Log in</span>
<li data-test-main-nav-tokens class={{if (is-href 'dc.acls.tokens' @dc.Name) 'is-active'}}> </label>
<a href={{href-to 'dc.acls.tokens' @dc.Name}}>Tokens</a> <ModalDialog @name={{concat guid "-login-toggle"}} @onclose={{this.close}} @onopen={{this.open}} as |api|>
</li> <Ref @target={{this}} @name="modal" @value={{api}} />
<li data-test-main-nav-policies class={{if (is-href 'dc.acls.policies' @dc.Name) 'is-active'}}> <BlockSlot @name="header">
<a href={{href-to 'dc.acls.policies' @dc.Name}}>Policies</a> <h2>Log in to Consul</h2>
</li> </BlockSlot>
<li data-test-main-nav-roles class={{if (is-href 'dc.acls.roles' @dc.Name) 'is-active'}}> <BlockSlot @name="body">
<a href={{href-to 'dc.acls.roles' @dc.Name}}>Roles</a> <AuthForm as |api|>
</li> <Ref @target={{this}} @name="authForm" @value={{api}} />
</ul> </AuthForm>
{{/if}} </BlockSlot>
<BlockSlot @name="actions" as |close|>
</:main-nav> <button type="button" onclick={{action close}}>
Continue without logging in
<:complementary-nav> </button>
<ul> </BlockSlot>
<li data-test-main-nav-help> </ModalDialog>
<PopoverMenu @position="right" as |components|> </BlockSlot>
<BlockSlot @name="trigger"> <BlockSlot @name="authorized">
Help <ModalDialog @name={{concat guid "-login-toggle"}} @onclose={{this.close}} @onopen={{this.open}} as |api|>
</BlockSlot> <Ref @target={{this}} @name="modal" @value={{api}} />
<BlockSlot @name="menu"> <BlockSlot @name="header">
{{#let components.MenuItem components.MenuSeparator as |MenuItem MenuSeparator|}} <h2>Log in with a different token</h2>
<MenuItem </BlockSlot>
class="docs-link" <BlockSlot @name="body">
@href={{env 'CONSUL_DOCS_URL'}} <AuthForm as |api|>
> <Ref @target={{this}} @name="authForm" @value={{api}} />
<BlockSlot @name="label"> </AuthForm>
Documentation </BlockSlot>
</BlockSlot> <BlockSlot @name="actions" as |close|>
</MenuItem> <button type="button" onclick={{action close}}>
<MenuItem Continue without logging in
class="learn-link" </button>
@href={{concat (env 'CONSUL_DOCS_LEARN_URL') '/consul'}} </BlockSlot>
> </ModalDialog>
<BlockSlot @name="label"> <PopoverMenu @position="right" as |components api|>
HashiCorp Learn <BlockSlot @name="trigger">
</BlockSlot> Logout
</MenuItem> </BlockSlot>
<MenuSeparator /> <BlockSlot @name="menu">
<MenuItem {{#let components.MenuItem components.MenuSeparator as |MenuItem MenuSeparator|}}
class="learn-link" {{!TODO: It might be nice to use one of our recursive components here}}
@href={{env 'CONSUL_REPO_ISSUES_URL'}} {{#if authDialog.token.AccessorID}}
> <li role="none">
<BlockSlot @name="label"> <AuthProfile />
Provide Feedback </li>
</BlockSlot> <MenuSeparator />
</MenuItem> {{/if}}
<MenuItem
class="dangerous"
@onclick={{action authDialog.logout}}
>
<BlockSlot @name="label">
Logout
</BlockSlot>
</MenuItem>
{{/let}}
</BlockSlot>
</PopoverMenu>
</BlockSlot>
{{/let}} {{/let}}
</BlockSlot> </AuthDialog>
</PopoverMenu> </li>
</li> {{/if}}
<li data-test-main-nav-settings class={{if (is-href 'settings') 'is-active'}}> </ul>
<a href={{href-to 'settings'}}>Settings</a> </:complementary-nav>
</li>
{{#if (env 'CONSUL_ACLS_ENABLED')}}
<li data-test-main-nav-auth>
<AuthDialog
@dc={{@dc.Name}}
@nspace={{@nspace.Name}}
@onchange={{this.reauthorize}} as |authDialog components|
>
{{#let components.AuthForm components.AuthProfile as |AuthForm AuthProfile|}}
<BlockSlot @name="unauthorized">
<label tabindex="0" for={{concat guid "-login-toggle"}} onkeypress={{this.keypressClick}}>
<span>Log in</span>
</label>
<ModalDialog @name={{concat guid "-login-toggle"}} @onclose={{this.close}} @onopen={{this.open}} as |api|>
<Ref @target={{this}} @name="modal" @value={{api}} />
<BlockSlot @name="header">
<h2>Log in to Consul</h2>
</BlockSlot>
<BlockSlot @name="body">
<AuthForm as |api|>
<Ref @target={{this}} @name="authForm" @value={{api}} />
</AuthForm>
</BlockSlot>
<BlockSlot @name="actions" as |close|>
<button type="button" onclick={{action close}}>
Continue without logging in
</button>
</BlockSlot>
</ModalDialog>
</BlockSlot>
<BlockSlot @name="authorized">
<ModalDialog @name={{concat guid "-login-toggle"}} @onclose={{this.close}} @onopen={{this.open}} as |api|>
<Ref @target={{this}} @name="modal" @value={{api}} />
<BlockSlot @name="header">
<h2>Log in with a different token</h2>
</BlockSlot>
<BlockSlot @name="body">
<AuthForm as |api|>
<Ref @target={{this}} @name="authForm" @value={{api}} />
</AuthForm>
</BlockSlot>
<BlockSlot @name="actions" as |close|>
<button type="button" onclick={{action close}}>
Continue without logging in
</button>
</BlockSlot>
</ModalDialog>
<PopoverMenu @position="right" as |components api|>
<BlockSlot @name="trigger">
Logout
</BlockSlot>
<BlockSlot @name="menu">
{{#let components.MenuItem components.MenuSeparator as |MenuItem MenuSeparator|}}
{{!TODO: It might be nice to use one of our recursive components here}}
{{#if authDialog.token.AccessorID}}
<li role="none">
<AuthProfile />
</li>
<MenuSeparator />
{{/if}}
<MenuItem
class="dangerous"
@onclick={{action authDialog.logout}}
>
<BlockSlot @name="label">
Logout
</BlockSlot>
</MenuItem>
{{/let}}
</BlockSlot>
</PopoverMenu>
</BlockSlot>
{{/let}}
</AuthDialog>
</li>
{{/if}}
</ul>
</:complementary-nav>
<:main> <:main>
{{yield}} {{yield}}
</:main> </:main>
<:content-info> <:content-info>
<Action <Action
@href={{concat (env 'CONSUL_COPYRIGHT_URL') '/'}} @href={{concat (env 'CONSUL_COPYRIGHT_URL') '/'}}
@external={{true}} @external={{true}}
> >
&copy; {{env 'CONSUL_COPYRIGHT_YEAR'}} HashiCorp &copy; {{env 'CONSUL_COPYRIGHT_YEAR'}} HashiCorp
</Action> </Action>
<p> <p>
Consul {{env 'CONSUL_VERSION'}} Consul {{env 'CONSUL_VERSION'}}
</p> </p>
<Action <Action
@href={{env 'CONSUL_DOCS_URL'}} @href={{env 'CONSUL_DOCS_URL'}}
@external={{true}} @external={{true}}
> >
Documentation Documentation
</Action> </Action>
{{{concat '<!-- ' (env 'CONSUL_GIT_SHA') '-->'}}} {{{concat '<!-- ' (env 'CONSUL_GIT_SHA') '-->'}}}
</:content-info> </:content-info>
</App> </App>
{{/let}}

View File

@ -1,15 +1,7 @@
import Component from '@glimmer/component'; import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { action } from '@ember/object'; import { action } from '@ember/object';
export default class HashiCorpConsul extends Component { export default class HashiCorpConsul extends Component {
@service('dom') dom;
constructor(args, owner) {
super(...arguments);
this.guid = this.dom.guid(this);
}
// TODO: Right now this is the only place where we need permissions // TODO: Right now this is the only place where we need permissions
// but we are likely to need it elsewhere, so probably need a nice helper // but we are likely to need it elsewhere, so probably need a nice helper
get canManageNspaces() { get canManageNspaces() {

View File

@ -0,0 +1,10 @@
import Helper from '@ember/component/helper';
import { inject as service } from '@ember/service';
export default class UniqueIdHelper extends Helper {
@service('dom') dom;
compute(params, hash) {
return this.dom.guid({});
}
}