Skip to content

Commit

Permalink
repurposing component index code for charts index (#1746)
Browse files Browse the repository at this point in the history
* repurposing component index code for charts index

* dummy data causing build prob?

* dummy data

* does it build with parameter absent, not incorrect

* tweaks made during our call

* added ai-apps basic charts

* feat(chart-index): add carbon charts files to index

* chore(chart-index): fix duplicate titles

* updated filters and test thumbnails

* Optimised images with calibre/image-actions

* added 'Other' as a valid option for chart type

* added a 'complexity' filter

* Optimised images with calibre/image-actions

* Added advanced charts from carbon and ai-apps

* images for all carbon-charts, fix capitalization

* cleanup and page title change

* remove cognos as maintainer until they have content

* add contribution note to no result text

* fix misspelt chart name

* Optimised images with calibre/image-actions

* resolve image conflict

* Optimised images with calibre/image-actions

* Optimised images with calibre/image-actions

Co-authored-by: Alessandra Davila <aledavila@ibm.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
4 people authored Oct 8, 2020
1 parent 11cf109 commit e528f72
Show file tree
Hide file tree
Showing 94 changed files with 2,008 additions and 15 deletions.
11 changes: 11 additions & 0 deletions gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ module.exports = {
path: path.join(__dirname, 'src/data/index'),
ignore: ['**/*.js', '**/*.yml', '**/.*'],
},
options: {
name: 'chart-index-images',
path: path.join(__dirname, 'src/data/chart-index'),
ignore: ['**/*.js', '**/*.yml', '**/.*'],
},
},
{
resolve: 'gatsby-remark-images',
Expand Down Expand Up @@ -58,5 +63,11 @@ module.exports = {
directory: path.resolve(__dirname, './src/data/index'),
},
},
{
resolve: 'gatsby-plugin-chart-index',
options: {
directory: path.resolve(__dirname, './src/data/chart-index'),
},
},
],
};
1 change: 1 addition & 0 deletions plugins/gatsby-plugin-chart-index/data/index.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Name,Website link,Storybook/GitHub,Maintainer team,Description,Framework,Design asset,Platform,Availability,Date added to index,Image,Search aliases
78 changes: 78 additions & 0 deletions plugins/gatsby-plugin-chart-index/gatsby-node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
const fs = require('fs-extra');
const path = require('path');
const yml = require('js-yaml');
const schema = require('./src/schema');

// TODO: for some reason throwing an error in `sourceNodes` here does not cause
// the build to fail. In the interim, we're logging the error to the console and
// manually exiting the process so that we don't have builds that pass but don't
// have the appropriate source nodes
exports.sourceNodes = async (
{ actions, createNodeId, createContentDigest },
pluginOptions
) => {
const { directory: rootDirectory } = pluginOptions;
const { createNode } = actions;

const manifestPath = path.join(rootDirectory, 'maintainers.yml');
if (!(await fs.pathExists(manifestPath))) {
console.log(`Unable to find maintainer manifest at ${manifestPath}`);
process.exit(1);
}

const manifestData = yml.safeLoad(await fs.readFile(manifestPath, 'utf8'));
const { value: manifest, error } = schema.maintainer.validate(manifestData);
if (error) {
console.log(error.annotate());
process.exit(1);
}

const charts = [];

for (const maintainer of manifest.maintainers) {
const directory = path.join(rootDirectory, maintainer.name);
const files = await fs.readdir(directory);

for (const file of files.filter(filterFiles)) {
const filepath = path.join(directory, file);
const contents = await fs.readFile(filepath, 'utf8');
const chart = yml.safeLoad(contents);

charts.push({
...chart,
name: path.basename(file, '.yml'),
friendly_name: chart.name,
maintainer: {
name: maintainer.name,
friendly_name: maintainer.friendly_name,
},
});
}
}

for (const chart of charts) {
const { error, value } = schema.chart.validate(chart);
if (error) {
console.log(error.annotate());
process.exit(1);
}

const node = {
id: createNodeId(`${value.maintainer.name}:${value.name}`),
parent: null,
children: [],
internal: {
type: 'ChartIndexEntry',
contentDigest: createContentDigest(value),
},
...value,
};

createNode(node);
}
};

const denylist = new Set(['images', '.DS_Store']);
function filterFiles(filename) {
return !denylist.has(filename);
}
1 change: 1 addition & 0 deletions plugins/gatsby-plugin-chart-index/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// noop
188 changes: 188 additions & 0 deletions plugins/gatsby-plugin-chart-index/migrations/2020-08-04.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/* eslint-disable */

