mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-08-10 19:03:17 +02:00
Collapsible headers
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import { PanelSettings } from '../../models/PanelSettings';
|
||||
import { Collapsible } from './Collapsible';
|
||||
import { CustomScript } from './CustomScript';
|
||||
import { DateAction } from './DateAction';
|
||||
import { Icon } from './Icon';
|
||||
import { PublishAction } from './PublishAction';
|
||||
import { SlugAction } from './SlugAction';
|
||||
|
||||
@@ -19,22 +19,22 @@ export const Actions: React.FunctionComponent<IActionsProps> = (props: React.Pro
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`section article__actions`}>
|
||||
<h3><Icon name={`rocket`} /> Actions</h3>
|
||||
<Collapsible title="Actions">
|
||||
<div className={`article__actions`}>
|
||||
{ metadata && metadata.title && <SlugAction value={metadata.title} crntValue={metadata.slug} slugOpts={settings.slug} /> }
|
||||
|
||||
{ metadata && metadata.title && <SlugAction value={metadata.title} crntValue={metadata.slug} slugOpts={settings.slug} /> }
|
||||
|
||||
<DateAction />
|
||||
<DateAction />
|
||||
|
||||
{ metadata && typeof metadata.draft !== undefined && <PublishAction draft={metadata.draft} />}
|
||||
{ metadata && typeof metadata.draft !== undefined && <PublishAction draft={metadata.draft} />}
|
||||
|
||||
{
|
||||
(settings && settings.scripts && settings.scripts.length > 0) && (
|
||||
settings.scripts.map((value) => (
|
||||
<CustomScript key={value.title.replace(/ /g, '')} {...value} />
|
||||
))
|
||||
)
|
||||
}
|
||||
</div>
|
||||
{
|
||||
(settings && settings.scripts && settings.scripts.length > 0) && (
|
||||
settings.scripts.map((value) => (
|
||||
<CustomScript key={value.title.replace(/ /g, '')} {...value} />
|
||||
))
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</Collapsible>
|
||||
);
|
||||
};
|
||||
@@ -10,9 +10,7 @@ export interface IArticleDetailsProps {
|
||||
}
|
||||
|
||||
export const ArticleDetails: React.FunctionComponent<IArticleDetailsProps> = ({details}: React.PropsWithChildren<IArticleDetailsProps>) => {
|
||||
|
||||
console.log(details);
|
||||
|
||||
|
||||
if (!details || (details.headings === undefined && details.paragraphs === undefined)) {
|
||||
return null;
|
||||
}
|
||||
@@ -21,7 +19,7 @@ export const ArticleDetails: React.FunctionComponent<IArticleDetailsProps> = ({d
|
||||
<div className={`seo__status__details valid`}>
|
||||
<h4>More details</h4>
|
||||
|
||||
<VsTable>
|
||||
<VsTable bordered>
|
||||
<VsTableHeader slot="header">
|
||||
<VsTableHeaderCell>Type</VsTableHeaderCell>
|
||||
<VsTableHeaderCell>Total</VsTableHeaderCell>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import * as React from 'react';
|
||||
import { VsCollapsible } from './VscodeComponents';
|
||||
|
||||
export interface ICollapsibleProps {
|
||||
title: string;
|
||||
sendUpdate?: (open: boolean) => void;
|
||||
}
|
||||
|
||||
export const Collapsible: React.FunctionComponent<ICollapsibleProps> = ({children, title, sendUpdate}: React.PropsWithChildren<ICollapsibleProps>) => {
|
||||
const [ isOpen, setIsOpen ] = React.useState(true);
|
||||
|
||||
// This is a work around for a lit-element issue of duplicate slot names
|
||||
const triggerClick = (e: React.MouseEvent<HTMLElement>) => {
|
||||
if ((e.target as any).tagName === 'VSCODE-COLLAPSIBLE') {
|
||||
setIsOpen(prev => {
|
||||
if (sendUpdate) {
|
||||
sendUpdate(!prev);
|
||||
}
|
||||
return !prev;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<VsCollapsible title={title} onClick={triggerClick} open={isOpen}>
|
||||
<div className={`section collapsible__body`} slot="body">
|
||||
{children}
|
||||
</div>
|
||||
</VsCollapsible>
|
||||
);
|
||||
};
|
||||
@@ -24,7 +24,7 @@ export const SeoDetails: React.FunctionComponent<ISeoDetailsProps> = (props: Rea
|
||||
<div className={`seo__status__details ${validate()}`}>
|
||||
<h4>{title}</h4>
|
||||
|
||||
<VsTable>
|
||||
<VsTable {...{bordered:true}}>
|
||||
<VsTableHeader slot="header">
|
||||
<VsTableHeaderCell className={validate()}>{valueTitle}</VsTableHeaderCell>
|
||||
<VsTableHeaderCell>Recommended</VsTableHeaderCell>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export interface ISeoKeywordsProps {
|
||||
keywords: string[] | null;
|
||||
}
|
||||
|
||||
export const SeoKeywords: React.FunctionComponent<ISeoKeywordsProps> = ({keywords}: React.PropsWithChildren<ISeoKeywordsProps>) => {
|
||||
return (
|
||||
<div className={`seo__status__keywords`}>
|
||||
<h4>Keywords</h4>
|
||||
|
||||
<p>{keywords?.join(',')}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,8 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import { SEO } from '../../models/PanelSettings';
|
||||
import { ArticleDetails } from './ArticleDetails';
|
||||
import { Icon } from './Icon';
|
||||
import { Collapsible } from './Collapsible';
|
||||
import { SeoDetails } from './SeoDetails';
|
||||
import { SeoKeywords } from './SeoKeywords';
|
||||
|
||||
export interface ISeoStatusProps {
|
||||
seo: SEO;
|
||||
@@ -12,6 +13,7 @@ export interface ISeoStatusProps {
|
||||
export const SeoStatus: React.FunctionComponent<ISeoStatusProps> = (props: React.PropsWithChildren<ISeoStatusProps>) => {
|
||||
const { data, seo } = props;
|
||||
const { title } = data;
|
||||
const [ isOpen, setIsOpen ] = React.useState(true);
|
||||
|
||||
const { descriptionField } = seo;
|
||||
|
||||
@@ -19,27 +21,39 @@ export const SeoStatus: React.FunctionComponent<ISeoStatusProps> = (props: React
|
||||
return null;
|
||||
}
|
||||
|
||||
const renderContent = () => {
|
||||
console.log(`render`);
|
||||
|
||||
if (!isOpen) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ (title && seo.title > 0) && <SeoDetails title="Title" valueTitle="Length" allowedLength={seo.title} value={title.length} /> }
|
||||
|
||||
{ (data[descriptionField] && seo.description > 0) && <SeoDetails title="Description" valueTitle="Length" allowedLength={seo.description} value={data[descriptionField].length} /> }
|
||||
|
||||
{
|
||||
seo.content > 0 && data?.articleDetails?.wordCount && (
|
||||
<SeoDetails title="Article length"
|
||||
valueTitle="Words"
|
||||
allowedLength={seo.content}
|
||||
value={data?.articleDetails?.wordCount}
|
||||
noValidation />
|
||||
)
|
||||
}
|
||||
|
||||
<SeoKeywords keywords={data?.keywords} />
|
||||
|
||||
<ArticleDetails details={data.articleDetails} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="section seo__status">
|
||||
<h3>
|
||||
<Icon name="search" /> SEO Status
|
||||
</h3>
|
||||
|
||||
{ (title && seo.title > 0) && <SeoDetails title="Title" valueTitle="Length" allowedLength={seo.title} value={title.length} /> }
|
||||
|
||||
{ (data[descriptionField] && seo.description > 0) && <SeoDetails title="Description" valueTitle="Length" allowedLength={seo.description} value={data[descriptionField].length} /> }
|
||||
|
||||
{
|
||||
seo.content > 0 && data?.articleDetails?.wordCount && (
|
||||
<SeoDetails title="Article length"
|
||||
valueTitle="Words"
|
||||
allowedLength={seo.content}
|
||||
value={data?.articleDetails?.wordCount}
|
||||
noValidation />
|
||||
)
|
||||
}
|
||||
|
||||
<ArticleDetails details={data.articleDetails} />
|
||||
</div>
|
||||
<Collapsible title="SEO Status" sendUpdate={(value) => setIsOpen(value)}>
|
||||
{ renderContent() }
|
||||
</Collapsible>
|
||||
);
|
||||
};
|
||||
@@ -5,4 +5,5 @@ export const VsTableHeader = wrapWc(`vscode-table-header`);
|
||||
export const VsTableHeaderCell = wrapWc(`vscode-table-header-cell`);
|
||||
export const VsTableBody = wrapWc(`vscode-table-body`);
|
||||
export const VsTableRow = wrapWc(`vscode-table-row`);
|
||||
export const VsTableCell = wrapWc(`vscode-table-cell`);
|
||||
export const VsTableCell = wrapWc(`vscode-table-cell`);
|
||||
export const VsCollapsible = wrapWc(`vscode-collapsible`);
|
||||
@@ -8,6 +8,7 @@ import '@bendera/vscode-webview-elements/dist/vscode-table-header-cell';
|
||||
import '@bendera/vscode-webview-elements/dist/vscode-table-body';
|
||||
import '@bendera/vscode-webview-elements/dist/vscode-table-row';
|
||||
import '@bendera/vscode-webview-elements/dist/vscode-table-cell';
|
||||
import '@bendera/vscode-webview-elements/dist/vscode-collapsible';
|
||||
|
||||
declare const acquireVsCodeApi: <T = unknown>() => {
|
||||
getState: () => T;
|
||||
|
||||
Reference in New Issue
Block a user