ui: Change URI helper to a template based approach (#9344)

This moves our uri helper to use a the template renderer we already have for rendering URLs.
This commit is contained in:
John Cowen 2020-12-09 09:22:46 +00:00 committed by hashicorp-ci
parent 4f3a0836ea
commit c3218f1bee
7 changed files with 99 additions and 22 deletions

View File

@ -1,8 +1,28 @@
<DataLoader @items={{item}} @src={{uri nspace dc type src}} @onchange={{action "setData"}} @once={{true}}> <DataLoader
@items={{item}}
@src={{uri
'/${nspace}/${dc}/${type}/${src}'
(hash
nspace=nspace
dc=dc
type=type
src=src
)
}}
@onchange={{action "setData"}}
@once={{true}}
>
<BlockSlot @name="loaded"> <BlockSlot @name="loaded">
<DataWriter <DataWriter
@sink={{uri nspace (or data.Datacenter dc) type}} @sink={{uri
'/${nspace}/${dc}/${type}'
(hash
nspace=nspace
dc=(or data.Datacenter dc)
type=type
)
}}
@type={{type}} @type={{type}}
@label={{label}} @label={{label}}
@ondelete={{action ondelete}} @ondelete={{action ondelete}}

View File

@ -1,6 +1,14 @@
{{#if (not @noMetricsReason)}} {{#if (not @noMetricsReason)}}
<DataSource <DataSource
@src={{uri @nspace @dc 'metrics' 'summary-for-service' @service @protocol}} @src={{uri
'/${nspace}/${dc}/metrics/summary-for-service/${service}/${protocol}'
(hash
nspace=@nspace
dc=@dc
service=@service
protocol=@protocol
)
}}
@onchange={{action 'change'}} @onchange={{action 'change'}}
@onerror={{action (mut error) value="error"}} @onerror={{action (mut error) value="error"}}
/> />

View File

@ -1,6 +1,15 @@
{{#if (not @noMetricsReason)}} {{#if (not @noMetricsReason)}}
<DataSource <DataSource
@src={{uri @nspace @dc 'metrics' @endpoint @service @protocol}} @src={{uri
'/${nspace}/${dc}/metrics/${endpoint}/${service}/${protocol}'
(hash
nspace=@nspace
dc=@dc
endpoint=@endpoint
service=@service
protocol=@protocol
)
}}
@onchange={{action 'statsUpdate'}} @onchange={{action 'statsUpdate'}}
@onerror={{action (mut error) value="error"}} @onerror={{action (mut error) value="error"}}
/> />

View File

@ -1,18 +1,19 @@
import { helper } from '@ember/component/helper'; import Helper from '@ember/component/helper';
import { get } from '@ember/object'; import { inject as service } from '@ember/service';
// Covers alpha-capitalized dot separated API keys such as // simple mustache regexp `/{{item.Name}}/`
// `{{Name}}`, `{{Service.Name}}` etc. but not `{{}}`
const templateRe = /{{([A-Za-z.0-9_-]+)}}/g; const templateRe = /{{([A-Za-z.0-9_-]+)}}/g;
export default helper(function renderTemplate([template, vars]) { let render;
if (typeof vars !== 'undefined' && typeof template !== 'undefined') { export default class RenderTemplateHelper extends Helper {
return template.replace(templateRe, function(match, group) { @service('encoder') encoder;
try { constructor() {
return encodeURIComponent(get(vars, group) || ''); super(...arguments);
} catch (e) { if (typeof render !== 'function') {
return ''; render = this.encoder.createRegExpEncoder(templateRe, encodeURIComponent, false);
} }
});
} }
return '';
}); compute([template, vars]) {
return render(template, vars);
}
}

View File

@ -1,10 +1,18 @@
import Helper from '@ember/component/helper'; import Helper from '@ember/component/helper';
import { inject as service } from '@ember/service'; import { inject as service } from '@ember/service';
const templateRe = /\${([A-Za-z.0-9_-]+)}/g;
let render;
export default class UriHelper extends Helper { export default class UriHelper extends Helper {
@service('encoder') encoder; @service('encoder') encoder;
constructor() {
super(...arguments);
if (typeof render !== 'function') {
render = this.encoder.createRegExpEncoder(templateRe, encodeURIComponent);
}
}
compute(params, hash) { compute([template, vars]) {
return this.encoder.uriJoin(params); return render(template, vars);
} }
} }

View File

@ -1,10 +1,32 @@
import Service from '@ember/service'; import Service from '@ember/service';
import { get } from '@ember/object';
import { runInDebug } from '@ember/debug';
import atob from 'consul-ui/utils/atob'; import atob from 'consul-ui/utils/atob';
import btoa from 'consul-ui/utils/btoa'; import btoa from 'consul-ui/utils/btoa';
const createRegExpEncoder = function(re, encoder = str => str, strict = true) {
return (template = '', vars = {}) => {
if (template !== '') {
return template.replace(re, (match, group) => {
const value = get(vars, group);
runInDebug(() => {
if (strict && typeof value === 'undefined') {
console.error(new Error(`${group} is undefined in ${template}`));
}
});
return encoder(value || '');
});
}
return '';
};
};
export default class EncoderService extends Service { export default class EncoderService extends Service {
uriComponent = encodeURIComponent; uriComponent = encodeURIComponent;
createRegExpEncoder(re, encoder) {
return createRegExpEncoder(re, encoder);
}
atob() { atob() {
return atob(...arguments); return atob(...arguments);
} }

View File

@ -1,4 +1,13 @@
<DataLoader @src={{uri nspace dc 'intentions' 'for-service' slug}} as |api|> <DataLoader
@src={{uri
'/${nspace}/${dc}/intentions/for-service/${slug}'
(hash
nspace=nspace
dc=dc
slug=slug
)
}}
as |api|>
<BlockSlot @name="error"> <BlockSlot @name="error">
<ErrorState @error={{api.error}} /> <ErrorState @error={{api.error}} />
</BlockSlot> </BlockSlot>