diff --git a/app/styles/components/_dropdown.scss b/app/styles/components/_dropdown.scss index e4810bfaf..d6f6b014b 100644 --- a/app/styles/components/_dropdown.scss +++ b/app/styles/components/_dropdown.scss @@ -57,6 +57,11 @@ $ember-basic-dropdown-content-z-index: 1500; background: $accent-bg; } + &.lang-select { + max-height: 300px; + overflow: scroll; + } + // Links within the dropdown menu > li > a { display: block; diff --git a/app/styles/components/_tooltip.scss b/app/styles/components/_tooltip.scss index 8380f9a87..e938433d3 100644 --- a/app/styles/components/_tooltip.scss +++ b/app/styles/components/_tooltip.scss @@ -90,6 +90,12 @@ $tooltip-arrow-color : $tooltip-bg !default; background: lighten($primary-dark, 15%); } + .icon-vertical-ellipsis { + position: relative; + top: 50%; + transform: translateY(-50%); + } + .icon-chevron-down { transition: ease all 350ms; } diff --git a/lib/global-admin/addon/components/site-access/component.js b/lib/global-admin/addon/components/site-access/component.js index fa8be5c19..50c4e3051 100644 --- a/lib/global-admin/addon/components/site-access/component.js +++ b/lib/global-admin/addon/components/site-access/component.js @@ -3,6 +3,7 @@ import Component from '@ember/component'; import Errors from 'ui/utils/errors'; import layout from './template'; import { get, set, observer } from '@ember/object'; +import { on } from '@ember/object/evented'; export default Component.extend({ layout, @@ -20,11 +21,6 @@ export default Component.extend({ saved: true, errors: null, - init() { - this._super(...arguments); - this.accessModeChanged(); - }, - actions: { addAuthorized(principal) { if ( !principal ) { @@ -76,7 +72,7 @@ export default Component.extend({ return get(this, 'model.accessMode') !== 'unrestricted'; }.property('model.accessMode'), - accessModeChanged: observer('model.accessMode', function() { + accessModeChanged: on('init', observer('model.accessMode', function() { set(this, 'saved',false); let allowedPrincipals = get(this, 'model.allowedPrincipalIds') || []; // ['princ_id1://yada'] @@ -93,6 +89,6 @@ export default Component.extend({ } set(this, 'model.allowedPrincipalIds', allowedPrincipals); - }), + })), }); diff --git a/lib/global-admin/addon/security/authentication/azuread/controller.js b/lib/global-admin/addon/security/authentication/azuread/controller.js index d05becacf..300ed00d6 100644 --- a/lib/global-admin/addon/security/authentication/azuread/controller.js +++ b/lib/global-admin/addon/security/authentication/azuread/controller.js @@ -1,127 +1,183 @@ import { later } from '@ember/runloop'; import { inject as service } from '@ember/service'; import Controller from '@ember/controller'; +import { alias } from '@ember/object/computed'; +import { + get, set, setProperties, computed +} from '@ember/object'; +import C from 'ui/utils/constants'; export default Controller.extend({ - access : service(), - settings : service(), - intl : service(), + access: service(), + settings: service(), + intl: service(), - confirmDisable : false, - errors : null, - testing : false, - error : null, + confirmDisable: false, + errors: null, + testing: false, + error: null, - loginUsername : null, - loginPassword : null, + loginUsername: null, + loginPassword: null, + + //new + azureADConfig: alias('model.azureADConfig'), + isEnabled: alias('azureADConfig.enabled'), + editing: false, + mode: 'global', + modeClass: 'span-4', + + numUsers: computed('azureADConfig.allowedPrincipalIds.[]','userType','groupType', function() { + return ( get(this, 'azureADConfig.allowedPrincipalIds') || [] ).filter(principal => principal.includes(C.PROJECT.TYPE_AZURE_USER)).get('length'); + }), + + numGroups: computed('azureADConfig.allowedPrincipalIds.[]','userType','groupType', function() { + return ( get(this, 'azureADConfig.allowedPrincipalIds') || [] ).filter(principal => principal.includes(C.PROJECT.TYPE_AZURE_GROUP)).get('length'); + }), actions: { + + edit() { + set(this, 'editing', true); + }, + + toggleMode() { + + if (get(this, 'mode') === 'global') { + + setProperties(this, { + mode: 'china', + modeClass: 'span-3' + }); + + } else { + + setProperties(this, { + mode: 'global', + modeClass: 'span-4' + }); + + } + }, + test: function() { this.send('clearError'); - var model = this.get('model'); + const model = get(this, 'azureADConfig'); + const enabled = get(this, 'azureADConfig.enabled'); + model.setProperties({ - enabled: false, + accessMode: 'unrestricted', }); var errors = model.validationErrors(); - if ( errors.get('length') ) - { - this.set('errors', errors); - } - else - { - this.set('testing', true); - model.save().then(() => { - this.send('authenticate'); - }).catch(err => { + + if ( errors.get('length') ) { + + set(this, 'errors', errors); + set(this, 'testing', false); + model.set('enabled', enabled); + + } else { + + set(this, 'testing', true); + + // delete model.enabled; + + model.doAction('testAndApply', { + azureAdConfig: model, + enabled: true, + username: get(this, 'loginUsername'), + password: get(this, 'loginPassword'), + }).then( () => { + + this.send('waitAndRefresh'); + + }).catch((err) => { + + set(model, 'enabled', enabled); + this.send('gotError', err); + }); } }, - authenticate: function() { - this.send('clearError'); - var code = this.get('loginUsername')+':'+this.get('loginPassword'); - this.get('access').login(code).then(res => { - this.send('authenticationSucceeded', res.body); - }).catch(err => { - this.send('gotError', err); - }); - }, - - authenticationSucceeded: function(/*auth*/) { - this.send('clearError'); - - // Set this to true so the token will be sent with the request - this.set('access.enabled', true); - - var model = this.get('model'); - model.setProperties({ - enabled: true, - }); - - model.save().then(() => { - this.send('waitAndRefresh'); - }).catch((err) => { - this.set('access.enabled', false); - this.send('gotError', err); - }); - }, - waitAndRefresh: function(url) { + $('#loading-underlay, #loading-overlay').removeClass('hide').show(); // eslint-disable-line + setTimeout(function() { window.location.href = url || window.location.href; }, 1000); + }, promptDisable: function() { - this.set('confirmDisable', true); + + set(this, 'confirmDisable', true); + later(this, function() { - this.set('confirmDisable', false); + set(this, 'confirmDisable', false); }, 10000); + }, gotError: function(err) { - if ( err.message ) - { + + if ( err.message ) { + this.send('showError', err.message + (err.detail? '('+err.detail+')' : '')); - } - else - { + + } else { + this.send('showError', 'Error ('+err.status + ' - ' + err.code+')'); + } - this.set('testing', false); - this.set('saving', false); + setProperties(this, { + testing: false, + saving: false, + }); + }, showError: function(msg) { - this.set('errors', [msg]); + + set(this, 'errors', [msg]); + window.scrollY = 0; + }, clearError: function() { - this.set('errors', null); + + set(this, 'errors', null); + }, disable: function() { + this.send('clearError'); - var model = this.get('model'); - model.setProperties({ - enabled: false, - username: "", - password: "", + const model = get(this, 'azureADConfig'); + + setProperties(model, { + enabled: false, }); - model.save().then(() => { + model.doAction('disable').then(() => { + this.send('waitAndRefresh'); + }).catch((err) => { + this.send('gotError', err); + }).finally(() => { - this.set('confirmDisable', false); + + set(this, 'confirmDisable', false); + }); }, }, diff --git a/lib/global-admin/addon/security/authentication/azuread/route.js b/lib/global-admin/addon/security/authentication/azuread/route.js index c7fde2c27..a4bf65dff 100644 --- a/lib/global-admin/addon/security/authentication/azuread/route.js +++ b/lib/global-admin/addon/security/authentication/azuread/route.js @@ -1,11 +1,17 @@ import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; +import { get } from '@ember/object'; +import { hash } from 'rsvp'; export default Route.extend({ - model: function() { - return this.get('globalStore').find('azureadconfig', null, {forceReload: true}).then((collection) => { - let obj = collection.get('firstObject'); - obj.set('accessMode','unrestricted'); - return obj; - }); + globalStore: service(), + + model() { + let gs = get(this, 'globalStore'); + return hash({ + azureADConfig: gs.find('authconfig', 'azuread'), + principals: gs.all('principal') + }).catch( e => e); }, + }); diff --git a/lib/global-admin/addon/security/authentication/azuread/template.hbs b/lib/global-admin/addon/security/authentication/azuread/template.hbs index b702c369e..16bc1d63b 100644 --- a/lib/global-admin/addon/security/authentication/azuread/template.hbs +++ b/lib/global-admin/addon/security/authentication/azuread/template.hbs @@ -1,117 +1,187 @@
- {{#if access.enabled}} -

{{t 'authPage.azuread.header.enabled'}}

- {{t 'authPage.azuread.subtext.enabled' appName=settings.appName}} + {{#if isEnabled}} +

{{t (concat 'authPage.azuread.header.enabled.' azureADConfig.accessMode) + appName=settings.appName + groups=numGroups + users=numUsers + htmlSafe=true + }}

{{else}} -

{{t 'authPage.azuread.subtext.disabled' appName=settings.appName}}

+

{{t 'authPage.azuread.header.disabled.warning' appName=settings.appName}}

{{/if}}
-{{#if access.enabled}} -
-

{{t 'authPage.azuread.enabled.header' htmlSafe=true}}

-
-

- {{t 'authPage.azuread.enabled.warning' appName=settings.appName htmlSafe=true}} -

+{{#accordion-list showExpandAll=false as |al expandFn|}} - {{#if confirmDisable}} - - {{else}} - - {{/if}} + {{#if isEnabled}} -
-{{/if}} + {{#accordion-list-item + detail=(t 'authPage.azuread.configure.help') + expand=(action expandFn) + expandAll=al.expandAll + expandOnInit=true + expanded=true + showExpand=false + title=(t 'authPage.github.authenticated.header.text') + }} -{{#unless access.enabled}} -
-

{{t 'authPage.azuread.configure.header'}}

-
+
+
+
+ + +
+ {{t 'authPage.azuread.configure.help'}} +
+
+
+
+

{{t 'authPage.azuread.enabled.general.header'}}

+
+ {{t 'authPage.azuread.configure.tenantId.label'}}: {{azureADConfig.tenantId}} +
+
+ {{t 'authPage.azuread.configure.clientId.label'}}: {{azureADConfig.clientId}} +
+
+ {{t 'authPage.azuread.configure.domain.label'}}: {{azureADConfig.domain}} +
+
+
+
-
-
-
- - {{input type="text" value=model.tenantId placeholder=(t 'authPage.azuread.configure.tenantId.placeholder') classNames="form-control"}} -

{{t 'authPage.azuread.configure.tenantId.help'}}

-
-
-
-
- - {{input type="text" value=model.clientId placeholder=(t 'authPage.azuread.configure.clientId.placeholder') classNames="form-control"}} -
-
-
-
- - {{input type="text" value=model.domain placeholder=(t 'authPage.azuread.configure.domain.placeholder') classNames="form-control"}} -
-
-
+ {{/accordion-list-item}} -
-
-
- - {{input type="text" value=model.adminAccountUsername placeholder=(t 'authPage.azuread.configure.adminAccountUsername.placeholder') classNames="form-control"}} -

{{t 'authPage.azuread.configure.adminAccountUsername.help'}}

-
-
-
-
- - {{input type="password" value=model.adminAccountPassword classNames="form-control"}} -
-
-
-
+ {{#accordion-list-item + classNames="mt-30" + detail=(t 'siteAccess.helpText' appName=settings.appName htmlSafe=true) + expand=(action expandFn) + expandAll=al.expandAll + expandOnInit=true + expanded=true + showExpand=false + title=(t 'siteAccess.header') + }} -
-

{{t 'authPage.azuread.test.header'}}

-
-

{{t 'authPage.azuread.test.help'}}

- {{top-errors errors=errors}} + {{site-access + model=azureADConfig + principals=model.principals + collection='siteAccess.organizations' + }} -
-
-
- - {{input type="text" value=loginUsername prompt=(t 'authPage.azuread.test.username.placeholder') classNames="form-control"}} + {{/accordion-list-item}} + + {{/if}} + + + {{#if (or (not isEnabled) editing)}} + {{#accordion-list-item + classNames="mt-30" + detail=(t 'authPage.azuread.configure.help') + expand=(action expandFn) + expandAll=al.expandAll + expandOnInit=true + expanded=true + showExpand=false + title=(t 'authPage.azuread.configure.header') + }} + +
+
+
+ + +
-
-
-
- - {{input type="password" value=loginPassword classNames="form-control"}} +
+ +
+
+
+ + {{input type="text" value=azureADConfig.tenantId placeholder=(t 'authPage.azuread.configure.tenantId.placeholder') classNames="form-control"}} +

{{t 'authPage.azuread.configure.tenantId.help'}}

+
+
+
+
+ + {{input type="text" value=azureADConfig.clientId placeholder=(t 'authPage.azuread.configure.clientId.placeholder') classNames="form-control"}} +
+
+ {{#unless (eq mode 'global')}} +
+
+ + {{input type="password" value=azureADConfig.clientSecret placeholder=(t 'authPage.azuread.configure.clientSecret.placeholder') classNames="form-control"}} +
+
+ {{/unless}} +
+
+ + {{input type="text" value=azureADConfig.domain placeholder=(t 'authPage.azuread.configure.domain.placeholder') classNames="form-control"}} +
+
-
-
-
- - +
+ + {{/accordion-list-item}} + + {{#accordion-list-item + classNames="mt-30" + detail=(t 'authPage.azuread.test.help') + expand=(action expandFn) + expandAll=al.expandAll + expandOnInit=true + expanded=true + showExpand=false + title=(t 'authPage.azuread.test.header') + }} + +
+ {{top-errors errors=errors}} +
+
+
+ + {{input type="text" value=loginUsername prompt=(t 'authPage.azuread.test.username.placeholder') classNames="form-control"}} +
+
+
+
+ + {{input type="password" value=loginPassword classNames="form-control"}} +
+
- - -
-{{/unless}} +
+
+ +
+
+ + + {{/accordion-list-item}} + {{/if}} + +{{/accordion-list}} \ No newline at end of file diff --git a/lib/global-admin/addon/security/authentication/controller.js b/lib/global-admin/addon/security/authentication/controller.js index cb6a9b837..8634b3639 100644 --- a/lib/global-admin/addon/security/authentication/controller.js +++ b/lib/global-admin/addon/security/authentication/controller.js @@ -10,9 +10,8 @@ export default Controller.extend({ drivers: computed(function() { return [ {route: 'security.authentication.activedirectory', label: 'Active Directory', css: 'activedirectory', available: this.hasRecord('activedirectoryconfig') }, - // {route: 'security.authentication.azuread', label: 'Azure AD', css: 'azuread', available: this.hasRecord('azureadconfig') }, + {route: 'security.authentication.azuread', label: 'Azure AD', css: 'azuread', available: this.hasRecord('azureadconfig') }, {route: 'security.authentication.github', label: 'GitHub', css: 'github', available: this.hasRecord('githubconfig') }, - // {route: 'security.authentication.localauth', label: 'Local', css: 'local', available: this.hasRecord('localconfig') }, // always on // {route: 'security.authentication.openldap', label: 'OpenLDAP', css: 'openldap', available: this.hasRecord('openldapconfig') }, // {route: 'security.authentication.shibboleth', label: 'Shibboleth', css: 'shibboleth', available: this.hasRecord('shibbolethconfig') }, ]; diff --git a/lib/login/addon/components/login-user-pass/component.js b/lib/login/addon/components/login-user-pass/component.js index 30dd519c4..3c0b48cba 100644 --- a/lib/login/addon/components/login-user-pass/component.js +++ b/lib/login/addon/components/login-user-pass/component.js @@ -1,24 +1,72 @@ -import { get, set, computed } from '@ember/object'; +import { get, set, computed, setProperties } from '@ember/object'; import { next } from '@ember/runloop'; import { inject as service } from '@ember/service'; import Component from '@ember/component'; import C from 'ui/utils/constants'; export default Component.extend({ - access: service(), + access: service(), cookies: service(), - isCaas: computed('app.mode', function() { - return this.get('app.mode') === 'caas' ? true : false; - }), - waiting: null, + intl: service(), - username: null, + waiting: null, + username: null, rememberUsername: false, - password: null, - shown: false, - provider: null, + password: null, + shown: false, + provider: null, readableProvider: null, - onlyLocal: null, + onlyLocal: null, + + init() { + this._super(...arguments); + + let username = null; + + if (get(this, 'provider') === 'local') { + + username = get(this, `cookies.${C.COOKIE.USERNAME}`); + + } else { + + username = get(this, `cookies.${get(this, 'provider').toUpperCase()}-USERNAME`); + + } + + if ( username ) { + setProperties(this, { + username: username, + rememberUsername: true, + }); + } + + if (get(this, 'provider') && !get(this,'onlyLocal')) { + + let pv = null; + + switch(get(this, 'provider')) { + + case 'activedirectory': + pv = get(this, 'intl').t('loginPage.readableProviders.ad'); + break; + + case 'azuread': + pv = get(this, 'intl').t('loginPage.readableProviders.azureAd'); + break; + + case 'local': + default: + pv = get(this, 'intl').t('loginPage.readableProviders.local'); + break; + + } + + set(this, 'readableProvider', pv); + + // console.log(this.get('provider')); + } + + }, actions: { showLocal() { @@ -56,39 +104,9 @@ export default Component.extend({ } }, - init() { - this._super(...arguments); - - var username = null; - if (get(this, 'provider') === 'local') { - username = get(this, `cookies.${C.COOKIE.USERNAME}`); - } else { - username = get(this, `cookies.${get(this, 'provider').toUpperCase()}-USERNAME`); - } - - if ( username ) { - set(this, 'username', username); - set(this, 'rememberUsername', true); - } - - if (get(this, 'provider') && !get(this,'onlyLocal')) { - let pv = null; - switch(get(this, 'provider')) { - case 'activedirectory': - pv = 'Active Directory'; - break; - case 'local': - default: - pv = 'a Local User'; - break; - } - - set(this, 'readableProvider', pv); - - // console.log(this.get('provider')); - } - - }, + isCaas: computed('app.mode', function() { + return this.get('app.mode') === 'caas' ? true : false; + }), focusSomething() { if ( this.isDestroyed || this.isDestroying ) { diff --git a/lib/login/addon/login/controller.js b/lib/login/addon/login/controller.js index b5fcddbb7..98e085f70 100644 --- a/lib/login/addon/login/controller.js +++ b/lib/login/addon/login/controller.js @@ -101,6 +101,9 @@ export default Controller.extend({ case 'activedirectory': this.toggleProperty('adWaiting'); break; + case 'azuread': + this.toggleProperty('azureadWaiting'); + break; case 'shibboleth': this.toggleProperty('shibbolethWaiting'); break; diff --git a/lib/login/addon/login/template.hbs b/lib/login/addon/login/template.hbs index a8a47eceb..cfbf5f044 100644 --- a/lib/login/addon/login/template.hbs +++ b/lib/login/addon/login/template.hbs @@ -36,6 +36,16 @@ }} {{/if}} + {{#if isAzureAd}} + {{login-user-pass + action="authenticate" + classNames="row" + provider="azuread" + shown=true + waiting=azureadWaiting + }} + {{/if}} + {{#if isLocal}} {{login-user-pass action="authenticate" diff --git a/lib/shared/addon/components/action-menu/component.js b/lib/shared/addon/components/action-menu/component.js index e13b08028..c6b332b10 100644 --- a/lib/shared/addon/components/action-menu/component.js +++ b/lib/shared/addon/components/action-menu/component.js @@ -1,7 +1,7 @@ import Component from '@ember/component'; import layout from './template'; import { inject as service } from '@ember/service' -import { computed } from '@ember/object'; +import { computed, get } from '@ember/object'; export default Component.extend({ @@ -17,16 +17,29 @@ export default Component.extend({ size: 'xs', actions: { + clickedAction: function(actionName) { this.get('resourceActions').triggerAction(actionName); }, + closeLater(dd) { dd.actions.close(); return true; }, + preload() { this.get('resourceActions').setActionItems(this.get('model'), this.get('context')); - } + }, + + actionsOpen() { + get(this, 'tooltipService').set('childOpened', true); + }, + + actionsClosed() { + get(this, 'tooltipService').set('childOpened', false); + get(this, 'tooltipService').hide(); + }, + }, sizeClass: computed('size', function() { diff --git a/lib/shared/addon/components/action-menu/template.hbs b/lib/shared/addon/components/action-menu/template.hbs index 63948418c..547c29bb6 100644 --- a/lib/shared/addon/components/action-menu/template.hbs +++ b/lib/shared/addon/components/action-menu/template.hbs @@ -1,4 +1,10 @@ -{{#basic-dropdown as |dd|}} +{{#basic-dropdown + horizontalPosition="right" + verticalPosition="below" + onOpen=(action 'actionsOpen') + onClose=(action 'actionsClosed') + as |dd| +}} {{#dd.trigger ariaLabel=(t 'generic.moreActions') diff --git a/lib/shared/addon/components/cluster-driver/driver-azureaks/template.hbs b/lib/shared/addon/components/cluster-driver/driver-azureaks/template.hbs index b10252f58..a1783985d 100644 --- a/lib/shared/addon/components/cluster-driver/driver-azureaks/template.hbs +++ b/lib/shared/addon/components/cluster-driver/driver-azureaks/template.hbs @@ -18,6 +18,10 @@ localizedPrompt=true }} +
+ + {{input type="text" value=config.masterDnsPrefix classNames="form-control" placeholder=(t 'clusterNew.azureaks.dns.placeholder')}} +
{{/accordion-list-item}} {{#accordion-list-item @@ -70,7 +74,7 @@ {{t 'generic.na'}} {{else}} - {{input type="text" value=config.clientSecret classNames="form-control" placeholder=(t 'clusterNew.azureaks.clientSecret.placeholder')}} + {{input type="password" value=config.clientSecret classNames="form-control" placeholder=(t 'clusterNew.azureaks.clientSecret.placeholder')}} {{/if}} @@ -111,7 +115,7 @@ {{/if}}
- + {{#if editing}}
{{config.resourceGroup}} diff --git a/lib/shared/addon/components/language-dropdown/template.hbs b/lib/shared/addon/components/language-dropdown/template.hbs index 4cfb77181..2a12fd623 100644 --- a/lib/shared/addon/components/language-dropdown/template.hbs +++ b/lib/shared/addon/components/language-dropdown/template.hbs @@ -1,5 +1,4 @@ {{#basic-dropdown - verticalPosition="above" horizontalPosition="right" as |dd| }} @@ -10,7 +9,7 @@ {{selectedLabel}} {{/dd.trigger}} - {{#dd.content class="text-right"}} + {{#dd.content class="text-right lang-select"}} {{#if settings.isRancher}}
  • {{t 'languageContribute'}}
  • diff --git a/lib/shared/addon/mixins/hover-dropdowns.js b/lib/shared/addon/mixins/hover-dropdowns.js index cdbb2924b..23f51b64b 100644 --- a/lib/shared/addon/mixins/hover-dropdowns.js +++ b/lib/shared/addon/mixins/hover-dropdowns.js @@ -1,27 +1,44 @@ import Mixin from '@ember/object/mixin'; import { cancel, later } from '@ember/runloop'; +import { get, set } from '@ember/object'; export default Mixin.create({ + closeTimer: null, + actions: { prevent() { return false; }, open(dropdown) { - if (this.closeTimer) { - cancel(this.closeTimer); - this.closeTimer = null; + const ct = get(this, 'closeTimer'); + + console.log('open closeTimer: ', this.closeTimer, get(dropdown, 'uniqueId')); + if (ct) { + + cancel(ct); + set(this, 'closeTimer', null); + + } else { + dropdown.actions.open(); + } }, closeLater(dropdown) { - this.closeTimer = later(() => { - this.closeTimer = null; + + set(this, 'closeTimer', later(() => { + dropdown.actions.close(); - }, 200); + set(this, 'closeTimer', null); + + }, 200)); + console.log('close closeTimer: ', this.closeTimer, get(dropdown, 'uniqueId')); + } + }, }); diff --git a/lib/shared/addon/tooltip/service.js b/lib/shared/addon/tooltip/service.js index 048595528..f175c480b 100644 --- a/lib/shared/addon/tooltip/service.js +++ b/lib/shared/addon/tooltip/service.js @@ -1,19 +1,24 @@ import { later, cancel } from '@ember/runloop'; import Service, { inject as service } from '@ember/service'; +import { get } from '@ember/object'; const DELAY = 250; export default Service.extend({ - mouseLeaveTimer: null, - requireClick: false, - tooltipOpts: null, + app: service(), + + mouseLeaveTimer: null, + requireClick: false, + tooltipOpts: null, openedViaContextClick: false, - app: service(), + childOpened: false, startTimer() { + this.set('mouseLeaveTimer', later(() => { this.hide(); }, DELAY)); + }, cancelTimer() { @@ -21,13 +26,19 @@ export default Service.extend({ }, hide() { - this.set('tooltipOpts', null); + + if (!get(this, 'childOpened')) { + this.set('tooltipOpts', null); + } + }, leave() { - if ( !this.get('requireClick') ) - { + + if ( !this.get('requireClick') ) { this.startTimer(); } + }, + }); diff --git a/translations/en-us.yaml b/translations/en-us.yaml index 77bf5edd5..2c4f36dfe 100644 --- a/translations/en-us.yaml +++ b/translations/en-us.yaml @@ -449,36 +449,62 @@ authPage: post: Waiting to hear back from GitHub azuread: header: - enabled: 'Azure AD Authentication is enabled' - disabled: 'Azure AD Authentication is not configured' - subtext: - enabled: '{appName} is configured to allow access to accounts in Azure AD' - disabled: '{appName} can be configured to restrict access to a set of accounts defined in the {appName} database. This is not currently set up, so anybody that reach this page (or the API) has full control over the system.' + enabled: + label: "Azure AD is enabled" + required: | + {appName} is configured to allow access to {groups, plural, + =0 {no groups} + =1 {# group} + other {# groups} + } and {users, plural, + =0 {no users} + =1 {# user} + other {# users} + }. + restricted: | + {appName} is configured to allow access to environment members, {groups, plural, + =0 {no groups} + =1 {# group} + other {# groups} + } and {users, plural, + =0 {no users} + =1 {# user} + other {# users} + }. + unrestricted: "{appName} is configured to allow access to any Azure AD user." + disabled: + label: "Azure AD is not configured" + warning: "{appName} can be configured to restrict access to a set of Azure AD users and groups" enabled: header: 'Danger Zone™' - warning: 'Caution: Disabling access control will give complete control over {appName} to anyone that can reach this page or the API.' reallyDisable: 'Are you sure? Click again to really disable access control' - promptDisable: Disable access control + promptDisable: Disable Azure AD + general: + header: General configure: - header: '1. Configure Azure AD Account' - tenantId: - label: Tenant ID - placeholder: A long UUID string - help: From the Azure AD portal - clientId: - label: Client ID - placeholder: A long UUID string - domain: - label: Domain - placeholder: e.g. youcompany.onmicrosoft.com + header: 'Configure Azure AD Account' + help: Enter the Tenant ID, Client ID, and Admin user details to connect to your Azure AD auth account. adminAccountUsername: label: Admin Account Username placeholder: e.g. rancher-admin help: A user that can read information about other users adminAccountPassword: label: Admin Account Password + clientId: + label: Client ID + placeholder: A long UUID string + clientSecret: + label: Client Secret + placeholder: Your Client Secret + domain: + label: Domain + placeholder: e.g. youcompany.onmicrosoft.com + tenantId: + label: Tenant ID + placeholder: A long UUID string + help: From the Azure AD portal test: - header: '2. Test and enable authentication' + header: 'Test and enable authentication' help: 'Check that everything is configured correctly by testing authentication with your account:' username: label: Login Username @@ -1076,6 +1102,10 @@ loginPage: error: authFailedCreds: "Logging in failed: Check credentials, or your account may not be authorized to log in." authFailed: "Logging in failed: Your account may not be authorized to log in." + readableProviders: + ad: Active Directory + azureAd: Azure AD + local: a Local User machinePage: header: Node Drivers @@ -1757,6 +1787,9 @@ clusterNew: prompt: Choose a size... diskSizeGb: label: OS Disk Size + dns: + label: DNS Prfix + placeholder: "e.g. example" ssh: label: SSH Public Key security: @@ -4763,7 +4796,7 @@ nodeDriver: region: label: Region aliyunecs: - accountSection: + accountSection: label: 1. Account Access detail: API Keys will be used to launch Aliyun ECS Instances. next: "Next: Authenticate & Config network options" @@ -4796,7 +4829,7 @@ nodeDriver: aliyunSLB: label: Aliyun SLB ID placeholder: Aliyun SLB ID - storageSection: + storageSection: label: Storage detail: Configure the storage for the instances that will be created by this template. next: "Next: Config Aliyun ECS Instance options" @@ -4837,7 +4870,7 @@ nodeDriver: placeholder: Private IP in Private Network privateAddressOnly: label: Private Address Only - securitySection: + securitySection: label: Security detail: Choose the security groups that will be applied to Instances securityGroup: diff --git a/yarn.lock b/yarn.lock index 17dfab02a..8411bf66a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2604,9 +2604,9 @@ elliptic@^6.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" -ember-api-store@^2.6.6: - version "2.6.6" - resolved "https://registry.yarnpkg.com/ember-api-store/-/ember-api-store-2.6.6.tgz#c405ce94f21ca7c5d80568cbf33f99b42403dce0" +ember-api-store@2.6.8: + version "2.6.8" + resolved "https://registry.yarnpkg.com/ember-api-store/-/ember-api-store-2.6.8.tgz#fdcc950ea1c8cab7633e0480eb5061534c650d0c" dependencies: broccoli-file-creator "^1.1.1" ember-cli-babel "^6.8.2"