mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-05-16 14:25:44 +02:00
346 lines
13 KiB
TypeScript
346 lines
13 KiB
TypeScript
import * as React from 'react';
|
|
import { Messenger, messageHandler } from '@estruyf/vscode/dist/client';
|
|
import { DashboardMessage } from '../../DashboardMessage';
|
|
import { Settings } from '../../models/Settings';
|
|
import { Status } from '../../models/Status';
|
|
import { Step } from './Step';
|
|
import { useMemo, useState } from 'react';
|
|
import { Menu } from '@headlessui/react';
|
|
import { MenuItem } from '../Menu';
|
|
import { ContentFolder, Framework, StaticFolder, Template } from '../../../models';
|
|
import { ChevronDownIcon } from '@heroicons/react/outline';
|
|
import { FrameworkDetectors } from '../../../constants/FrameworkDetectors';
|
|
import { join } from 'path';
|
|
import useThemeColors from '../../hooks/useThemeColors';
|
|
import * as l10n from '@vscode/l10n';
|
|
import { LocalizationKey } from '../../../localization';
|
|
import { SelectItem } from './SelectItem';
|
|
import { Templates } from '../../../constants';
|
|
|
|
export interface IStepsToGetStartedProps {
|
|
settings: Settings;
|
|
}
|
|
|
|
const Folder = ({
|
|
wsFolder,
|
|
folder,
|
|
folders,
|
|
addFolder
|
|
}: {
|
|
wsFolder: string;
|
|
folder: string;
|
|
folders: ContentFolder[];
|
|
addFolder: (folder: string) => void;
|
|
}) => {
|
|
|
|
const isAdded = useMemo(
|
|
() => folders.find((f) => f.path.toLowerCase() === join(wsFolder, folder).toLowerCase()),
|
|
[folder, folders, wsFolder]
|
|
);
|
|
|
|
return (
|
|
<SelectItem
|
|
title={folder}
|
|
buttonTitle={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedButtonAddFolderTitle)}
|
|
isSelected={!!isAdded}
|
|
onClick={() => addFolder(folder)} />
|
|
);
|
|
};
|
|
|
|
export const StepsToGetStarted: React.FunctionComponent<IStepsToGetStartedProps> = ({
|
|
settings
|
|
}: React.PropsWithChildren<IStepsToGetStartedProps>) => {
|
|
const [framework, setFramework] = useState<string | null>(null);
|
|
const [taxImported, setTaxImported] = useState<boolean>(false);
|
|
const [templates, setTemplates] = useState<Template[]>([]);
|
|
const { getColors } = useThemeColors();
|
|
|
|
const frameworks: Framework[] = FrameworkDetectors.map((detector: any) => detector.framework);
|
|
|
|
const setFrameworkAndSendMessage = (framework: string) => {
|
|
setFramework(framework);
|
|
Messenger.send(DashboardMessage.setFramework, framework);
|
|
};
|
|
|
|
const addFolder = (folder: string) => {
|
|
Messenger.send(DashboardMessage.addFolder, folder);
|
|
};
|
|
|
|
const addAssetFolder = (folder: string | StaticFolder) => {
|
|
Messenger.send(DashboardMessage.addAssetsFolder, folder);
|
|
}
|
|
|
|
const triggerTemplate = (template: Template) => {
|
|
messageHandler.request<boolean>(DashboardMessage.triggerTemplate, template).then((result) => {
|
|
if (result) {
|
|
reload();
|
|
}
|
|
});
|
|
}
|
|
|
|
const reload = () => {
|
|
const crntState: any = Messenger.getState() || {};
|
|
|
|
Messenger.setState({
|
|
...crntState,
|
|
isWelcomeConfiguring: false
|
|
});
|
|
|
|
Messenger.send(DashboardMessage.reload);
|
|
};
|
|
|
|
const importTaxonomy = () => {
|
|
Messenger.send(DashboardMessage.importTaxonomy);
|
|
setTaxImported(true);
|
|
};
|
|
|
|
const crntTemplates = useMemo(() => {
|
|
if (!templates || templates.length === 0 || !settings.crntFramework) {
|
|
return [];
|
|
}
|
|
|
|
return templates.filter((t) => t.type === settings.crntFramework);
|
|
}, [templates, settings.crntFramework])
|
|
|
|
const steps = useMemo(() => (
|
|
[
|
|
{
|
|
id: `welcome-init`,
|
|
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedInitializeProjectName),
|
|
description: <>{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedInitializeProjectDescription)}</>,
|
|
show: true,
|
|
status: settings.initialized ? Status.Completed : Status.NotStarted,
|
|
onClick: settings.initialized
|
|
? undefined
|
|
: () => {
|
|
Messenger.send(DashboardMessage.initializeProject);
|
|
}
|
|
},
|
|
{
|
|
id: `welcome-framework`,
|
|
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedFrameworkName),
|
|
description: (
|
|
<div>
|
|
<div>
|
|
{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedFrameworkDescription)}
|
|
</div>
|
|
|
|
<Menu as="div" className="relative inline-block text-left mt-4">
|
|
<div>
|
|
<Menu.Button className={`group flex justify-center p-2 rounded-md border ${getColors(
|
|
'text-vulcan-500 hover:text-vulcan-600 dark:text-whisper-500 dark:hover:text-whisper-600 border-vulcan-400 dark:border-white',
|
|
'text-[var(--vscode-tab-inactiveForeground)] hover:text-[var(--vscode-tab-activeForeground)]'
|
|
)
|
|
}`}>
|
|
{framework ? framework : l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedFrameworkSelect)}
|
|
<ChevronDownIcon
|
|
className={`flex-shrink-0 -mr-1 ml-1 h-5 w-5 ${getColors(
|
|
'text-gray-400 group-hover:text-gray-500 dark:text-whisper-600 dark:group-hover:text-whisper-700',
|
|
''
|
|
)
|
|
}`}
|
|
aria-hidden="true"
|
|
/>
|
|
</Menu.Button>
|
|
</div>
|
|
|
|
<Menu.Items
|
|
className={`w-40 origin-top-left absolute left-0 z-10 mt-2 rounded-md shadow-2xl ring-1 ring-opacity-5 focus:outline-none text-sm max-h-96 overflow-auto ${getColors(
|
|
'bg-white dark:bg-vulcan-500 ring-vulcan-400 dark:ring-white',
|
|
'bg-[var(--vscode-sideBar-background)] ring-[var(--frontmatter-border)]'
|
|
)
|
|
}`}
|
|
>
|
|
<div className="py-1">
|
|
<MenuItem
|
|
title={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedFrameworkSelectOther)}
|
|
value={`other`}
|
|
isCurrent={!framework}
|
|
onClick={(value: string) => setFrameworkAndSendMessage(value)}
|
|
/>
|
|
|
|
<hr className={`border-[var(--frontmatter-border)]`} />
|
|
|
|
{frameworks.map((f) => (
|
|
<MenuItem
|
|
key={f.name}
|
|
title={f.name}
|
|
value={f.name}
|
|
isCurrent={f.name === framework}
|
|
onClick={(value: string) => setFrameworkAndSendMessage(value)}
|
|
/>
|
|
))}
|
|
</div>
|
|
</Menu.Items>
|
|
</Menu>
|
|
</div>
|
|
),
|
|
show: true,
|
|
status: settings.crntFramework ? Status.Completed : Status.NotStarted,
|
|
onClick: undefined
|
|
},
|
|
{
|
|
id: `welcome-template`,
|
|
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedTemplateName),
|
|
description: (
|
|
<div className='mt-4'>
|
|
<div className="text-sm">{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedTemplateDescription)}</div>
|
|
<div className="mt-1 space-y-1">
|
|
{
|
|
crntTemplates && (crntTemplates || []).map(template => (
|
|
<SelectItem
|
|
key={template.name.toLowerCase().replace(/ /g, '-')}
|
|
title={template.name}
|
|
icon='add'
|
|
buttonTitle={template.name}
|
|
isSelected={false}
|
|
onClick={() => triggerTemplate(template)} />
|
|
))
|
|
}
|
|
</div>
|
|
</div>
|
|
),
|
|
show: (crntTemplates || []).length > 0,
|
|
status: Status.Active,
|
|
},
|
|
{
|
|
id: `welcome-assets`,
|
|
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderName),
|
|
description: (
|
|
<div className='mt-4'>
|
|
<div className="text-sm">{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderDescription)}</div>
|
|
<div className="mt-1 space-y-1">
|
|
<SelectItem
|
|
title={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderPublicTitle)}
|
|
buttonTitle={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderPublicTitle)}
|
|
isSelected={settings.staticFolder === "public"}
|
|
onClick={() => addAssetFolder(`public`)} />
|
|
|
|
<SelectItem
|
|
title={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderAssetsTitle)}
|
|
buttonTitle={l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderAssetsTitle)}
|
|
isSelected={settings.staticFolder === "src/assets"}
|
|
onClick={() => addAssetFolder({
|
|
"path": "src/assets",
|
|
"relative": true
|
|
})} />
|
|
|
|
<p className='text-sm'>
|
|
<b>{l10n.t(LocalizationKey.commonInformation)}</b>: {l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedAssetsFolderOtherDescription)}</p>
|
|
</div>
|
|
</div>
|
|
),
|
|
show: settings.crntFramework === 'astro' || framework === 'astro',
|
|
status: settings.initialized && settings.staticFolder && settings.staticFolder !== "/" ? Status.Completed : Status.NotStarted,
|
|
},
|
|
{
|
|
id: `welcome-content-folders`,
|
|
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersName),
|
|
description: (
|
|
<>
|
|
<p>
|
|
{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersDescription)}
|
|
</p>
|
|
|
|
{settings?.dashboardState?.welcome?.contentFolders?.length > 0 && (
|
|
<div className="mt-4">
|
|
<div className="text-sm">{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersLabel)}</div>
|
|
<div className="mt-1 space-y-1">
|
|
{settings?.dashboardState?.welcome?.contentFolders?.map((folder: string) => (
|
|
<Folder
|
|
key={folder}
|
|
folder={folder}
|
|
addFolder={addFolder}
|
|
wsFolder={settings.wsFolder}
|
|
folders={settings.contentFolders}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<p className={`mt-4 ${getColors('text-vulcan-300 dark:text-gray-400', '')}`}>
|
|
<b>{l10n.t(LocalizationKey.commonInformation)}</b>: {l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedContentFoldersInformationDescription)}.
|
|
</p>
|
|
</>
|
|
),
|
|
show: true,
|
|
status:
|
|
settings.contentFolders && settings.contentFolders.length > 0
|
|
? Status.Completed
|
|
: Status.NotStarted
|
|
},
|
|
{
|
|
id: `welcome-import`,
|
|
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedTagsName),
|
|
description: <>{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedTagsDescription)}</>,
|
|
show: true,
|
|
status: taxImported ? Status.Completed : Status.NotStarted,
|
|
onClick:
|
|
settings.contentFolders && settings.contentFolders.length > 0 ? importTaxonomy : undefined
|
|
},
|
|
{
|
|
id: `welcome-show-dashboard`,
|
|
name: l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedShowDashboardName),
|
|
description: <>{l10n.t(LocalizationKey.dashboardStepsStepsToGetStartedShowDashboardDescription)}</>,
|
|
show: true,
|
|
status:
|
|
settings.initialized && settings.contentFolders && settings.contentFolders.length > 0
|
|
? Status.Active
|
|
: Status.NotStarted,
|
|
onClick:
|
|
settings.initialized && settings.contentFolders && settings.contentFolders.length > 0
|
|
? reload
|
|
: undefined
|
|
}
|
|
]
|
|
), [settings, framework, taxImported, templates]);
|
|
|
|
React.useEffect(() => {
|
|
if (settings.crntFramework || settings.framework?.name) {
|
|
setFramework(settings.crntFramework || settings.framework?.name || null);
|
|
}
|
|
}, [settings.crntFramework, settings.framework]);
|
|
|
|
React.useEffect(() => {
|
|
const fetchTemplates = async () => {
|
|
try {
|
|
const response = await fetch(Templates.url);
|
|
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
setTemplates(data);
|
|
}
|
|
} catch (e) {
|
|
setTemplates([]);
|
|
}
|
|
};
|
|
|
|
fetchTemplates();
|
|
}, []);
|
|
|
|
return (
|
|
<nav aria-label="Progress">
|
|
<ol role="list">
|
|
{steps.map((step, stepIdx) => (
|
|
step.show && (
|
|
<li
|
|
key={step.id}
|
|
className={`${stepIdx !== steps.length - 1 ? 'pb-10' : ''} relative`}
|
|
data-test={step.id}
|
|
>
|
|
<Step
|
|
name={step.name}
|
|
description={step.description}
|
|
status={step.status}
|
|
showLine={stepIdx !== steps.length - 1}
|
|
onClick={step.onClick}
|
|
/>
|
|
</li>
|
|
)
|
|
))}
|
|
</ol>
|
|
</nav>
|
|
);
|
|
};
|