forked from iarv/vscode-front-matter
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2ae94df34 | ||
|
|
f799613b1a | ||
|
|
3f057a01d8 | ||
|
|
3ad5136735 | ||
|
|
e201ce6f83 | ||
|
|
383a3a7d4c | ||
|
|
8261f1de1b | ||
|
|
5b38e6fa56 | ||
|
|
717f34bc85 | ||
|
|
47fb2a90a9 | ||
|
|
85a7221895 |
3
.github/workflows/release-beta.yml
vendored
3
.github/workflows/release-beta.yml
vendored
@@ -25,3 +25,6 @@ jobs:
|
||||
- name: Publish
|
||||
run: npx vsce publish -p ${{ secrets.VSCE_PAT }} --baseImagesUrl https://raw.githubusercontent.com/estruyf/vscode-front-matter/dev
|
||||
|
||||
- name: Publish to open-vsx.org
|
||||
run: npx ovsx publish -p ${{ secrets.OPEN_VSX_PAT }}
|
||||
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -26,3 +26,5 @@ jobs:
|
||||
- name: Publish
|
||||
run: npx vsce publish -p ${{ secrets.VSCE_PAT }}
|
||||
|
||||
- name: Publish to open-vsx.org
|
||||
run: npx ovsx publish -p ${{ secrets.OPEN_VSX_PAT }}
|
||||
@@ -1,5 +1,14 @@
|
||||
# Change Log
|
||||
|
||||
## [5.5.0] - 2021-11-15
|
||||
|
||||
As from this version onwards, the extension will be published to [open-vsx.org](https://open-vsx.org/).
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
- [#173](https://github.com/estruyf/vscode-front-matter/issues/173): Allow to specify your own sorting for the content dashboard
|
||||
- [#174](https://github.com/estruyf/vscode-front-matter/issues/174): Added option to exclude sub-directories from page/markdown content retrieval
|
||||
|
||||
## [5.4.0] - 2021-11-05
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vscode-front-matter-beta",
|
||||
"version": "5.4.0",
|
||||
"version": "5.5.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
51
package.json
51
package.json
@@ -3,7 +3,7 @@
|
||||
"displayName": "Front Matter",
|
||||
"description": "An essential Visual Studio Code extension when you want to manage the markdown pages of your static site like: Hugo, Jekyll, Hexo, NextJs, Gatsby, and many more...",
|
||||
"icon": "assets/frontmatter-teal-128x128.png",
|
||||
"version": "5.4.0",
|
||||
"version": "5.5.0",
|
||||
"preview": false,
|
||||
"publisher": "eliostruyf",
|
||||
"galleryBanner": {
|
||||
@@ -154,6 +154,11 @@
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "Path of the folder"
|
||||
},
|
||||
"excludeSubdir": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Exclude sub-directories"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -170,6 +175,48 @@
|
||||
"markdownDescription": "Specify the folder name where all your assets are located. For instance in Hugo this is the `static` folder. [Check in the docs](https://frontmatter.codes/docs/settings#frontmatter.content.publicfolder)",
|
||||
"scope": "Content"
|
||||
},
|
||||
"frontMatter.content.sorting": {
|
||||
"type": "object",
|
||||
"default": [],
|
||||
"markdownDescription": "Define the sorting options for your dashboard content. [Check in the docs](https://frontmatter.codes/docs/settings#frontMatter.content.sorting)",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Name of the sorting label"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the metadata field to sort by"
|
||||
},
|
||||
"order": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"asc",
|
||||
"desc"
|
||||
],
|
||||
"description": "Order of the sorting"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"default": "string",
|
||||
"enum": [
|
||||
"string",
|
||||
"date"
|
||||
],
|
||||
"description": "Type of the field value"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"title",
|
||||
"name",
|
||||
"order"
|
||||
]
|
||||
},
|
||||
"scope": "Content"
|
||||
},
|
||||
"frontMatter.custom.scripts": {
|
||||
"type": "array",
|
||||
"default": [],
|
||||
@@ -792,4 +839,4 @@
|
||||
"dependencies": {
|
||||
"@docsearch/js": "^3.0.0-alpha.40"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import { SETTINGS_CONTENT_STATIC_FOLDER, SETTING_DATE_FIELD, SETTING_SEO_DESCRIPTION_FIELD, SETTINGS_DASHBOARD_OPENONSTART, SETTINGS_DASHBOARD_MEDIA_SNIPPET, SETTING_TAXONOMY_CONTENT_TYPES, DefaultFields, HOME_PAGE_NAVIGATION_ID, ExtensionState, COMMAND_NAME, SETTINGS_FRAMEWORK_ID, SETTINGS_CONTENT_DRAFT_FIELD } from '../constants';
|
||||
import { SETTINGS_CONTENT_STATIC_FOLDER, SETTING_DATE_FIELD, SETTING_SEO_DESCRIPTION_FIELD, SETTINGS_DASHBOARD_OPENONSTART, SETTINGS_DASHBOARD_MEDIA_SNIPPET, SETTING_TAXONOMY_CONTENT_TYPES, DefaultFields, HOME_PAGE_NAVIGATION_ID, ExtensionState, COMMAND_NAME, SETTINGS_FRAMEWORK_ID, SETTINGS_CONTENT_DRAFT_FIELD, SETTINGS_CONTENT_SORTING } from '../constants';
|
||||
import { ArticleHelper } from './../helpers/ArticleHelper';
|
||||
import { basename, dirname, extname, join, parse } from "path";
|
||||
import { existsSync, readdirSync, statSync, unlinkSync, writeFileSync } from "fs";
|
||||
import { commands, Uri, ViewColumn, Webview, WebviewPanel, window, workspace, env, Position } from "vscode";
|
||||
import { Settings as SettingsHelper } from '../helpers';
|
||||
import { DraftField, Framework, TaxonomyType } from '../models';
|
||||
import { DraftField, Framework, SortingSetting, TaxonomyType } from '../models';
|
||||
import { Folders } from './Folders';
|
||||
import { DashboardCommand } from '../dashboardWebView/DashboardCommand';
|
||||
import { DashboardMessage } from '../dashboardWebView/DashboardMessage';
|
||||
@@ -39,7 +39,7 @@ export class Dashboard {
|
||||
return Dashboard._viewData;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Init the dashboard
|
||||
*/
|
||||
public static async init() {
|
||||
@@ -192,6 +192,11 @@ export class Dashboard {
|
||||
case DashboardMessage.setFramework:
|
||||
Dashboard.setFramework(msg?.data);
|
||||
break;
|
||||
case DashboardMessage.setState:
|
||||
if (msg?.data?.key && msg?.data?.value) {
|
||||
Extension.getInstance().setState(msg?.data?.key, msg?.data?.value, "workspace");
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -280,9 +285,13 @@ export class Dashboard {
|
||||
mediaSnippet: SettingsHelper.get<string[]>(SETTINGS_DASHBOARD_MEDIA_SNIPPET) || [],
|
||||
contentTypes: SettingsHelper.get(SETTING_TAXONOMY_CONTENT_TYPES) || [],
|
||||
draftField: SettingsHelper.get<DraftField>(SETTINGS_CONTENT_DRAFT_FIELD),
|
||||
contentFolders: Folders.get().map(f => f.path),
|
||||
customSorting: SettingsHelper.get<SortingSetting[]>(SETTINGS_CONTENT_SORTING),
|
||||
contentFolders: Folders.get(),
|
||||
crntFramework: SettingsHelper.get<string>(SETTINGS_FRAMEWORK_ID),
|
||||
framework: (!isInitialized && wsFolder) ? FrameworkDetector.get(wsFolder.fsPath) : null,
|
||||
dashboardState: {
|
||||
sorting: await ext.getState<ViewType | undefined>(ExtensionState.Dashboard.Sorting, "workspace")
|
||||
}
|
||||
} as Settings
|
||||
});
|
||||
}
|
||||
|
||||
@@ -210,8 +210,8 @@ export class Folders {
|
||||
if (projectStart) {
|
||||
projectStart = projectStart.replace(/\\/g, '/');
|
||||
projectStart = projectStart.startsWith('/') ? projectStart.substr(1) : projectStart;
|
||||
const mdFiles = await workspace.findFiles(join(projectStart, '**/*.md'));
|
||||
const mdxFiles = await workspace.findFiles(join(projectStart, '**/*.mdx'));
|
||||
const mdFiles = await workspace.findFiles(join(projectStart, folder.excludeSubdir ? '/' : '**/', '*.md'));
|
||||
const mdxFiles = await workspace.findFiles(join(projectStart, folder.excludeSubdir ? '/' : '**/', '*.mdx'));
|
||||
let files = [...mdFiles, ...mdxFiles];
|
||||
if (files) {
|
||||
let fileStats: FileInfo[] = [];
|
||||
@@ -263,7 +263,7 @@ export class Folders {
|
||||
const folders: ContentFolder[] = Settings.get(SETTINGS_CONTENT_PAGE_FOLDERS) as ContentFolder[];
|
||||
|
||||
return folders.map(folder => ({
|
||||
title: folder.title,
|
||||
...folder,
|
||||
path: Folders.absWsFolder(folder, wsFolder)
|
||||
}));
|
||||
}
|
||||
@@ -274,10 +274,12 @@ export class Folders {
|
||||
*/
|
||||
private static async update(folders: ContentFolder[]) {
|
||||
const wsFolder = Folders.getWorkspaceFolder();
|
||||
|
||||
let folderDetails = folders.map(folder => ({
|
||||
title: folder.title,
|
||||
...folder,
|
||||
path: Folders.relWsFolder(folder, wsFolder)
|
||||
}));
|
||||
|
||||
await Settings.update(SETTINGS_CONTENT_PAGE_FOLDERS, folderDetails, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,4 +5,8 @@ export const ExtensionState = {
|
||||
Version: `frontMatter:Version`,
|
||||
SettingPromoted: `frontMatter:Settings:Promoted`,
|
||||
MoveTemplatesFolder: `frontMatter:Templates:Move`,
|
||||
|
||||
Dashboard: {
|
||||
Sorting: `frontMatter:Dashboard:Sorting`,
|
||||
}
|
||||
};
|
||||
@@ -40,6 +40,7 @@ export const SETTINGS_CONTENT_PAGE_FOLDERS = "content.pageFolders";
|
||||
export const SETTINGS_CONTENT_STATIC_FOLDER = "content.publicFolder";
|
||||
export const SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT = "content.fmHighlight";
|
||||
export const SETTINGS_CONTENT_DRAFT_FIELD = "content.draftField";
|
||||
export const SETTINGS_CONTENT_SORTING = "content.sorting";
|
||||
|
||||
export const SETTINGS_DASHBOARD_OPENONSTART = "dashboard.openOnStart";
|
||||
export const SETTINGS_DASHBOARD_MEDIA_SNIPPET = "dashboard.mediaSnippet";
|
||||
|
||||
@@ -19,4 +19,5 @@ export enum DashboardMessage {
|
||||
updateMediaMetadata = 'updateMediaMetadata',
|
||||
createMediaFolder = 'createMediaFolder',
|
||||
setFramework = 'setFramework',
|
||||
setState = 'setState',
|
||||
}
|
||||
@@ -31,9 +31,10 @@ export const Breadcrumb: React.FunctionComponent<IBreadcrumbProps> = (props: Rea
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
1
|
||||
for (let i = 0; i < contentFolders.length; i++) {
|
||||
const contentFolder = parseWinPath(contentFolders[i]) as string;
|
||||
const folder = contentFolders[i];
|
||||
const contentFolder = parseWinPath(folder.path) as string;
|
||||
const relContentPath = folderPath.replace(contentFolder, '');
|
||||
return relContentPath.length > 1 && folderPath.startsWith(contentFolder);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { XCircleIcon } from '@heroicons/react/solid';
|
||||
import * as React from 'react';
|
||||
import { useRecoilValue, useResetRecoilState } from 'recoil';
|
||||
import { SortingSelector, FolderSelector, TagSelector, CategorySelector, SortingAtom, DEFAULT_SORTING_OPTION, FolderAtom, DEFAULT_FOLDER_STATE, TagAtom, CategoryAtom, DEFAULT_TAG_STATE, DEFAULT_CATEGORY_STATE } from '../../state';
|
||||
import { FolderSelector, TagSelector, CategorySelector, SortingAtom, FolderAtom, DEFAULT_FOLDER_STATE, TagAtom, CategoryAtom, DEFAULT_TAG_STATE, DEFAULT_CATEGORY_STATE } from '../../state';
|
||||
|
||||
import { DefaultValue } from 'recoil';
|
||||
|
||||
@@ -17,7 +17,6 @@ export interface IClearFiltersProps {}
|
||||
export const ClearFilters: React.FunctionComponent<IClearFiltersProps> = (props: React.PropsWithChildren<IClearFiltersProps>) => {
|
||||
const [ show, setShow ] = React.useState(false);
|
||||
|
||||
const sorting = useRecoilValue(SortingSelector);
|
||||
const folder = useRecoilValue(FolderSelector);
|
||||
const tag = useRecoilValue(TagSelector);
|
||||
const category = useRecoilValue(CategorySelector);
|
||||
@@ -36,19 +35,19 @@ export const ClearFilters: React.FunctionComponent<IClearFiltersProps> = (props:
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (sorting !== DEFAULT_SORTING_OPTION || folder !== DEFAULT_FOLDER_STATE || tag !== DEFAULT_TAG_STATE || category !== DEFAULT_CATEGORY_STATE) {
|
||||
if (folder !== DEFAULT_FOLDER_STATE || tag !== DEFAULT_TAG_STATE || category !== DEFAULT_CATEGORY_STATE) {
|
||||
setShow(true);
|
||||
} else {
|
||||
setShow(false);
|
||||
}
|
||||
}, [sorting, folder, tag, category]);
|
||||
}, [folder, tag, category]);
|
||||
|
||||
if (!show) return null;
|
||||
|
||||
return (
|
||||
<button className="flex items-center hover:text-teal-600" onClick={reset} title={`Clear filters, grouping, and sorting`}>
|
||||
<XCircleIcon className={`inline-block w-5 h-5 mr-1`} /><span>Clear</span>
|
||||
<span className={`sr-only`}> filters, grouping, and sorting</span>
|
||||
<span className={`sr-only`}> filters and grouping</span>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
@@ -1,19 +1,19 @@
|
||||
import { Menu } from '@headlessui/react';
|
||||
import * as React from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { FolderAtom } from '../../state';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { FolderAtom, SettingsSelector } from '../../state';
|
||||
import { MenuButton, MenuItem, MenuItems } from '../Menu';
|
||||
|
||||
export interface IFoldersProps {
|
||||
folders: string[];
|
||||
}
|
||||
export interface IFoldersProps {}
|
||||
|
||||
const DEFAULT_TYPE = "All types";
|
||||
|
||||
export const Folders: React.FunctionComponent<IFoldersProps> = ({folders}: React.PropsWithChildren<IFoldersProps>) => {
|
||||
export const Folders: React.FunctionComponent<IFoldersProps> = ({}: React.PropsWithChildren<IFoldersProps>) => {
|
||||
const [ crntFolder, setCrntFolder ] = useRecoilState(FolderAtom);
|
||||
const settings = useRecoilValue(SettingsSelector);
|
||||
const contentFolders = settings?.contentFolders || [];
|
||||
|
||||
if (folders.length <= 1) {
|
||||
if (contentFolders.length <= 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -29,12 +29,12 @@ export const Folders: React.FunctionComponent<IFoldersProps> = ({folders}: React
|
||||
isCurrent={!crntFolder}
|
||||
onClick={(value) => setCrntFolder(value)} />
|
||||
|
||||
{folders.map((option) => (
|
||||
{contentFolders.map((option) => (
|
||||
<MenuItem
|
||||
key={option}
|
||||
title={option}
|
||||
value={option}
|
||||
isCurrent={option === crntFolder}
|
||||
key={option.title}
|
||||
title={option.title}
|
||||
value={option.title}
|
||||
isCurrent={option.title === crntFolder}
|
||||
onClick={(value) => setCrntFolder(value)} />
|
||||
))}
|
||||
</MenuItems>
|
||||
|
||||
@@ -98,7 +98,7 @@ export const Header: React.FunctionComponent<IHeaderProps> = ({totalPages, folde
|
||||
<div className={`py-4 px-5 w-full flex items-center justify-between lg:justify-end space-x-4 lg:space-x-6 xl:space-x-8 bg-gray-200 border-b border-gray-300 dark:bg-vulcan-400 dark:border-vulcan-100`}>
|
||||
<ClearFilters />
|
||||
|
||||
<Folders folders={folders || []} />
|
||||
<Folders />
|
||||
|
||||
<Filter label={`Tag`} activeItem={crntTag} items={settings?.tags || []} onClick={(value) => setCrntTag(value)} />
|
||||
|
||||
|
||||
@@ -1,37 +1,64 @@
|
||||
import { Messenger } from '@estruyf/vscode/dist/client';
|
||||
import { Menu } from '@headlessui/react';
|
||||
import * as React from 'react';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { ExtensionState } from '../../../constants';
|
||||
import { SortOrder, SortType } from '../../../models';
|
||||
import { SortOption } from '../../constants/SortOption';
|
||||
import { SearchSelector, SortingAtom } from '../../state';
|
||||
import { DashboardMessage } from '../../DashboardMessage';
|
||||
import { SortingOption } from '../../models/SortingOption';
|
||||
import { SearchSelector, SettingsSelector, SortingAtom } from '../../state';
|
||||
import { MenuButton, MenuItem, MenuItems } from '../Menu';
|
||||
|
||||
export interface ISortingProps {}
|
||||
|
||||
export const sortOptions = [
|
||||
{ name: "Last modified", id: SortOption.LastModified },
|
||||
{ name: "By filename (asc)", id: SortOption.FileNameAsc },
|
||||
{ name: "By filename (desc)", id: SortOption.FileNameDesc },
|
||||
export const sortOptions: SortingOption[] = [
|
||||
{ name: "Last modified", id: SortOption.LastModified, order: SortOrder.desc, type: SortType.string },
|
||||
{ name: "By filename (asc)", id: SortOption.FileNameAsc, order: SortOrder.asc, type: SortType.string },
|
||||
{ name: "By filename (desc)", id: SortOption.FileNameDesc, order: SortOrder.desc, type: SortType.string },
|
||||
];
|
||||
|
||||
export const Sorting: React.FunctionComponent<ISortingProps> = ({}: React.PropsWithChildren<ISortingProps>) => {
|
||||
const [ crntSorting, setCrntSorting ] = useRecoilState(SortingAtom);
|
||||
const searchValue = useRecoilValue(SearchSelector);
|
||||
const settings = useRecoilValue(SettingsSelector);
|
||||
|
||||
const crntSort = sortOptions.find(x => x.id === crntSorting);
|
||||
const updateSorting = (value: SortingOption) => {
|
||||
|
||||
Messenger.send(DashboardMessage.setState, {
|
||||
key: ExtensionState.Dashboard.Sorting,
|
||||
value: value
|
||||
})
|
||||
|
||||
setCrntSorting(value)
|
||||
};
|
||||
|
||||
let allOptions = [...sortOptions];
|
||||
if (settings?.customSorting) {
|
||||
allOptions = [...allOptions, ...settings.customSorting.map((s) => ({
|
||||
title: s.title || s.name,
|
||||
name: s.name,
|
||||
id: `${s.name}-${s.order}`,
|
||||
order: s.order,
|
||||
type: s.type
|
||||
}))];
|
||||
}
|
||||
|
||||
let crntSort = allOptions.find(x => x.id === crntSorting?.id) || sortOptions[0];
|
||||
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<Menu as="div" className="relative z-10 inline-block text-left">
|
||||
<MenuButton label={`Sort by`} title={crntSort?.name || ""} disabled={!!searchValue} />
|
||||
<MenuButton label={`Sort by`} title={crntSort?.title || crntSort?.name || ""} disabled={!!searchValue} />
|
||||
|
||||
<MenuItems>
|
||||
{sortOptions.map((option) => (
|
||||
{allOptions.map((option) => (
|
||||
<MenuItem
|
||||
key={option.id}
|
||||
title={option.name}
|
||||
value={option.id}
|
||||
isCurrent={option.id === crntSorting}
|
||||
onClick={(value) => setCrntSorting(value)} />
|
||||
title={option.title || option.name}
|
||||
value={option}
|
||||
isCurrent={option.id === crntSorting?.id}
|
||||
onClick={(value) => updateSorting(value)} />
|
||||
))}
|
||||
</MenuItems>
|
||||
</Menu>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export enum SortOption {
|
||||
LastModified = 1,
|
||||
FileNameAsc,
|
||||
FileNameDesc
|
||||
LastModified = "LastModified",
|
||||
FileNameAsc = "FileNameAsc",
|
||||
FileNameDesc = "FileNameDesc"
|
||||
}
|
||||
@@ -3,8 +3,10 @@ import { SortOption } from '../constants/SortOption';
|
||||
import { Tab } from '../constants/Tab';
|
||||
import { Page } from '../models/Page';
|
||||
import Fuse from 'fuse.js';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { CategorySelector, FolderSelector, SearchSelector, SettingsSelector, SortingSelector, TabSelector, TagSelector } from '../state';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { CategorySelector, FolderSelector, SearchSelector, SettingsSelector, SortingAtom, TabSelector, TagSelector } from '../state';
|
||||
import { SortOrder, SortType } from '../../models';
|
||||
import { DateHelper } from '../../helpers/DateHelper';
|
||||
|
||||
const fuseOptions: Fuse.IFuseOptions<Page> = {
|
||||
keys: [
|
||||
@@ -16,16 +18,48 @@ const fuseOptions: Fuse.IFuseOptions<Page> = {
|
||||
|
||||
export default function usePages(pages: Page[]) {
|
||||
const [ pageItems, setPageItems ] = useState<Page[]>([]);
|
||||
const [ sorting, setSorting ] = useRecoilState(SortingAtom);
|
||||
const settings = useRecoilValue(SettingsSelector);
|
||||
const tab = useRecoilValue(TabSelector);
|
||||
const sorting = useRecoilValue(SortingSelector);
|
||||
const folder = useRecoilValue(FolderSelector);
|
||||
const search = useRecoilValue(SearchSelector);
|
||||
const tag = useRecoilValue(TagSelector);
|
||||
const category = useRecoilValue(CategorySelector);
|
||||
|
||||
// Sort field value alphabetically
|
||||
const sortAlphabetically = (property: string) => {
|
||||
return (a: Page, b: Page) => {
|
||||
if (a[property] < b[property]) {
|
||||
return -1;
|
||||
}
|
||||
if (a[property] > b[property]) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
};
|
||||
|
||||
// Sort by date
|
||||
const sortByDate = (property: string) => {
|
||||
return (a: Page, b: Page) => {
|
||||
const dateA = DateHelper.tryParse(a[property]);
|
||||
const dateB = DateHelper.tryParse(b[property]);
|
||||
|
||||
return (dateA || new Date(0)).getTime() - (dateB || new Date(0)).getTime();
|
||||
};
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const draftField = settings?.draftField;
|
||||
let usedSorting = sorting;
|
||||
|
||||
if (!usedSorting) {
|
||||
const lastSort = settings?.dashboardState.sorting;
|
||||
if (lastSort) {
|
||||
setSorting(lastSort);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if search needs to be performed
|
||||
let searchedPages = pages;
|
||||
@@ -58,12 +92,26 @@ export default function usePages(pages: Page[]) {
|
||||
// Sort the pages
|
||||
let pagesSorted: Page[] = Object.assign([], pagesToShow);
|
||||
if (!search) {
|
||||
if (sorting === SortOption.FileNameAsc) {
|
||||
pagesSorted = pagesToShow.sort((a, b) => a.fmFileName.toLowerCase().localeCompare(b.fmFileName.toLowerCase()));
|
||||
} else if (sorting === SortOption.FileNameDesc) {
|
||||
pagesSorted = pagesToShow.sort((a, b) => b.fmFileName.toLowerCase().localeCompare(a.fmFileName.toLowerCase()));
|
||||
if (sorting && sorting.id === SortOption.FileNameAsc) {
|
||||
pagesSorted = pagesSorted.sort(sortAlphabetically("fmFileName"));
|
||||
} else if (sorting && sorting.id === SortOption.FileNameDesc) {
|
||||
pagesSorted = pagesSorted.sort(sortAlphabetically("fmFileName")).reverse();
|
||||
} else if (sorting && sorting.id === SortOption.LastModified) {
|
||||
pagesSorted = pagesSorted.sort((a, b) => b.fmModified - a.fmModified);
|
||||
} else if (sorting && sorting.id && sorting.name) {
|
||||
const { order, name, type } = sorting;
|
||||
|
||||
if (type === SortType.string) {
|
||||
pagesSorted = pagesSorted.sort(sortAlphabetically(name));
|
||||
} else if (type === SortType.date) {
|
||||
pagesSorted = pagesSorted.sort(sortByDate(name));
|
||||
}
|
||||
|
||||
if (order === SortOrder.desc) {
|
||||
pagesSorted = pagesSorted.reverse();
|
||||
}
|
||||
} else {
|
||||
pagesSorted = pagesToShow.sort((a, b) => b.fmModified - a.fmModified);
|
||||
pagesSorted = pagesSorted.sort((a, b) => b.fmModified - a.fmModified);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { VersionInfo } from '../../models/VersionInfo';
|
||||
import { ViewType } from '../state';
|
||||
import { ContentFolder } from '../../models/ContentFolder';
|
||||
import { ContentType, DraftField, Framework } from '../../models';
|
||||
import { ContentType, DraftField, Framework, SortingSetting } from '../../models';
|
||||
import { SortingOption } from './SortingOption';
|
||||
|
||||
export interface Settings {
|
||||
beta: boolean;
|
||||
@@ -16,8 +17,14 @@ export interface Settings {
|
||||
pageViewType: ViewType | undefined;
|
||||
mediaSnippet: string[];
|
||||
contentTypes: ContentType[];
|
||||
contentFolders: string[];
|
||||
contentFolders: ContentFolder[];
|
||||
crntFramework: string;
|
||||
framework: Framework | null | undefined;
|
||||
draftField: DraftField | null | undefined;
|
||||
customSorting: SortingSetting[] | undefined;
|
||||
dashboardState: DashboardState;
|
||||
}
|
||||
|
||||
export interface DashboardState {
|
||||
sorting: SortingOption | null | undefined;
|
||||
}
|
||||
10
src/dashboardWebView/models/SortingOption.ts
Normal file
10
src/dashboardWebView/models/SortingOption.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { SortOrder, SortType } from "../../models";
|
||||
import { SortOption } from "../constants/SortOption";
|
||||
|
||||
export interface SortingOption {
|
||||
title?: string;
|
||||
name: string;
|
||||
id: SortOption | string;
|
||||
order: SortOrder,
|
||||
type: SortType;
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
import { atom } from 'recoil';
|
||||
import { SortOption } from '../../constants/SortOption';
|
||||
import { SortingOption } from '../../models/SortingOption';
|
||||
|
||||
export const DEFAULT_SORTING_OPTION = SortOption.LastModified;
|
||||
|
||||
export const SortingAtom = atom<SortOption>({
|
||||
export const SortingAtom = atom<SortingOption | null>({
|
||||
key: 'SortingAtom',
|
||||
default: DEFAULT_SORTING_OPTION
|
||||
default: null
|
||||
});
|
||||
@@ -91,11 +91,13 @@ export class ArticleHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return matter.stringify(content, data, ({
|
||||
...TomlEngine,
|
||||
...langOpts,
|
||||
noArrayIndent: !indentArray,
|
||||
skipInvalid: true,
|
||||
noCompatMode: true,
|
||||
lineWidth: 500,
|
||||
indent: spaces || 2
|
||||
} as DumpOptions as any));
|
||||
|
||||
@@ -115,7 +115,7 @@ export class Extension {
|
||||
const projectFolder = basename(workspace?.fsPath || "");
|
||||
|
||||
const paths = folders.map((folder: any) => ({
|
||||
title: folder.title,
|
||||
...folder,
|
||||
path: `${WORKSPACE_PLACEHOLDER}${folder.fsPath.split(projectFolder).slice(1).join('')}`.split('\\').join('/')
|
||||
}));
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export interface ContentFolder {
|
||||
title: string;
|
||||
path: string;
|
||||
|
||||
excludeSubdir?: boolean;
|
||||
}
|
||||
4
src/models/SortOrder.ts
Normal file
4
src/models/SortOrder.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export enum SortOrder {
|
||||
asc = 'asc',
|
||||
desc = 'desc'
|
||||
}
|
||||
4
src/models/SortType.ts
Normal file
4
src/models/SortType.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export enum SortType {
|
||||
string = 'string',
|
||||
date = 'date'
|
||||
}
|
||||
8
src/models/SortingSetting.ts
Normal file
8
src/models/SortingSetting.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { SortOrder, SortType } from ".";
|
||||
|
||||
export interface SortingSetting {
|
||||
title: string;
|
||||
name: string;
|
||||
order: SortOrder;
|
||||
type: SortType;
|
||||
}
|
||||
@@ -5,5 +5,8 @@ export * from './DraftField';
|
||||
export * from './Framework';
|
||||
export * from './MediaPaths';
|
||||
export * from './PanelSettings';
|
||||
export * from './SortOrder';
|
||||
export * from './SortType';
|
||||
export * from './SortingSetting';
|
||||
export * from './TaxonomyType';
|
||||
export * from './VersionInfo';
|
||||
|
||||
Reference in New Issue
Block a user