consul/ui/packages/consul-ui/app/components/data-source
John Cowen fc14a412fd
ui: Partitions Application Layer (#11017)
* Add Partition to all our models

* Add partitions into our serializers/fingerprinting

* Make some amends to a few adapters ready for partitions

* Amend blueprints to avoid linting error

* Update all  our repositories to include partitions, also

Remove enabled/disable nspace repo and just use a nspace with
conditionals

* Ensure nspace and parition parameters always return '' no matter what

* Ensure data-sink finds the model properly

This will later be replaced by a @dataSink decorator but we are find
kicking that can down the road a little more

* Add all the new partition data layer

* Add a way to set the title of the page from inside the route

and make it accessibile via a route announcer

* Make the Consul Route the default/basic one

* Tweak nspace and partition abilities not to check the length

* Thread partition through all the components that need it

* Some ACL tweaks

* Move the entire app to use partitions

* Delete all the tests we no longer need

* Update some Unit tests to use partition

* Fix up KV title tests

* Fix up a few more acceptance tests

* Fixup and temporarily ignore some acceptance tests

* Stop using ember-cli-page-objects fillable as it doesn't seem to work

* Fix lint error

* Remove old ACL related test

* Add a tick after filling out forms

* Fix token warning modal

* Found some more places where we need a partition var

* Fixup some more acceptance tests

* Tokens still needs a repo service for CRUD

* Remove acceptance tests we no longer need

* Fixup and "FIXME ignore" a few tests

* Remove an s

* Disable blocking queries for KV to revert to previous release for now

* Fixup adapter tests to follow async/function resolving interface

* Fixup all the serializer integration tests

* Fixup service/repo integration tests

* Fixup deleting acceptance test

* Fixup some ent tests

* Make sure nspaces passes the dc through for when thats important

* ...aaaand acceptance nspaces with the extra dc param
2021-09-15 19:50:11 +01:00
..
README.mdx ui: Partitions Application Layer (#11017) 2021-09-15 19:50:11 +01:00
index.hbs
index.js ui: Partitions Application Layer (#11017) 2021-09-15 19:50:11 +01:00

README.mdx

# DataSource

Use the `@dataSource` decorator in your repositories to define URI to async
method mapping.

```javascript
class SomethingRepository extends Service {
  @dataSource('/:partition/:nspace/:dc/services')
  async youCouldCallItAnythingTodoWithGettingServices(params) {
    console.log(params);
    // {partition: "partition", nspace: "nspace", dc: "dc"}
    return getTheThing(params);
  }
}
```

```hbs preview-template
<DataSource
  @src="/partition/nspace/dc/services"
  @loading="eager"
  @disabled={{false}}
as |source|>
{{#each source.data as |service|}}
{{service.Name}}<br />
{{/each}}
</DataSource>
```

## Attributes

| Argument | Type | Default | Description |
| --- | --- | --- | --- |
| `src` | `String` | | The source to subscribe to updates to, this should map to a string based URI |
| `loading` | `String` | eager | Allows the browser to defer loading offscreen DataSources (`eager\|lazy`). Setting to `lazy` only loads the data when the DataSource is visible in the DOM (inc. `display: none\|block;`) |
| `disabled` | `Boolean` | true | When disabled the DataSource is closed |
| `open` | `Boolean` | false | Force the DataSource to open, used to force non-blocking data to refresh (has no effect for blocking data) |
| `onchange` | `Function` |  | The action to fire when the data changes. Emits an Event-like object with a `data` property containing the data. |
| `onerror` | `Function` |  | The action to fire when an error occurs. Emits ErrorEvent object with an `error` property containing the Error. |

The component takes a `src` or an identifier (a uri) for some data and then emits `onchange` events whenever that data changes. If an error occurs whilst listening for data changes, an `onerror` event is emitted.

Setting `@loading="lazy"` uses `IntersectionObserver` to activate/deactive event emitting until the `<DataSource />` element is displayed in the DOM. This means you can use CSS `display: none|block;` to control the loading and stopping loading of data for usage with CSS based tabs and such-like.

Consuls HTTP API DataSources use Consul's blocking query support for live updating of data.

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.

`DataSource` 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 `DataSource` to listen to `LocalStorage` changes using the `settings://` pseudo-protocol in the URI (See examples below).


## Examples

Straightforward usage can use `mut` to easily update data within a template using an event handler approach.

```hbs
  {{! listen for HTTP API changes}}
  <DataSource
    @src="/partition/nspace/dc/services"
    @onchange={{action (mut items) value="data"}}
    @onerror={{action (mut error) value="error"}}
  />
  {{#if error}}
    Something went wrong!
  {{/if}}
  {{#if (not items)}}
    Loading...
  {{/if}}
  {{! the value of items will change whenever the data changes}}
  {{#each items as |item|}}
    {{item.Name}} {{! < Prints the item name }}
  {{/each}}

  {{! listen for Settings (local storage) changes}}
  <DataSource
    @src="settings://consul:token"
    @onchange={{action (mut token) value="data"}}
    @onerror={{action (mut error) value="error"}}
  />
  {{! the value of token will change whenever the data changes}}
  {{token.AccessorID}} {{! < Prints the token AccessorID }}
```

A property approach to easily update data within a template

```hbs
  {{! listen for HTTP API changes}}
  <DataSource
    @src="/partition/nspace/dc/services"
  as |source|>
    {{#if source.error}}
      Something went wrong!
    {{/if}}
    {{#if (not source.data)}}
      Loading...
    {{/if}}
    {{! the value of items will change whenever the data changes}}
    {{#each source.data as |item|}}
      {{item.Name}} {{! < Prints the item name }}
    {{/each}}
  </DataSource>
```

Both approaches can be used in tandem.

DataSources can also be recursively nested for loading in series as opposed to in parallel. Nested DataSources will not start loading until the immediate parent has loaded (ie. it has data) as they are not placed into the DOM until this has happened. However, if a DataSource has started loading, and the immediate parent errors, the nested DataSource will stop receiving updates yet it and its properties will remain accessible within the DOM.

```hbs

  {{! straightforwards error/loading states}}
  {{#if error}}
    Something went wrong!
  {{else if (not loaded)}}
    Loading...
  {{/if}}

  {{! listen for HTTP API changes}}
  <DataSource
    @src="/partition/nspace/dc/services"
    @onerror={{action (mut error) value="error"}}
  as |source|>

    <source.Source
      @src="/partition/nspace/dc/service/{{source.data.firstObject.Name}}"
      @onerror={{action (mut error) value="error"}}
    as |source|>

      {{source.data.Service.Service.Name}} <== Detailed information for the first service

      <source.Source
        @src="/partition/nspace/dc/proxy/for-service/{{source.data.Service.ID}}"
        @onerror={{action (mut error) value="error"}}
        @onchange={{action (mut loaded) true}}
      as |source|>

        {{source.data.DestinationName}}

      </source.Source>

    </source.Source>

  </DataSource>
```

## See

- [Component Source Code](./index.js)
- [Template Source Code](./index.hbs)

---