Cover Files rich file icons
This commit is contained in:
parent
3c54ef55c9
commit
d2a07baf82
|
|
@ -129,6 +129,34 @@ test.describe('G: Files Plugin', () => {
|
|||
await expect(page.locator('[data-file-name="bad"]')).toHaveCount(0);
|
||||
});
|
||||
|
||||
test('files explorer uses rich file icons by file type', async ({ page }) => {
|
||||
await page.locator('.wt-label').filter({ hasText: 'Project' }).click();
|
||||
await openFilesTool(page);
|
||||
await expect(page.locator('.files-breadcrumb')).toContainText('Project', { timeout: 10000 });
|
||||
|
||||
async function createFile(action, name) {
|
||||
await page.locator(`[data-files-action="${action}"]`).click();
|
||||
await page.locator('[data-files-create-input]').fill(name);
|
||||
await page.locator('[data-files-create-confirm]').click();
|
||||
await expect(page.locator(`[data-file-name="${name}"]`)).toBeVisible();
|
||||
}
|
||||
|
||||
await createFile('new-markdown', 'IconNote.md');
|
||||
await createFile('new-text', 'Photo.png');
|
||||
await createFile('new-text', 'Manual.pdf');
|
||||
await createFile('new-text', 'Script.js');
|
||||
|
||||
const iconFor = (name) => page.locator(`[data-file-name="${name}"] .files-item-icon`);
|
||||
await expect(iconFor('Notes')).toHaveAttribute('data-file-icon', 'folder');
|
||||
await expect(iconFor('project-only.txt')).toHaveAttribute('data-file-icon', 'text');
|
||||
await expect(iconFor('IconNote.md')).toHaveAttribute('data-file-icon', 'markdown');
|
||||
await expect(iconFor('Photo.png')).toHaveAttribute('data-file-icon', 'image');
|
||||
await expect(iconFor('Manual.pdf')).toHaveAttribute('data-file-icon', 'pdf');
|
||||
await expect(iconFor('Script.js')).toHaveAttribute('data-file-icon', 'code');
|
||||
await expect(iconFor('Manual.pdf')).toHaveAttribute('aria-label', 'PDF file');
|
||||
await expect(iconFor('Photo.png')).toHaveAttribute('title', 'Image file');
|
||||
});
|
||||
|
||||
test('files explorer restores an item from trash metadata', async ({ page }) => {
|
||||
await page.locator('.wt-label').filter({ hasText: 'Project' }).click();
|
||||
await openFilesTool(page);
|
||||
|
|
|
|||
|
|
@ -679,6 +679,41 @@
|
|||
return '(' + function () {
|
||||
var SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M6 2h9l5 5v15H6V2Zm8 1.5V8h4.5L14 3.5Z"/></svg>';
|
||||
var FOLDER_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M3 5a2 2 0 0 1 2-2h5l2 3h7a2 2 0 0 1 2 2v1H3V5Zm0 6h18v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7Z"/></svg>';
|
||||
var FILE_SVGS = {
|
||||
folder: FOLDER_SVG,
|
||||
generic: SVG,
|
||||
markdown: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M5 3h10l4 4v14H5V3Zm9 1.5V8h3.5L14 4.5ZM8 11h8v2H8v-2Zm0 4h8v2H8v-2Z"/></svg>',
|
||||
text: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M6 2h9l5 5v15H6V2Zm8 1.5V8h4.5L14 3.5ZM8 12h8v1.5H8V12Zm0 3h8v1.5H8V15Zm0 3h5v1.5H8V18Z"/></svg>',
|
||||
image: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg>',
|
||||
pdf: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M20 2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-8.5 7.5c0 .83-.67 1.5-1.5 1.5H9v2H7.5V7H10c.83 0 1.5.67 1.5 1.5v1zm5 2c0 .83-.67 1.5-1.5 1.5h-2.5V7H15c.83 0 1.5.67 1.5 1.5v3zm4-3H19v1h1.5V11H19v2h-1.5V7h3v1.5zM9 9.5h1v-1H9v1zm6 2h1v-3h-1v3z"/></svg>',
|
||||
code: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M22 21H2V3h20v18zM4 5v14h16V5H4zm3 4h10v2H7V9zm0 4h6v2H7v-2z"/></svg>'
|
||||
};
|
||||
var ICON_EXTENSIONS = {
|
||||
md: 'markdown', markdown: 'markdown',
|
||||
txt: 'text', text: 'text', log: 'text', rtf: 'text',
|
||||
jpg: 'image', jpeg: 'image', png: 'image', gif: 'image', webp: 'image', svg: 'image',
|
||||
pdf: 'pdf',
|
||||
js: 'code', jsx: 'code', mjs: 'code', cjs: 'code', ts: 'code', tsx: 'code',
|
||||
py: 'code', go: 'code', rs: 'code', css: 'code', html: 'code', json: 'code'
|
||||
};
|
||||
function fileIconCategory(item) {
|
||||
if (item.type === 'folder') return 'folder';
|
||||
return ICON_EXTENSIONS[(item.extension || ext(item.name)).toLowerCase()] || 'generic';
|
||||
}
|
||||
function fileIconLabel(category) {
|
||||
return {
|
||||
folder: 'Folder',
|
||||
markdown: 'Markdown file',
|
||||
text: 'Text file',
|
||||
image: 'Image file',
|
||||
pdf: 'PDF file',
|
||||
code: 'Code file',
|
||||
generic: 'File'
|
||||
}[category] || 'File';
|
||||
}
|
||||
function fileIcon(item) {
|
||||
return FILE_SVGS[fileIconCategory(item)] || FILE_SVGS.generic;
|
||||
}
|
||||
function e(tag, attrs, children) {
|
||||
var node = document.createElement(tag);
|
||||
attrs = attrs || {};
|
||||
|
|
@ -838,6 +873,8 @@
|
|||
list.appendChild(e('div', { className: 'files-header' }, [e('span', {}, ['Name']), e('span', {}, ['Type']), e('span', {}, ['Size']), e('span', {}, ['Modified']), e('span', {}, ['Actions'])]));
|
||||
var shown = visible();
|
||||
shown.forEach(function (item) {
|
||||
var iconCategory = fileIconCategory(item);
|
||||
var iconLabel = fileIconLabel(iconCategory);
|
||||
var row = e('div', {
|
||||
className: 'files-item' + (selected[item.relativePath] ? ' selected' : ''),
|
||||
'data-file-name': item.name,
|
||||
|
|
@ -852,7 +889,7 @@
|
|||
ev.dataTransfer.effectAllowed = 'move';
|
||||
}
|
||||
}, []);
|
||||
row.appendChild(e('span', { className: 'files-namecell' }, [e('span', { className: 'files-item-icon', innerHTML: item.type === 'folder' ? FOLDER_SVG : SVG }, []), e('span', { className: 'files-item-name' }, [item.name])]));
|
||||
row.appendChild(e('span', { className: 'files-namecell' }, [e('span', { className: 'files-item-icon', 'data-file-icon': iconCategory, title: iconLabel, 'aria-label': iconLabel, innerHTML: fileIcon(item) }, []), e('span', { className: 'files-item-name' }, [item.name])]));
|
||||
row.appendChild(e('span', { className: 'files-item-meta' }, [item.type === 'folder' ? 'folder' : (item.extension || ext(item.name) || 'file')]));
|
||||
row.appendChild(e('span', { className: 'files-item-meta' }, [item.size ? String(item.size) : '']));
|
||||
row.appendChild(e('span', { className: 'files-item-meta' }, [formatDate(item.modifiedAt)]));
|
||||
|
|
|
|||
Loading…
Reference in New Issue