Skip to content

Commit

Permalink
refactor(cc-grafana-info)!: migrate to the new smart component design
Browse files Browse the repository at this point in the history
BREAKING CHANGE: all properties have been merged into a new `state` property.

Fixes #923
  • Loading branch information
pdesoyres-cc committed Feb 2, 2024
1 parent 1ebec4e commit 9e404f6
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 221 deletions.
7 changes: 4 additions & 3 deletions demo-smart/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@
<li>
<a class="definition-link" href="?definition=cc-env-var-form.smart-exposed-config&context=exposed-config">cc-env-var-form.smart-exposed-config</a>
</li>
<!-- <li>-->
<!-- <a class="definition-link" href="?definition=cc-grafana-info.smart&grafanaBaseLink=http%3A%2F%2Fexample.com"">cc-grafana-info.smart</a>-->
<!-- </li>-->
<li>
<a class="definition-link" href="?definition=cc-grafana-info.smart">cc-grafana-info.smart</a>
</li>
<!-- <li>-->
<!-- <a class="definition-link" href="?definition=cc-invoice-list.smart">cc-invoice-list.smart</a>-->
<!-- </li>-->
Expand Down Expand Up @@ -118,6 +118,7 @@
<div class="context-buttons">
<button data-context='{}'>null</button>
<button data-context='{"apiConfig":{}}'>bad API config</button>
<button data-context='{"ownerId":"orga_3547a882-d464-4c34-8168-add4b3e0c135","grafanaBaseLink":"https://example.com"}'>grafana-info</button>
<button data-context='{"ownerId":"orga_3547a882-d464-4c34-8168-add4b3e0c135","appId":"app_8f5610ab-1d9f-41b6-854f-85d9a115e417"}'>app-node</button>
<button data-context='{"ownerId":"orga_3547a882-d464-4c34-8168-add4b3e0c135","appId":"app_e048c5ba-dc84-4f01-a750-d053706805fd"}'>app-play</button>
<button data-context='{"ownerId":"orga_3547a882-d464-4c34-8168-add4b3e0c135","currentUserId":"user_d3d02829-8847-40ea-ab76-ada4e2f026c0"}'>ACME BAR</button>
Expand Down
62 changes: 24 additions & 38 deletions src/components/cc-grafana-info/cc-grafana-info.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import '../cc-block/cc-block.js';
import '../cc-block-section/cc-block-section.js';
import '../cc-icon/cc-icon.js';
import '../cc-img/cc-img.js';
import '../cc-loader/cc-loader.js';
import '../cc-block-section/cc-block-section.js';
import '../cc-block/cc-block.js';
import '../cc-notice/cc-notice.js';
import { css, html, LitElement } from 'lit';
import { iconRemixInformationFill as iconInfo } from '../../assets/cc-remix.icons.js';
Expand All @@ -17,9 +17,7 @@ const GRAFANA_ADDON_SCREEN = 'https://assets.clever-cloud.com/grafana/screens/ad
const GRAFANA_DOCUMENTATION = 'https://www.clever-cloud.com/doc/administrate/metrics/overview/';

/**
* @typedef {import('./cc-grafana-info.types.js').GrafanaErrorType} GrafanaErrorType
* @typedef {import('./cc-grafana-info.types.js').GrafanaStatusType} GrafanaStatusType
* @typedef {import('./cc-grafana-info.types.js').GrafanaWaitingType} GrafanaWaitingType
* @typedef {import('./cc-grafana-info.types.js').GrafanaInfoState} GrafanaInfoState
*/

/**
Expand All @@ -35,27 +33,15 @@ export class CcGrafanaInfo extends LitElement {

static get properties () {
return {
error: { type: String },
link: { type: String },
status: { type: String },
waiting: { type: String },
state: { type: Object },
};
}

constructor () {
super();

/** @type {GrafanaErrorType} Displays an error message. */
this.error = false;