'use strict';

const { paramCase } = require('change-case');
const fs = require('fs-extra');
const path = require('path');
const csv = require('csvtojson');
const yml = require('js-yaml');
const schema = require('../src/schema');

const CSV_FILEPATH = path.resolve(__dirname, '../data/index.csv');
const renames = {
'Platform (Web, iOS, Android)': 'platform',
'Availability (open source, IBM internal)': 'availability',
'Date added to index': 'date_added',
'Search aliases': 'aliases',
'Design asset': 'design_asset',
'Maintainer team': 'maintainer',
Image: 'image_url',

// New
'Website link': 'website_url',
'Storybook/GitHub': 'code_url',
};
const maintainerRenames = {
'Cloud PAL': 'cloud-pal',
'Cloud Data & AI': 'cdai',
'Watson Health': 'watson-health',
'AI Apps': 'ai-apps',
};

async function main() {
const data = await csv().fromFile(CSV_FILEPATH);
const components = data
// Rename keys
.map((component) => {
const keys = Object.keys(component);
const result = {};
for (const key of keys) {
if (renames[key]) {
const rename = renames[key];
result[rename] = component[key];
} else {
result[key] = component[key];
}
}
return result;
})
// Lowercase
.map((component) => {
const keys = Object.keys(component);
const result = {};
for (const key of keys) {
result[key.toLowerCase()] = component[key];
}
return result;
})
// Transform aliases to array
.map((component) => {
const aliases =
component.aliases.length > 0
? component.aliases
.split(',')
.map((alias) => alias.trim().toLowerCase())
: [];
return {
...component,
aliases,
};
})
// Transform empty fields to null
.map((component) => {
const result = {};
const keys = Object.keys(component);
for (const key of keys) {
const value = component[key];
if (value === '') {
continue;
}
result[key] = component[key];
}
return result;
})
// Transform design asset to Sketch
.map((component) => {
if (component.design_asset) {
switch (component.design_asset) {
case 'CD&AI Design Kit':
case 'IBM Watson IoT PAL tables':
case 'IBM Watson IoT PAL charts':
case 'IBM Watson IoT PAL.sketch':
case 'IBM Watson IoT PAL buttons':
component.design_asset = 'Sketch';
break;
case 'No asset':
component.design_asset = null;
}
}
return component;
})
.filter((component) => {
return component.name !== 'Not included';
})
.map((component) => {
const result = {};
for (const key of Object.keys(component)) {
if (component[key] === 'n/a') {
continue;
}
result[key] = component[key];
}
return result;
})
.map((component) => {
return {
...component,
date_added: '2020-08-04',
};
});

const maintainers = new Map();

for (const component of components) {
if (!maintainers.has(component.maintainer)) {
maintainers.set(component.maintainer, {
components: [],
});
}
const maintainer = maintainers.get(component.maintainer);
maintainer.components.push(component);
}

const INDEX_DATA_DIRECTORY = path.resolve(
__dirname,
'../../../src/data/index'
);

if (await fs.pathExists(INDEX_DATA_DIRECTORY)) {
await fs.emptyDir(INDEX_DATA_DIRECTORY);
}
await fs.ensureDir(INDEX_DATA_DIRECTORY);

const manifestFilePath = path.join(INDEX_DATA_DIRECTORY, 'maintainers.yml');
const manifestFile = {
maintainers: Array.from(maintainers.keys())
.sort()
.map((friendlyName) => {
return {
name: maintainerRenames[friendlyName],
friendly_name: friendlyName,
};
}),
};

await fs.writeFile(manifestFilePath, yml.safeDump(manifestFile), 'utf8');

for (const [maintainer, value] of maintainers) {
const directory = path.join(
INDEX_DATA_DIRECTORY,
maintainerRenames[maintainer]
);
await fs.ensureDir(directory);

for (const component of value.components) {
const filepath = path.join(directory, `${paramCase(component.name)}.yml`);
const entry = {};

for (const key of Object.keys(component)) {
if (component[key] !== null) {
entry[key] = component[key];
}
}

const { value, error } = schema.component.validate(entry);
if (error) {
throw error;
}
const data = yml.safeDump(value);
await fs.writeFile(filepath, data, 'utf8');
}
}
}

main().catch((error) => {
console.log(error);
process.exit(1);
});
Loading

1 comment on commit e528f72

@vercel
Copy link

@vercel vercel bot commented on e528f72 Oct 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.