-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* ui: Logout button This commit adds an easier way to logout of the UI using a logout button Notes: - Added a Logout button to the main navigation when you are logged in, meaning you have easy access to a way to log out of the UI. - Changed all wording to use 'Log in/out' vocabulary instad of 'stop using'. - The logout button opens a panel to show you your current ACL token and a logout button in order to logout. - When using legacy ACLs we don't show the current ACL token as legacy ACLs tokens only have secret values, whereas the new ACLs use a non-secret ID plus a secret ID (that we don't show). - We also added a new `<EmptyState />` component to use for all our empty states. We currently only use this for the ACLs disabled screen to provide more outgoing links to more readind material/documentation to help you to understand and enable ACLs. - The `<DataSink />` component is the sibling to our `<DataSource />` component and whilst is much simpler (as it doesn't require polling support), its tries to use the same code patterns for consistencies sake. - We had a fun problem with ember-data's `store.unloadAll` here, and in the end went with `store.init` to empty the ember-data store instead due to timing issues. - We've tried to use already existing patterns in the Consul UI here such as our preexisting `feedback` service, although these are likely to change in the future. The thinking here is to add this feature with as little change as possible. Overall this is a precursor to a much larger piece of work centered on auth in the UI. We figured this was a feature complete piece of work as it is and thought it was worthwhile to PR as a feature on its own, which also means the larger piece of work will be a smaller scoped PR also.
- Loading branch information
Showing
47 changed files
with
730 additions
and
183 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
## DataSink | ||
|
||
```handlebars | ||
<DataSink | ||
@sink="/dc/nspace/intentions/{{intentions.uid}}" | ||
@onchange={{action (mut items) value="data"}} | ||
@onerror={{action (mut error) value="error"}} | ||
as |api| | ||
></DataSink> | ||
``` | ||
|
||
### Arguments | ||
|
||
| Argument | Type | Default | Description | | ||
| --- | --- | --- | --- | | ||
| `sink` | `String` | | The location of the sink, this should map to a string based URI | | ||
| `data` | `Object` | | The data to be saved to the current instance, null or an empty string means remove | | ||
| `onchange` | `Function` | | The action to fire when the data has arrived to the sink. Emits an Event-like object with a `data` property containing the data, if the data was deleted this is `undefined`. | | ||
| `onerror` | `Function` | | The action to fire when an error occurs. Emits ErrorEvent object with an `error` property containing the Error. | | ||
|
||
### Methods/Actions/api | ||
|
||
| Method/Action | Description | | ||
| --- | --- | | ||
| `open` | Manually add or remove fom the data sink | | ||
|
||
The component takes a `sink` or an identifier (a uri) for the location of a sink and then emits `onchange` events whenever that data has been arrived to the sink (whether persisted or removed). If an error occurs whilst listening for data changes, an `onerror` event is emitted. | ||
|
||
Behind the scenes in the Consul UI we map URIs back to our `ember-data` backed `Repositories` meaning we can essentially redesign the URIs used for our data to more closely fit our needs. For example we currently require that **all** HTTP API URIs begin with `/dc/nspace/` values whether they require them or not. | ||
|
||
`DataSink` is not just restricted to HTTP API data, and can be configured to listen for data changes using a variety of methods and sources. For example we have also configured `DataSink` to send data to `LocalStorage` using the `settings://` pseudo-protocol in the URI (See examples below). | ||
|
||
|
||
### Examples | ||
|
||
```handlebars | ||
<DataSink @src="/dc/nspace/intentions/{{intention.uid}}" | ||
@onchange={{action (mut item) value="data"}} | ||
@onerror={{action (mut error) value="error"}} | ||
as |api| | ||
> | ||
<button type="button" onclick={{action api.open (hash Name="New Name")}}>Create/Update</button> | ||
<button type="button" onclick={{action api.open null}}>Delete</button> | ||
</DataSink> | ||
{{item.Name}} | ||
``` | ||
|
||
```handlebars | ||
<DataSink @src="/dc/nspace/intentions/{{intention.uid}}" | ||
@data=(hash Name="New Name") | ||
@onchange={{action (mut item) value="data"}} | ||
@onerror={{action (mut error) value="error"}} | ||
></DataSink> | ||
{{item.Name}} | ||
``` | ||
|
||
### See | ||
|
||
- [Component Source Code](./index.js) | ||
- [Template Source Code](./index.hbs) | ||
|
||
--- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{{yield (hash | ||
open=(action 'open') | ||
state=state | ||
)}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import Component from '@ember/component'; | ||
import { inject as service } from '@ember/service'; | ||
import { set, get, computed } from '@ember/object'; | ||
|
||
import { once } from 'consul-ui/utils/dom/event-source'; | ||
|
||
export default Component.extend({ | ||
tagName: '', | ||
|
||
service: service('data-sink/service'), | ||
dom: service('dom'), | ||
logger: service('logger'), | ||
|
||
onchange: function(e) {}, | ||
onerror: function(e) {}, | ||
|
||
state: computed('instance', 'instance.{dirtyType,isSaving}', function() { | ||
let id; | ||
const isSaving = get(this, 'instance.isSaving'); | ||
const dirtyType = get(this, 'instance.dirtyType'); | ||
if (typeof isSaving === 'undefined' && typeof dirtyType === 'undefined') { | ||
id = 'idle'; | ||
} else { | ||
switch (dirtyType) { | ||
case 'created': | ||
id = isSaving ? 'creating' : 'create'; | ||
break; | ||
case 'updated': | ||
id = isSaving ? 'updating' : 'update'; | ||
break; | ||
case 'deleted': | ||
case undefined: | ||
id = isSaving ? 'removing' : 'remove'; | ||
break; | ||
} | ||
id = `active.${id}`; | ||
} | ||
return { | ||
matches: name => id.indexOf(name) !== -1, | ||
}; | ||
}), | ||
|
||
init: function() { | ||
this._super(...arguments); | ||
this._listeners = this.dom.listeners(); | ||
}, | ||
willDestroy: function() { | ||
this._super(...arguments); | ||
this._listeners.remove(); | ||
}, | ||
source: function(cb) { | ||
const source = once(cb); | ||
const error = err => { | ||
set(this, 'instance', undefined); | ||
try { | ||
this.onerror(err); | ||
this.logger.execute(err); | ||
} catch (err) { | ||
this.logger.execute(err); | ||
} | ||
}; | ||
this._listeners.add(source, { | ||
message: e => { | ||
try { | ||
set(this, 'instance', undefined); | ||
this.onchange(e); | ||
} catch (err) { | ||
error(err); | ||
} | ||
}, | ||
error: e => error(e), | ||
}); | ||
return source; | ||
}, | ||
didInsertElement: function() { | ||
this._super(...arguments); | ||
if (typeof this.data !== 'undefined') { | ||
this.actions.open.apply(this, [this.data]); | ||
} | ||
}, | ||
persist: function(data, instance) { | ||
set(this, 'instance', this.service.prepare(this.sink, data, instance)); | ||
this.source(() => this.service.persist(this.sink, this.instance)); | ||
}, | ||
remove: function(instance) { | ||
set(this, 'instance', this.service.prepare(this.sink, null, instance)); | ||
this.source(() => this.service.remove(this.sink, this.instance)); | ||
}, | ||
actions: { | ||
open: function(data, instance) { | ||
if (instance instanceof Event) { | ||
instance = undefined; | ||
} | ||
if (typeof data === 'undefined') { | ||
throw new Error('You must specify data to save, or null to remove'); | ||
} | ||
// potentially allow {} and "" as 'remove' flags | ||
if (data === null || data === '') { | ||
this.remove(instance); | ||
} else { | ||
this.persist(data, instance); | ||
} | ||
}, | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{{yield}} | ||
<div class="empty-state" ...attributes> | ||
<header> | ||
{{#yield-slot name="header"}} | ||
{{yield}} | ||
{{/yield-slot}} | ||
{{#yield-slot name="subheader"}} | ||
{{yield}} | ||
{{/yield-slot}} | ||
</header> | ||
<p> | ||
{{#yield-slot name="body"}} | ||
{{yield}} | ||
{{/yield-slot}} | ||
</p> | ||
{{#yield-slot name="actions"}} | ||
<ul> | ||
{{yield}} | ||
</ul> | ||
{{/yield-slot}} | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import Component from '@ember/component'; | ||
import Slotted from 'block-slots'; | ||
|
||
export default Component.extend(Slotted, { | ||
tagName: '', | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.