Skip to content
This repository was archived by the owner on Dec 30, 2025. It is now read-only.

Commit 19a28c4

Browse files
feat: Website - Display the Migration tab (#3683)
* site: display Migration tab * lint rules + script fix * address Pavel's concerns * fix for republishing staging * URL capitalization
1 parent eabf5bf commit 19a28c4

File tree

18 files changed

+453
-63
lines changed

18 files changed

+453
-63
lines changed

packages/dx-demo-shell/scripts/demos-generator.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import fs from 'fs';
22
import path from 'path';
33
import mustache from 'mustache';
44

5-
import { overrideFileIfChanged } from './fs-utils.js';
5+
import { writeStringToFile } from './fs-utils.js';
66

77
const DEMOS_FOLDER = './src/demo-sources';
88
const THEMES_FOLDER = './src/theme-sources';
@@ -47,7 +47,7 @@ const removeSuffix = (str, suffix) => str.substring(0, str.length - suffix.lengt
4747
const createFromTemplate = (sourceFilename, outputFilename, data) => {
4848
const source = fs.readFileSync(sourceFilename, 'utf-8');
4949
const output = mustache.render(source, data);
50-
overrideFileIfChanged(outputFilename, output);
50+
writeStringToFile(outputFilename, output);
5151
cancelFileRemoving(outputFilename);
5252
};
5353

@@ -77,6 +77,16 @@ export const loadDemosToGenerate = (themeNames) => {
7777
}
7878
const demoExtension = getDemoExtension(nestedFile);
7979
const demoName = removeSuffix(nestedFile, `.${demoExtension}`);
80+
const isMigrationSample = file.startsWith('$');
81+
if (isMigrationSample) {
82+
demos.push({
83+
sectionName,
84+
demoName,
85+
demoExtension,
86+
isMigrationSample: true,
87+
});
88+
return;
89+
}
8090
const testFile = fs.existsSync(path.join(DEMOS_FOLDER, sectionName, `${demoName}${TEST_SUFFIX}.jsxt`))
8191
? path.join(DEMOS_FOLDER, sectionName, `${demoName}${TEST_SUFFIX}.jsxt`)
8292
: getTestFileName(demoExtension);
@@ -174,15 +184,21 @@ export const generateDemos = (demos) => {
174184
generateTest,
175185
generateSsrTest,
176186
}) => {
187+
const themeData = themeName
188+
? JSON.parse(fs.readFileSync(path.join(THEMES_FOLDER, themeName, THEME_DEMO_DATA_FILE), 'utf-8'))
189+
: {};
190+
177191
const demoSourceData = {
178192
themeName,
179193
sectionName,
180194
demoName: `${demoName}${generateDemo ? GENERATED_SUFFIX : ''}`,
181-
...JSON.parse(fs.readFileSync(path.join(THEMES_FOLDER, themeName, THEME_DEMO_DATA_FILE), 'utf-8')),
195+
...themeData,
182196
};
183197

184198
try {
185-
fs.mkdirSync(path.join(DEMOS_FOLDER, sectionName, themeName));
199+
if (themeName) {
200+
fs.mkdirSync(path.join(DEMOS_FOLDER, sectionName, themeName));
201+
}
186202
} catch (e) {} // eslint-disable-line no-empty
187203

188204
if (generateDemo) {

packages/dx-demo-shell/scripts/fs-utils.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import fs from 'fs';
22

3-
export const overrideFileIfChanged = (filename, data) => {
3+
export const writeStringToFile = (filename, data, overwriteData = true) => {
44
let existingData;
55
if (fs.existsSync(filename)) {
66
existingData = fs.readFileSync(filename, 'utf-8');
77
}
8-
if (existingData !== data) {
8+
if (overwriteData && existingData !== data) {
99
fs.writeFileSync(filename, data, 'utf-8');
10+
} else if (!overwriteData) {
11+
fs.writeFileSync(filename, `${existingData}\n${data}`, 'utf-8');
1012
}
1113
};
1214
const indent = level => ' '.repeat(level * 2);
@@ -35,6 +37,7 @@ const stringifyEntity = (entity, level) => {
3537
if (type === "string" || type === "number") {
3638
return entity + ',\n';
3739
}
40+
3841
throw new Error('unsupported entity');
3942
}
4043
const stringifyObject = (obj, level) => Object.keys(obj)
@@ -44,9 +47,10 @@ const stringifyObject = (obj, level) => Object.keys(obj)
4447

4548
const stringify = obj => stringifyEntity(obj, 0);
4649

47-
export const writeObjectToFile = (filePath, obj, varName) => {
48-
overrideFileIfChanged(
50+
export const writeObjectToFile = (filePath, obj, varName, overwriteData = true) => {
51+
writeStringToFile(
4952
filePath,
5053
`export const ${varName} = ${stringify(obj)};\n`,
54+
overwriteData,
5155
);
5256
};

packages/dx-demo-shell/scripts/registry-generator.js

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,29 +26,63 @@ export const generateDemoRegistry = (demos, folderPath, getDemoLink) => {
2626
);
2727
});
2828

29-
const sections = Object.keys(structuredDemos).reduce((sectionsAcc, sectionName) => {
30-
sectionsAcc[sectionName] = Object.keys(structuredDemos[sectionName]).reduce((demosAcc, demoName) => {
31-
demosAcc[demoName] = structuredDemos[sectionName][demoName]
32-
.reduce((themesAcc, { themeName, generateDemo, demoExtension }) => {
33-
const fileName = `${DEMOS_FOLDER}/${sectionName}/${themeName}/${demoName}${generateDemo ? GENERATED_SUFFIX : ''}.${demoExtension}`;
34-
const demoSource = getFileContents(fileName);
35-
const helperFiles = parseHelperFiles(demoSource);
36-
37-
themesAcc[themeName] = {
38-
...getDemoLink(fileName) ? { demo: getDemoLink(fileName) } : {},
39-
source: demoSource,
40-
productName: `"${productName}"`,
41-
helperFiles,
42-
...(demoExtension === 'tsx') ? { requireTs: "true" } : {},
43-
};
44-
return themesAcc;
45-
}, {});
46-
47-
return demosAcc;
48-
}, {});
49-
50-
return sectionsAcc;
51-
}, {});
29+
const selectFromDemos = getSelector => Object.keys(structuredDemos).reduce((
30+
sectionsAcc,
31+
sectionName,
32+
) => ({
33+
...sectionsAcc,
34+
[sectionName]: Object.keys(structuredDemos[sectionName]).reduce((demosAcc, demoName) => ({
35+
...demosAcc,
36+
[demoName]: structuredDemos[sectionName][demoName].reduce(
37+
getSelector(sectionName, demoName),
38+
{},
39+
),
40+
}), {}),
41+
}), {});
42+
43+
const demoDataSelector = (sectionName, demoName) => (acc, {
44+
themeName,
45+
generateDemo,
46+
demoExtension,
47+
isMigrationSample,
48+
}) => {
49+
if (isMigrationSample) {
50+
return acc;
51+
}
52+
53+
const fileName = `${DEMOS_FOLDER}/${sectionName}/${themeName}/${demoName}${generateDemo ? GENERATED_SUFFIX : ''}.${demoExtension}`;
54+
const demoSource = getFileContents(fileName);
55+
const helperFiles = parseHelperFiles(demoSource);
56+
57+
acc[themeName] = {
58+
...getDemoLink(fileName) ? { demo: getDemoLink(fileName) } : {},
59+
source: demoSource,
60+
productName: `"${productName}"`,
61+
helperFiles,
62+
...(demoExtension === 'tsx') ? { requireTs: 'true' } : {},
63+
};
64+
return acc;
65+
};
66+
67+
const migrationSampleSelector = (sectionName, demoName) => (acc, {
68+
demoExtension,
69+
isMigrationSample,
70+
}) => {
71+
if (!isMigrationSample) {
72+
return acc;
73+
}
74+
75+
const fileName = `${DEMOS_FOLDER}/${sectionName}/$migration/${demoName}.${demoExtension}`;
76+
const demoSource = getFileContents(fileName);
77+
78+
return {
79+
source: demoSource,
80+
};
81+
};
82+
83+
const sections = selectFromDemos(demoDataSelector);
84+
const migrationSamples = selectFromDemos(migrationSampleSelector);
5285

5386
writeObjectToFile(folderPath, sections, 'demos');
87+
writeObjectToFile(folderPath, migrationSamples, 'migrationSamples', false);
5488
};

packages/dx-demo-shell/src/demo-viewer/demo-code-provider.jsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ export class DemoCodeProvider extends React.PureComponent {
7070
return demoSources[sectionName][demoName][themeName] || {};
7171
}
7272

73+
getMigrationSampleCode() {
74+
const { sectionName, demoName } = this.props;
75+
const { migrationSamples } = this.context;
76+
return migrationSamples[sectionName][demoName]?.source || '';
77+
}
78+
7379
getHelperFiles() {
7480
const { themeName } = this.props;
7581
const { themeComponents, demoData } = this.context;
@@ -160,11 +166,13 @@ export class DemoCodeProvider extends React.PureComponent {
160166
const { requireTs } = this.getDemoConfig();
161167
const onEditableLinkChange = this.onEditableLinkChange.bind(this);
162168
const { editableLink } = this.state;
169+
const migrationSample = this.getMigrationSampleCode();
163170

164171
return children({
165172
html,
166173
sandboxHtml,
167174
code,
175+
migrationSample,
168176
helperFiles,
169177
externalDeps,
170178
requireTs,
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,90 @@
11
span.nav-link {
22
cursor: pointer;
33
}
4+
5+
.demo-viewer .alert-note {
6+
border-radius: 6px;
7+
margin: 20px 0;
8+
padding: 12px 20px;
9+
color: #183C57;
10+
}
11+
12+
.demo-viewer .alert-note .part-title {
13+
font-weight: 700;
14+
font-size: 18px;
15+
line-height: 24px;
16+
}
17+
18+
.demo-viewer .nav {
19+
flex-wrap: nowrap;
20+
}
21+
22+
.demo-viewer .codesandbox-button {
23+
display: none;
24+
}
25+
26+
.demo-viewer .theme-selector {
27+
margin-left: 290px;
28+
display: none;
29+
}
30+
31+
.demo-viewer .theme-selector-displayed {
32+
margin-top: 0;
33+
}
34+
35+
.demo-viewer .theme-selector-hidden {
36+
margin-top: 0;
37+
}
38+
39+
@media (min-width: 480px) {
40+
.demo-viewer .theme-selector {
41+
display: block;
42+
}
43+
44+
.demo-viewer .theme-selector-displayed {
45+
margin-top: -42px;
46+
}
47+
}
48+
49+
@media (min-width: 680px) {
50+
.demo-viewer .codesandbox-button {
51+
display: inline-block;
52+
}
53+
54+
.demo-viewer .theme-selector {
55+
margin-left: 500px;
56+
}
57+
}
58+
59+
@media (min-width: 1000px) {
60+
.demo-viewer .nav .nav-link {
61+
padding: 0.5rem 0.75rem;
62+
}
63+
64+
.demo-viewer .codesandbox-button {
65+
margin-left: 15px;
66+
}
67+
68+
.demo-viewer .theme-selector {
69+
margin-left: 380px;
70+
}
71+
72+
.demo-viewer .theme-selector:has(.migration-tab) {
73+
margin-left: 450px;
74+
}
75+
}
76+
77+
@media (min-width: 1280px) {
78+
.demo-viewer .nav .nav-link {
79+
padding: 0.5rem 1rem;
80+
}
81+
82+
.demo-viewer .codesandbox-button {
83+
margin-left: 20px;
84+
}
85+
86+
.demo-viewer .theme-selector {
87+
margin-left: 500px;
88+
}
89+
}
90+

0 commit comments

Comments
 (0)