/** @type {string|null} Sets the grafana link. */
this.link = null;

/** @type {GrafanaStatusType} Grafana account status, is the Grafana enabled or disabled? Null means no data are received. */
this.status = null;

/** @type {GrafanaWaitingType} Waiting for the result status (based on actions: reset, disable or enable). */
this.waiting = false;
/** @type {GrafanaInfoState} Sets the grafana info state. */
this.state = { type: 'loading' };
}

_getDashboards () {
Expand Down Expand Up @@ -95,18 +81,18 @@ export class CcGrafanaInfo extends LitElement {

render () {

const isWaitingGrafana = this.waiting === 'enabling' || this.waiting === 'disabling';
const isFormDisabled = this.error !== false || this.waiting !== false;
const isGrafanaStatusLoading = this.error !== 'loading' && this.status == null;
const isGrafanaDisabled = this.error !== 'loading' && this.status === 'disabled';
const isGrafanaEnabled = this.error !== 'loading' && this.status === 'enabled';
const isSwitchingGrafanaStatus = this.state.type === 'loaded' && (this.state.info.action === 'enabling' || this.state.info.action === 'disabling');
const isFormDisabled = this.state.type === 'error' || (this.state.type === 'loaded' && this.state.info.action != null);
const isGrafanaDisabled = this.state.type === 'loaded' && this.state.info.status === 'disabled';
const isGrafanaEnabled = this.state.type === 'loaded' && this.state.info.status === 'enabled';
const isResetting = this.state.type === 'loaded' && this.state.info.status === 'enabled' && this.state.info.action === 'resetting';

return html`
<cc-block>
<div slot="title">${i18n('cc-grafana-info.main-title')}</div>
${isWaitingGrafana ? html`
${isSwitchingGrafanaStatus ? html`
<cc-loader slot="overlay"></cc-loader>
` : ''}
Expand All @@ -121,19 +107,19 @@ export class CcGrafanaInfo extends LitElement {
</div>
</cc-block-section>
${this.error === 'loading' ? html`
${this.state.type === 'loading' ? html`
<cc-block-section>
<div slot="title">${i18n('cc-grafana-info.loading-title')}</div>
<cc-notice intent="warning" message="${i18n('cc-grafana-info.error-loading')}"></cc-notice>
<div>
<cc-loader></cc-loader>
</div>
</cc-block-section>
` : ''}
${isGrafanaStatusLoading ? html`
${this.state.type === 'error' ? html`
<cc-block-section>
<div slot="title">${i18n('cc-grafana-info.loading-title')}</div>
<div>
<cc-loader></cc-loader>
</div>
<cc-notice intent="warning" message="${i18n('cc-grafana-info.error-loading')}"></cc-notice>
</cc-block-section>
` : ''}
Expand All @@ -144,7 +130,7 @@ export class CcGrafanaInfo extends LitElement {
<p>${i18n('cc-grafana-info.enable-description')}</p>
</div>
<div>
<cc-button success ?skeleton=${this._skeleton} ?disabled=${isFormDisabled} @cc-button:click=${this._onEnableSubmit}>
<cc-button success ?disabled=${isFormDisabled} @cc-button:click=${this._onEnableSubmit}>
${i18n('cc-grafana-info.enable-title')}
</cc-button>
</div>
Expand All @@ -157,11 +143,11 @@ export class CcGrafanaInfo extends LitElement {
<div slot="info">
<p>${i18n('cc-grafana-info.grafana-link-description')}</p>
</div>
${this.error === 'link-grafana' || this.link == null ? html`
${this.state.info.link == null ? html`
<cc-notice intent="warning" message="${i18n('cc-grafana-info.error-link-grafana')}"></cc-notice>
` : html`
<div>
${ccLink(this.link, html`
${ccLink(this.state.info.link, html`
<cc-img src="${GRAFANA_LOGO_URL}"></cc-img><span>${i18n('cc-grafana-info.link.grafana')}</span>
`)}
</div>
Expand All @@ -172,14 +158,14 @@ export class CcGrafanaInfo extends LitElement {
<div slot="title">${i18n('cc-grafana-info.reset-title')}</div>
<div slot="info">${i18n('cc-grafana-info.reset-description')}</div>
<div>
<cc-button primary ?skeleton=${this._skeleton} ?disabled=${isFormDisabled} ?waiting=${this.waiting === 'resetting'} @cc-button:click=${this._onResetSubmit}>
<cc-button primary ?disabled=${isFormDisabled} ?waiting=${isResetting} @cc-button:click=${this._onResetSubmit}>
${i18n('cc-grafana-info.reset-title')}
</cc-button>
</div>
</cc-block-section>
` : ''}
${!isWaitingGrafana ? html`
${!isSwitchingGrafanaStatus ? html`
${this._getDashboards().map((item) => html`
<cc-block-section>
<div slot="title">${item.title}</div>
Expand All @@ -198,7 +184,7 @@ export class CcGrafanaInfo extends LitElement {
<div slot="title">${i18n('cc-grafana-info.disable-title')}</div>
<div slot="info">${i18n('cc-grafana-info.disable-description')}</div>
<div>
<cc-button danger delay="3" ?skeleton=${this._skeleton} ?disabled=${isFormDisabled} @cc-button:click=${this._onDisableSubmit}>
<cc-button danger delay="3" ?disabled=${isFormDisabled} @cc-button:click=${this._onDisableSubmit}>
${i18n('cc-grafana-info.disable-title')}
</cc-button>
</div>
Expand Down
163 changes: 75 additions & 88 deletions src/components/cc-grafana-info/cc-grafana-info.smart.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,110 +6,97 @@ import {
getGrafanaOrganisation,
resetGrafanaOrganisation,
} from '../../lib/api-helpers.js';
import { defineSmartComponentWithObservables } from '../../lib/define-smart-component-with-observables.js';
import { defineSmartComponent } from '../../lib/define-smart-component.js';
import { i18n } from '../../lib/i18n.js';
import { notifyError, notifySuccess } from '../../lib/notifications.js';
import { fromCustomEvent, LastPromise, unsubscribeWithSignal, withLatestFrom } from '../../lib/observables.js';
import { sendToApi } from '../../lib/send-to-api.js';

// TODO, we need to refactor this one to make it more like the others
defineSmartComponentWithObservables({
defineSmartComponent({
selector: 'cc-grafana-info',
params: {
apiConfig: { type: Object },
ownerId: { type: String },
grafanaBaseLink: { type: String },
},
onConnect (container, component, context$, disconnectSignal) {

const grafana_lp = new LastPromise();

const onReset$ = fromCustomEvent(component, 'cc-grafana-info:reset')
.pipe(withLatestFrom(context$));
const onDisable$ = fromCustomEvent(component, 'cc-grafana-info:disable')
.pipe(withLatestFrom(context$));
const onEnable$ = fromCustomEvent(component, 'cc-grafana-info:enable')
.pipe(withLatestFrom(context$));

unsubscribeWithSignal(disconnectSignal, [

grafana_lp.error$.subscribe(console.error),
grafana_lp.error$.subscribe(() => {
component.error = 'loading';
component.waiting = false;
}),

grafana_lp.value$.subscribe((product) => {
component.status = product.status;
if (component.status === 'enabled' && product.link == null) {
component.error = 'link-grafana';
}
else {
component.link = product.link;
}
component.waiting = false;
}),

onReset$.subscribe(([variables, { apiConfig, ownerId }]) => {

component.error = false;
component.waiting = 'resetting';

doResetGrafanaOrganisation({ apiConfig, ownerId })
.then(() => notifySuccess(i18n('cc-grafana-info.reset.success')))
.catch(() => notifyError(i18n('cc-grafana-info.reset.error')))
.finally(() => {
component.waiting = false;
onContextUpdate ({ context, updateComponent, onEvent, signal }) {
const { apiConfig, ownerId, grafanaBaseLink } = context;

updateComponent('state', { type: 'loading' });

function fetch () {
fetchGrafanaOrganisation({ apiConfig, signal, ownerId, grafanaBaseLink })
.then((info) => {
updateComponent('state', { type: 'loaded', info });
})
.catch((error) => {
console.error(error);
updateComponent('state', { type: 'error' });
});
}

onEvent('cc-grafana-info:reset', () => {
updateComponent('state', (state) => {
state.info.action = 'resetting';
});

doResetGrafanaOrganisation({ apiConfig, ownerId })
.then(() => notifySuccess(i18n('cc-grafana-info.reset.success')))
.catch((error) => {
console.error(error);
notifyError(i18n('cc-grafana-info.reset.error'));
})
.finally(() => {
updateComponent('state', (state) => {
state.info.action = null;
});
}),

onDisable$.subscribe(([variables, { apiConfig, ownerId }]) => {
});
});

component.error = false;
component.waiting = 'disabling';
onEvent('cc-grafana-info:disable', () => {
updateComponent('state', (state) => {
state.info.action = 'disabling';
});

disableGrafanaOrganisation({ apiConfig, ownerId })
.then(() => {
component.status = 'disabled';
component.link = null;
notifySuccess(i18n('cc-grafana-info.disable.success'));
})
.catch(() => notifyError(i18n('cc-grafana-info.disable.error')))
.finally(() => {
component.waiting = false;
disableGrafanaOrganisation({ apiConfig, ownerId })
.then(() => {
updateComponent('state', (state) => {
state.info = { status: 'disabled' };
});
}),

onEnable$.subscribe(([_, { apiConfig, ownerId, grafanaBaseLink }]) => {

component.error = false;
component.waiting = 'enabling';

enableGrafanaOrganisation({ apiConfig, ownerId })
.then(() => {
grafana_lp.push((signal) => fetchGrafanaOrganisation({ apiConfig, signal, ownerId, grafanaBaseLink }));
notifySuccess(i18n('cc-grafana-info.enable.success'));
})
.catch(() => notifyError(i18n('cc-grafana-info.enable.error')))
.finally(() => {
component.waiting = false;
notifySuccess(i18n('cc-grafana-info.disable.success'));
})
.catch((error) => {
console.error(error);
notifyError(i18n('cc-grafana-info.disable.error'));
})
.finally(() => {
updateComponent('state', (state) => {
state.info.action = null;
});
}),

context$.subscribe(({ apiConfig, ownerId, grafanaBaseLink }) => {

component.error = false;
component.link = null;
component.status = null;
component.waiting = false;

if (apiConfig != null && ownerId != null && grafanaBaseLink != null) {
grafana_lp.push((signal) => fetchGrafanaOrganisation({ apiConfig, signal, ownerId, grafanaBaseLink }));
}
}),
});
});

]);
onEvent('cc-grafana-info:enable', () => {
updateComponent('state', (state) => {
state.info.action = 'enabling';
});

enableGrafanaOrganisation({ apiConfig, ownerId })
.then(() => {
fetch();
notifySuccess(i18n('cc-grafana-info.enable.success'));
})
.catch((error) => {
console.error(error);
notifyError(i18n('cc-grafana-info.enable.error'));
})
.finally(() => {
updateComponent('state', (state) => {
state.info.action = null;
});
});
});

fetch();
},
});

Expand All @@ -123,7 +110,7 @@ function fetchGrafanaOrganisation ({ apiConfig, signal, ownerId, grafanaBaseLink
})
.catch((error) => {
if (error.response?.status === 404 && error.toString().startsWith('Error: Grafana organization not found')) {
return { status: 'disabled', link: null };
return { status: 'disabled' };
}
else {
throw error;
Expand Down

0 comments on commit 9e404f6

Please sign in to comment.