Skip to content

Commit

Permalink
Merge pull request #931 from CleverCloud/new-smart-design/cc-article-…
Browse files Browse the repository at this point in the history
…list

refactor(cc-article-list)!: migrate to the new smart component design
  • Loading branch information
pdesoyres-cc authored Feb 2, 2024
2 parents ffc7464 + 4711406 commit 77e75c0
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 77 deletions.
7 changes: 4 additions & 3 deletions demo-smart/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@
<li>
<a class="definition-link" href="?definition=cc-addon-linked-apps.smart">cc-addon-linked-apps.smart</a>
</li>
<!-- <li>-->
<!-- <a class="definition-link" href="?definition=cc-article-list.smart">cc-article-list.smart</a>-->
<!-- </li>-->
<li>
<a class="definition-link" href="?definition=cc-article-list.smart">cc-article-list.smart</a>
</li>
<!-- <li>-->
<!-- <a class="definition-link" href="?definition=cc-env-var-form.smart-config-provider&context=config-provider">cc-env-var-form.smart-config-provider</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='{"lang":"en", "limit": 5}'>article-list</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>
Expand Down
28 changes: 12 additions & 16 deletions src/components/cc-article-list/cc-article-list.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { css, html, LitElement } from 'lit';
import { i18n } from '../../lib/i18n.js';
import '../cc-article-card/cc-article-card.js';
import '../cc-notice/cc-notice.js';
import { css, html, LitElement } from 'lit';
import { i18n } from '../../lib/i18n.js';

const ARTICLE_SKELETON_NUMBER = 9;

/**
* @typedef {import('./cc-article-list.types.js').Article} Article
* @typedef {import('./cc-article-list.types.js').ArticleListState} ArticleListState
*/

/**
Expand All @@ -18,37 +18,33 @@ export class CcArticleList extends LitElement {

static get properties () {
return {
articles: { type: Array },
error: { type: Boolean },
state: { type: Object },
};
}

constructor () {
super();

/** @type {Article[]} Sets an array that contains for each element an object with the content of a card article. */
this.articles = null;

/** @type {boolean} Displays an error message. */
this.error = false;
/** @type {ArticleListState} Sets the articles list state. */
this.state = { type: 'loading' };
}

