diff --git a/assets/media/styles.css b/assets/media/styles.css index fd384c80..39803fb9 100644 --- a/assets/media/styles.css +++ b/assets/media/styles.css @@ -247,14 +247,6 @@ background-color: var(--vscode-button-secondaryHoverBackground); } -.table__cell { - overflow: hidden; -} - -.table__title { - text-transform: capitalize; -} - .table__cell__seo_details { padding: 10px; } @@ -281,11 +273,6 @@ margin-left: 0.5rem; } -.seo__status__note { - font-size: 10px; - padding: 3px 0; -} - /* Fields */ .field__toggle { position: relative; @@ -364,7 +351,7 @@ input:checked + .field__toggle__slider:before { } /* File list */ -.file_list vscode-label { +.file_list label { border-bottom: 1px solid var(--vscode-foreground); } diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index 6e1f2b98..4e108527 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -37,6 +37,10 @@ "common.back": "Back", "common.open": "Open", "common.openWithValue": "Open: {0}", + "common.view": "View", + "common.translate": "Translate", + "common.languages": "Languages", + "common.scripts": "Scripts", "loading.initPages": "Loading content", @@ -146,6 +150,10 @@ "dashboard.filters.languageFilter.label": "Locale", "dashboard.filters.languageFilter.all": "All", + "dashboard.header.actionsBar.itemsSelected": "{0} selected", + "dashboard.header.actionsBar.alertDelete.title": "Delete selected files", + "dashboard.header.actionsBar.alertDelete.description": "Are you sure you want to delete the selected files?", + "dashboard.header.breadcrumb.home": "Home", "dashboard.header.clearFilters.title": "Clear filters, grouping, and sorting", @@ -229,6 +237,9 @@ "dashboard.media.folderCreation.hexo.create": "Create post asset folder", "dashboard.media.folderCreation.folder.create": "Create new folder", + "dashboard.media.folderItem.contentDirectory": "Content directory", + "dashboard.media.folderItem.publicDirectory": "Public directory", + "dashboard.media.item.buttom.insert.image": "Insert image", "dashboard.media.item.buttom.insert.snippet": "Insert snippet", diff --git a/package-lock.json b/package-lock.json index 81801084..232c2b03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,6 @@ }, "devDependencies": { "@actions/core": "^1.10.0", - "@bendera/vscode-webview-elements": "0.6.2", "@estruyf/vscode": "^1.1.0", "@headlessui/react": "^1.7.18", "@heroicons/react": "^2.1.1", @@ -38,6 +37,7 @@ "@types/vscode": "^1.73.0", "@typescript-eslint/eslint-plugin": "^5.50.0", "@typescript-eslint/parser": "^5.50.0", + "@vscode-elements/elements": "^1.2.0", "@vscode/l10n": "^0.0.14", "@vscode/webview-ui-toolkit": "^1.2.2", "@webpack-cli/serve": "^1.7.0", @@ -85,7 +85,7 @@ "react-quill": "^2.0.0", "react-router-dom": "^6.8.0", "react-sortable-hoc": "^2.0.0", - "recoil": "^0.4.1", + "recoil": "^0.7.7", "remark-gfm": "^3.0.1", "rimraf": "^3.0.2", "semver": "^7.3.8", @@ -400,15 +400,6 @@ "node": ">=6.9.0" } }, - "node_modules/@bendera/vscode-webview-elements": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@bendera/vscode-webview-elements/-/vscode-webview-elements-0.6.2.tgz", - "integrity": "sha512-smtr+KvCKV2MwjVrmyvrhonpaXVpxCjTMXUQOwDwWSAQ42x5pnlpjCGElz2dljc5VHS1Mh1ovPSQ/P3jAm7vMQ==", - "dev": true, - "dependencies": { - "lit-element": "^2.5.1" - } - }, "node_modules/@ctrl/tinycolor": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", @@ -764,6 +755,21 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", "dev": true }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz", + "integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g==", + "dev": true + }, + "node_modules/@lit/reactive-element": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz", + "integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==", + "dev": true, + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.2.0" + } + }, "node_modules/@microsoft/fast-element": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.12.0.tgz", @@ -2073,6 +2079,12 @@ "integrity": "sha512-bTHG8fcxEqv1M9+TD14P8ok8hjxoOCkfKc8XXLaaD05kI7ohpeI956jtDOD3XHKBQrlyPughUtzm1jtVhHpA5Q==", "dev": true }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true + }, "node_modules/@types/uglify-js": { "version": "3.17.4", "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.17.4.tgz", @@ -2337,6 +2349,15 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@vscode-elements/elements": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@vscode-elements/elements/-/elements-1.2.0.tgz", + "integrity": "sha512-aCsf9iEnx+PE2rRfAySjvFTSgqP4NUvHG0nOc5AxFB1FXHyG/ayYA2TN9XpT7zuO024tRAu+XoKREbRC7uAmLA==", + "dev": true, + "dependencies": { + "lit": "^3.1.2" + } + }, "node_modules/@vscode/l10n": { "version": "0.0.14", "resolved": "https://registry.npmjs.org/@vscode/l10n/-/l10n-0.0.14.tgz", @@ -6563,20 +6584,36 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "node_modules/lit-element": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-2.5.1.tgz", - "integrity": "sha512-ogu7PiJTA33bEK0xGu1dmaX5vhcRjBXCFexPja0e7P7jqLhTpNKYRPmE+GmiCaRVAbiQKGkUgkh/i6+bh++dPQ==", + "node_modules/lit": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.1.2.tgz", + "integrity": "sha512-VZx5iAyMtX7CV4K8iTLdCkMaYZ7ipjJZ0JcSdJ0zIdGxxyurjIn7yuuSxNBD7QmjvcNJwr0JS4cAdAtsy7gZ6w==", "dev": true, "dependencies": { - "lit-html": "^1.1.1" + "@lit/reactive-element": "^2.0.4", + "lit-element": "^4.0.4", + "lit-html": "^3.1.2" + } + }, + "node_modules/lit-element": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.4.tgz", + "integrity": "sha512-98CvgulX6eCPs6TyAIQoJZBCQPo80rgXR+dVBs61cstJXqtI+USQZAbA4gFHh6L/mxBx9MrgPLHLsUgDUHAcCQ==", + "dev": true, + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.2.0", + "@lit/reactive-element": "^2.0.4", + "lit-html": "^3.1.2" } }, "node_modules/lit-html": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-1.4.1.tgz", - "integrity": "sha512-B9btcSgPYb1q4oSOb/PrOT6Z/H+r6xuNzfH4lFli/AWhYwdtrgQkQWBbIc6mdnf6E2IL3gDXdkkqNktpU0OZQA==", - "dev": true + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.1.2.tgz", + "integrity": "sha512-3OBZSUrPnAHoKJ9AMjRL/m01YJxQMf+TMHanNtTHG68ubjnZxK0RFl102DPzsw4mWnHibfZIBJm3LWCZ/LmMvg==", + "dev": true, + "dependencies": { + "@types/trusted-types": "^2.0.2" + } }, "node_modules/load-json-file": { "version": "4.0.0", @@ -10156,9 +10193,9 @@ } }, "node_modules/recoil": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/recoil/-/recoil-0.4.1.tgz", - "integrity": "sha512-vp6KPwlHOjJ4bJofmdDchmgI9ilMTCoUisK8/WYLl8dThH7e7KmtZttiLgvDb2Em99dUfTEsk8vT8L1nUMgqXQ==", + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/recoil/-/recoil-0.7.7.tgz", + "integrity": "sha512-8Og5KPQW9LwC577Vc7Ug2P0vQshkv1y3zG3tSSkWMqkWSwHmE+by06L8JtnGocjW6gcCvfwB3YtrJG6/tWivNQ==", "dev": true, "dependencies": { "hamt_plus": "1.0.2" diff --git a/package.json b/package.json index 9f765e18..3f36e079 100644 --- a/package.json +++ b/package.json @@ -2707,7 +2707,6 @@ }, "devDependencies": { "@actions/core": "^1.10.0", - "@bendera/vscode-webview-elements": "0.6.2", "@estruyf/vscode": "^1.1.0", "@headlessui/react": "^1.7.18", "@heroicons/react": "^2.1.1", @@ -2732,6 +2731,7 @@ "@types/vscode": "^1.73.0", "@typescript-eslint/eslint-plugin": "^5.50.0", "@typescript-eslint/parser": "^5.50.0", + "@vscode-elements/elements": "^1.2.0", "@vscode/l10n": "^0.0.14", "@vscode/webview-ui-toolkit": "^1.2.2", "@webpack-cli/serve": "^1.7.0", @@ -2779,7 +2779,7 @@ "react-quill": "^2.0.0", "react-router-dom": "^6.8.0", "react-sortable-hoc": "^2.0.0", - "recoil": "^0.4.1", + "recoil": "^0.7.7", "remark-gfm": "^3.0.1", "rimraf": "^3.0.2", "semver": "^7.3.8", diff --git a/src/dashboardWebView/components/Common/ItemSelection.tsx b/src/dashboardWebView/components/Common/ItemSelection.tsx new file mode 100644 index 00000000..b8de29e1 --- /dev/null +++ b/src/dashboardWebView/components/Common/ItemSelection.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import useSelectedItems from '../../hooks/useSelectedItems'; +import { VSCodeCheckbox } from '@vscode/webview-ui-toolkit/react'; +import { useMemo } from 'react'; + +export interface IItemSelectionProps { + filePath: string; + isRowItem?: boolean; +} + +export const ItemSelection: React.FunctionComponent = ({ + filePath, + isRowItem +}: React.PropsWithChildren) => { + const { onMultiSelect, selectedFiles } = useSelectedItems(); + + const cssNames = useMemo(() => { + if (isRowItem) { + return 'block'; + } + return `${selectedFiles.includes(filePath) ? 'block' : 'hidden'} absolute top-2 left-2`; + }, [isRowItem, selectedFiles]); + + return ( +
+ ) => { + e.stopPropagation(); + onMultiSelect(filePath); + }} + checked={selectedFiles.includes(filePath)} /> +
+ ); +}; \ No newline at end of file diff --git a/src/dashboardWebView/components/Contents/Contents.tsx b/src/dashboardWebView/components/Contents/Contents.tsx index 0db5a4df..625e1af1 100644 --- a/src/dashboardWebView/components/Contents/Contents.tsx +++ b/src/dashboardWebView/components/Contents/Contents.tsx @@ -11,6 +11,7 @@ import { Messenger } from '@estruyf/vscode/dist/client'; import { DashboardMessage } from '../../DashboardMessage'; import { TelemetryEvent } from '../../../constants'; import { PageLayout } from '../Layout/PageLayout'; +import { FilesProvider } from '../../providers/FilesProvider'; export interface IContentsProps { pages: Page[]; @@ -32,18 +33,20 @@ export const Contents: React.FunctionComponent = ({ }, []); return ( - -
- {loading ? : } -
+ + +
+ {loading ? : } +
- + - Content metrics -
+ Content metrics +
+ ); }; diff --git a/src/dashboardWebView/components/Contents/Item.tsx b/src/dashboardWebView/components/Contents/Item.tsx index ba1edd16..89fc51d7 100644 --- a/src/dashboardWebView/components/Contents/Item.tsx +++ b/src/dashboardWebView/components/Contents/Item.tsx @@ -17,6 +17,7 @@ import { useNavigate } from 'react-router-dom'; import { routePaths } from '../..'; import useCard from '../../hooks/useCard'; import { I18nLabel } from './I18nLabel'; +import { ItemSelection } from '../Common/ItemSelection'; export interface IItemProps extends Page { } @@ -133,6 +134,8 @@ export const Item: React.FunctionComponent = ({ } + +
{ (statusPlaceholder || datePlaceholder) && ( @@ -232,6 +235,8 @@ export const Item: React.FunctionComponent = ({ className={`px-5 cursor-pointer w-full text-left grid grid-cols-12 gap-x-4 sm:gap-x-6 xl:gap-x-8 py-2 border-b hover:bg-opacity-70 border-[var(--frontmatter-border)] hover:bg-[var(--vscode-sideBar-background)]`} >
+ + + + + ) + } +
+ + {showAlert && ( + setShowAlert(false)} + trigger={onDeleteConfirm} + /> + )} + + ); +}; \ No newline at end of file diff --git a/src/dashboardWebView/components/Header/ActionsBarItem.tsx b/src/dashboardWebView/components/Header/ActionsBarItem.tsx new file mode 100644 index 00000000..91a34e43 --- /dev/null +++ b/src/dashboardWebView/components/Header/ActionsBarItem.tsx @@ -0,0 +1,26 @@ +import * as React from 'react'; +import { cn } from '../../../utils/cn'; + +export interface IActionsBarItemProps { + className?: string; + disabled?: boolean; + onClick?: () => void; +} + +export const ActionsBarItem: React.FunctionComponent = ({ + children, + className, + disabled, + onClick +}: React.PropsWithChildren) => { + return ( + + ); +}; \ No newline at end of file diff --git a/src/dashboardWebView/components/Header/Breadcrumb.tsx b/src/dashboardWebView/components/Header/Breadcrumb.tsx index e3eb9540..e3ff65c6 100644 --- a/src/dashboardWebView/components/Header/Breadcrumb.tsx +++ b/src/dashboardWebView/components/Header/Breadcrumb.tsx @@ -4,24 +4,25 @@ import * as React from 'react'; import { useRecoilState, useRecoilValue } from 'recoil'; import { HOME_PAGE_NAVIGATION_ID } from '../../../constants'; import { parseWinPath } from '../../../helpers/parseWinPath'; -import { SearchAtom, SelectedMediaFolderAtom, SettingsAtom } from '../../state'; +import { SearchAtom, SettingsAtom } from '../../state'; import * as l10n from '@vscode/l10n'; import { LocalizationKey } from '../../../localization'; +import useMediaFolder from '../../hooks/useMediaFolder'; export interface IBreadcrumbProps { } export const Breadcrumb: React.FunctionComponent = ( _: React.PropsWithChildren ) => { - const [selectedFolder, setSelectedFolder] = useRecoilState(SelectedMediaFolderAtom); + const { selectedFolder, updateFolder } = useMediaFolder(); const [, setSearchValue] = useRecoilState(SearchAtom); const [folders, setFolders] = React.useState([]); const settings = useRecoilValue(SettingsAtom); - const updateFolder = (folder: string) => { + const updateMediaFolder = React.useCallback((folder: string) => { setSearchValue(''); - setSelectedFolder(folder); - }; + updateFolder(folder); + }, [updateFolder, setSearchValue]); React.useEffect(() => { if (!settings) { @@ -79,11 +80,11 @@ export const Breadcrumb: React.FunctionComponent = ( }, [selectedFolder, settings]); return ( -
    +
    1. diff --git a/src/dashboardWebView/components/Header/Header.tsx b/src/dashboardWebView/components/Header/Header.tsx index 10705f84..8a2ac464 100644 --- a/src/dashboardWebView/components/Header/Header.tsx +++ b/src/dashboardWebView/components/Header/Header.tsx @@ -6,7 +6,7 @@ import { DashboardMessage } from '../../DashboardMessage'; import { Grouping } from '.'; import { ViewSwitch } from './ViewSwitch'; import { useRecoilValue, useResetRecoilState } from 'recoil'; -import { GroupingSelector, SortingAtom } from '../../state'; +import { GroupingSelector, MultiSelectedItemsAtom, SortingAtom } from '../../state'; import { Messenger } from '@estruyf/vscode/dist/client'; import { ClearFilters } from './ClearFilters'; import { MediaHeaderTop } from '../Media/MediaHeaderTop'; @@ -31,6 +31,7 @@ import { SettingsLink } from '../SettingsView/SettingsLink'; import { Link } from '../Common/Link'; import { SPONSOR_LINK } from '../../../constants'; import { Filters } from './Filters'; +import { ActionsBar } from './ActionsBar'; export interface IHeaderProps { header?: React.ReactNode; @@ -50,6 +51,7 @@ export const Header: React.FunctionComponent = ({ }: React.PropsWithChildren) => { const grouping = useRecoilValue(GroupingSelector); const resetSorting = useResetRecoilState(SortingAtom); + const resetSelectedItems = useResetRecoilState(MultiSelectedItemsAtom); const location = useLocation(); const navigate = useNavigate(); const { pageSetNr } = usePagination(settings?.dashboardState.contents.pagination); @@ -69,6 +71,7 @@ export const Header: React.FunctionComponent = ({ const updateView = (view: NavigationType) => { navigate(routePaths[view]); resetSorting(); + resetSelectedItems(); }; const runBulkScript = (script: CustomScript) => { @@ -121,7 +124,7 @@ export const Header: React.FunctionComponent = ({ return (
      -
      +
      @@ -159,12 +162,8 @@ export const Header: React.FunctionComponent = ({ {location.pathname === routePaths.contents && ( <> -
      - - -
      - {/* */} - +
      +
      = ({ disabled={!settings?.initialized} />
      + +
      @@ -185,7 +186,7 @@ export const Header: React.FunctionComponent = ({
      @@ -207,6 +208,8 @@ export const Header: React.FunctionComponent = ({
      )} + + )} @@ -215,6 +218,8 @@ export const Header: React.FunctionComponent = ({ + + )} diff --git a/src/dashboardWebView/components/Header/Searchbox.tsx b/src/dashboardWebView/components/Header/Searchbox.tsx index 0f189015..9749f0b4 100644 --- a/src/dashboardWebView/components/Header/Searchbox.tsx +++ b/src/dashboardWebView/components/Header/Searchbox.tsx @@ -40,7 +40,7 @@ export const Searchbox: React.FunctionComponent = ({ }, [debounceSearch]); return ( -
      +