Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import type { JSXElement } from '@fluentui/react-components';
import { DeclarativeChart, IDeclarativeChart, Schema } from '@fluentui/react-charts';
import {
Button,
Dropdown,
Field,
Input,
Expand Down Expand Up @@ -158,18 +159,7 @@ const DEFAULT_SCHEMAS = [
const dropdownStyles = { width: 200 };
const inputStyles = { maxWidth: 300 };

const cachedFetch = (url: string) => {
const cachedData = localStorage.getItem(url);
if (cachedData) {
return Promise.resolve(JSON.parse(cachedData));
}
return fetch(url)
.then(response => response.json())
.then(data => {
localStorage.setItem(url, JSON.stringify(data));
return data;
});
};
type LoadingState = 'initial' | 'loading' | 'loaded';

export const DeclarativeChartBasicExample = (): JSXElement => {
const declarativeChartRef = React.useRef<IDeclarativeChart>(null);
Expand All @@ -185,37 +175,44 @@ export const DeclarativeChartBasicExample = (): JSXElement => {
const [fluentDataVizColorPalette, setFluentDataVizColorPalette] =
React.useState<FluentDataVizColorPaletteTypes>('default');
const [showMore, setShowMore] = React.useState(false);
const [isLoading, setLoading] = React.useState(false);
const [loadingState, setLoadingState] = React.useState<LoadingState>('initial');
const [isLoadMoreDisabled, setLoadMoreDisabled] = React.useState(false);

React.useEffect(() => {
doc?.addEventListener('contextmenu', e => {
e.preventDefault();
});
}, [doc]);

React.useEffect(() => {
const loadSchemas = async () => {
setLoading(true);
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
const _schemas: { key: string; schema: any }[] = [];
for (let i = 1; i <= 80; i++) {
try {
const filename = `data_${('00' + i).slice(-3)}`;
const schema = await cachedFetch(
`https://raw.githubusercontent.com/microsoft/fluentui-charting-contrib/refs/heads/main/apps/plotly_examples/src/data/${filename}.json`,
);
_schemas.push({ key: filename, schema });
} catch (error) {
// Nothing to do here
}
}
loadedSchemas.current = _schemas;
setLoading(false);
};

loadSchemas();
const loadSchemas = React.useCallback(async (_loadingState: LoadingState = 'loading') => {
setLoadingState(_loadingState);
let disableLoadMore = false;
const offset = loadedSchemas.current.length;
const promises = Array.from({ length: 100 }, (_, index) => {
const id = offset + index + 1;
const filename = `data_${id < 100 ? ('00' + id).slice(-3) : id}`;
return fetch(
`https://raw.githubusercontent.com/microsoft/fluentui-charting-contrib/refs/heads/main/apps/plotly_examples/src/data/${filename}.json`,
)
.then(response => {
if (response.status === 404) {
disableLoadMore = true;
return null;
}
return response.json();
})
.then(schema => ({ key: filename, schema }))
.catch(() => ({ key: filename, schema: {} }));
});
loadedSchemas.current.push(...(await Promise.all(promises)).filter(item => item.schema !== null));
setLoadingState('loaded');
setLoadMoreDisabled(disableLoadMore);
}, []);

React.useEffect(() => {
loadSchemas('initial');
}, [loadSchemas]);

const getSchemaByKey = React.useCallback(
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
(key: string): any => {
Expand All @@ -226,23 +223,32 @@ export const DeclarativeChartBasicExample = (): JSXElement => {
);

React.useEffect(() => {
if (showMore && (isLoading || loadedSchemas.current.length === 0)) {
setOptions([]);
setSelectedOptions([]);
setDropdownValue('');
setSelectedLegends('');
if (showMore) {
if (loadingState === 'initial' || loadedSchemas.current.length === 0) {
setOptions([]);
setSelectedOptions([]);
setDropdownValue('');
setSelectedLegends('');
} else if (loadingState === 'loaded') {
const _options = loadedSchemas.current.map(schema => ({ key: schema.key, text: schema.key }));
setOptions(_options);
if (!dropdownValue.includes('data_')) {
setSelectedOptions([_options[0].key]);
setDropdownValue(_options[0].text);
const selectedPlotlySchema = getSchemaByKey(_options[0].key);
const { selectedLegends: _selectedLegends } = selectedPlotlySchema;
setSelectedLegends(_selectedLegends ? JSON.stringify(_selectedLegends) : '');
}
}
} else {
const _options = showMore
? loadedSchemas.current.map(schema => ({ key: schema.key, text: schema.key }))
: DEFAULT_OPTIONS;
setOptions(_options);
setSelectedOptions([_options[0].key]);
setDropdownValue(_options[0].text);
const selectedPlotlySchema = getSchemaByKey(_options[0].key);
setOptions(DEFAULT_OPTIONS);
setSelectedOptions([DEFAULT_OPTIONS[0].key]);
setDropdownValue(DEFAULT_OPTIONS[0].text);
const selectedPlotlySchema = getSchemaByKey(DEFAULT_OPTIONS[0].key);
const { selectedLegends: _selectedLegends } = selectedPlotlySchema;
setSelectedLegends(_selectedLegends ? JSON.stringify(_selectedLegends) : '');
}
}, [showMore, isLoading, getSchemaByKey]);
}, [showMore, loadingState, dropdownValue, getSchemaByKey]);

const onSwitchDataChange = React.useCallback((ev: React.ChangeEvent<HTMLInputElement>) => {
setShowMore(ev.currentTarget.checked);
Expand Down Expand Up @@ -293,7 +299,7 @@ export const DeclarativeChartBasicExample = (): JSXElement => {

const renderDeclarativeChart = React.useCallback(() => {
if (showMore) {
if (isLoading) {
if (loadingState === 'initial') {
return <Spinner label="Loading..." />;
} else if (loadedSchemas.current.length === 0) {
return <div>More examples could not be loaded.</div>;
Expand Down Expand Up @@ -325,7 +331,7 @@ export const DeclarativeChartBasicExample = (): JSXElement => {
);
}, [
showMore,
isLoading,
loadingState,
selectedOptions,
selectedLegends,
getSchemaByKey,
Expand All @@ -336,7 +342,7 @@ export const DeclarativeChartBasicExample = (): JSXElement => {
return (
<div>
<Switch checked={showMore} onChange={onSwitchDataChange} label={showMore ? 'Show more' : 'Show few'} />
<div style={{ display: 'flex', flexDirection: 'row', gap: '10px' }}>
<div style={{ display: 'flex', flexDirection: 'row', gap: '10px', alignItems: 'end' }}>
<Field label="Select a schema">
<Dropdown
value={dropdownValue}
Expand All @@ -351,6 +357,17 @@ export const DeclarativeChartBasicExample = (): JSXElement => {
))}
</Dropdown>
</Field>
{showMore && (
<div>
<Button
icon={loadingState === 'loaded' ? undefined : <Spinner size="tiny" />}
onClick={() => loadSchemas()}
disabledFocusable={loadingState !== 'loaded' || isLoadMoreDisabled}
>
{loadingState === 'loaded' ? 'Load more' : 'Loading'}
</Button>
</div>
)}
<Field label="Select a color palette">
<Dropdown
value={fluentDataVizColorPalette}
Expand Down