render () {

const skeleton = (this.articles == null);

return html`
<div class="article-container">
${this.error ? html`
${this.state.type === 'error' ? html`
<cc-notice intent="warning" message="${i18n('cc-article-list.error')}"></cc-notice>
` : ''}
${skeleton && !this.error ? html`
${this.state.type === 'loading' ? html`
${new Array(ARTICLE_SKELETON_NUMBER).fill(html`
<cc-article-card></cc-article-card>
`)}
` : ''}
${!skeleton && !this.error ? html`
${this.articles.map((article) => html`
${this.state.type === 'loaded' ? html`
${this.state.articles.map((article) => html`
<cc-article-card
banner=${article.banner}
title=${article.title ?? ''}
Expand Down
46 changes: 16 additions & 30 deletions src/components/cc-article-list/cc-article-list.smart.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,30 @@ import './cc-article-list.js';
import '../cc-smart-container/cc-smart-container.js';
import { request } from '@clevercloud/client/esm/request.fetch.js';
import { withCache } from '@clevercloud/client/esm/with-cache.js';
import { defineSmartComponentWithObservables } from '../../lib/define-smart-component-with-observables.js';
import { LastPromise, unsubscribeWithSignal } from '../../lib/observables.js';
import { defineSmartComponent } from '../../lib/define-smart-component.js';
import { parseRssFeed } from '../../lib/xml-parser.js';

const FOUR_HOURS = 1000 * 60 * 60 * 4;

defineSmartComponentWithObservables({
defineSmartComponent({
selector: 'cc-article-list',
params: {
lang: { type: String },
limit: { type: Number },
},
onConnect (container, component, context$, disconnectSignal) {

const articles_lp = new LastPromise();

unsubscribeWithSignal(disconnectSignal, [

articles_lp.error$.subscribe(console.error),
articles_lp.error$.subscribe(() => (component.error = true)),
articles_lp.value$.subscribe((articles) => (component.articles = articles)),

context$.subscribe(({ lang, limit }) => {

component.error = false;
component.articles = null;

// limit has a defaut value
if (lang != null) {
articles_lp.push((signal) => fetchArticleList({ signal, lang, limit }));
}

}),

]);

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

const { lang, limit } = context;

fetchArticleList({ signal, lang, limit })
.then((articles) => {
updateComponent('state', { type: 'loaded', articles: articles });
})
.catch((error) => {
console.error(error);
updateComponent('state', { type: 'error' });
});
},
});

Expand All @@ -59,7 +47,5 @@ async function fetchArticleList ({ signal, lang, limit = 9 }) {
FOUR_HOURS,
() => request(requestParams));

const articleList = parseRssFeed(rssFeed, limit);

return articleList;
return parseRssFeed(rssFeed, limit);
}
22 changes: 5 additions & 17 deletions src/components/cc-article-list/cc-article-list.smart.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ title: '💡 Smart'
<table>
<tr><th>Name <th>Type <th>Details <th>Default
<tr><td><code>lang</code> <td><code>String</code> <td>Sets the language the feed should be fetched in<td>
<tr><td><code>limit</code> <td><code>Number</code> <td>Sets the number of articles from the feed you should get<td>9
<tr><td><code>limit</code> <td><code>Number</code> <td>Sets the number of articles from the feed you should get<td>
</table>

## 🌐 API endpoints
Expand All @@ -34,35 +34,23 @@ title: '💡 Smart'
### English

```html
<cc-smart-container context='{ "lang": "en" }'>
<cc-smart-container context='{ "lang": "en" , "limit": 3}'>
<cc-article-list></cc-article-list>
</cc-smart-container>
```

<cc-smart-container context='{ "lang": "en" }'>
<cc-smart-container context='{ "lang": "en", "limit": 3 }'>
<cc-article-list></cc-article-list>
</cc-smart-container>

### French

```html
<cc-smart-container context='{ "lang": "fr" }'>
<cc-article-list></cc-article-list>
</cc-smart-container>
```

<cc-smart-container context='{ "lang": "fr" }'>
<cc-article-list></cc-article-list>
</cc-smart-container>

### Limit (number of articles)

```html
<cc-smart-container context='{ "lang": "en", "limit": 3 }'>
<cc-smart-container context='{ "lang": "fr", "limit": 3 }'>
<cc-article-list></cc-article-list>
</cc-smart-container>
```

<cc-smart-container context='{ "lang": "en", "limit": 3 }'>
<cc-smart-container context='{ "lang": "fr", "limit": 3 }'>
<cc-article-list></cc-article-list>
</cc-smart-container>
26 changes: 16 additions & 10 deletions src/components/cc-article-list/cc-article-list.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,34 +66,40 @@ const conf = {
export const defaultStory = makeStory(conf, {
items: [
{
articles: ARTICLES,
state: {
type: 'loaded',
articles: ARTICLES,
},
},
],
});

export const skeleton = makeStory(conf, {
items: [{}],
export const loading = makeStory(conf, {
items: [{ state: { type: 'loading' } }],
});

// No need to invest time on empty story right now.

export const error = makeStory(conf, {
items: [{ error: true }],
items: [{ state: { type: 'error' } }],
});

export const dataLoaded = makeStory(conf, {
items: [
{
articles: ARTICLES,
state: {
type: 'loaded',
articles: ARTICLES,
},
},
],
});

export const simulationsWithSucess = makeStory(conf, {
export const simulationsWithSuccess = makeStory(conf, {
items: [{}],
simulations: [
storyWait(2000, ([component]) => {
component.articles = ARTICLES;
component.state = { type: 'loaded', articles: ARTICLES };
}),
],
});
Expand All @@ -102,16 +108,16 @@ export const simulationsWithError = makeStory(conf, {
items: [{}],
simulations: [
storyWait(2000, ([componentError]) => {
componentError.error = true;
componentError.state = { type: 'error' };
}),
],
});

enhanceStoriesNames({
defaultStory,
loading,
error,
skeleton,
dataLoaded,
simulationsWithSucess,
simulationsWithSuccess,
simulationsWithError,
});
17 changes: 16 additions & 1 deletion src/components/cc-article-list/cc-article-list.types.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
export interface Article {
export type ArticleListState = ArticleListStateLoading | ArticleListStateError | ArticleListStateLoaded;

interface ArticleListStateLoading {
type: 'loading';
}

interface ArticleListStateError {
type: 'error';
}

interface ArticleListStateLoaded {
type: 'loaded';
articles: Array<Article>;
}

interface Article {
banner: string;
title: string;
link: string;
Expand Down

0 comments on commit 77e75c0

Please sign in to comment.