gitea: default repo setting; editor: asset picker with thumbnail grid
Gitea plugin: default_repo field per account (stored in DB, pre-fills create issue form but stays editable). Editor toolbar: asset picker flyout with 4-column thumbnail grid and live search filter. Clicking a tile inserts the matching markdown. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
c5bf8b0407
commit
04b52ecc19
9 files changed
+197
-6
No files matched your search
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
define('APP_NAME', 'hyprcrd');
|
define('APP_NAME', 'hyprcrd');
|
||||||
define('APP_VERSION', '1.1.0');
|
define('APP_VERSION', '1.2.0');
|
||||||
|
|
||||||
// Database path — writable directory, outside webroot
|
// Database path — writable directory, outside webroot
|
||||||
// DB_PATH / UPLOAD_DIR can be pre-defined by the Electron router for app isolation
|
// DB_PATH / UPLOAD_DIR can be pre-defined by the Electron router for app isolation
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hyprcrd",
|
"name": "hyprcrd",
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"description": "hyprcrd — self-hosted card manager",
|
"description": "hyprcrd — self-hosted card manager",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -2203,6 +2203,7 @@ if (str_starts_with($route, '/api/')) {
|
|||||||
<button data-md="extract" title="Extract selection to new card" class="toolbar-btn"><i class="ph ph-scissors text-sm"></i></button>
|
<button data-md="extract" title="Extract selection to new card" class="toolbar-btn"><i class="ph ph-scissors text-sm"></i></button>
|
||||||
<button id="md-upload-pdf" title="Upload & link PDF" class="toolbar-btn"><i class="ph ph-file-pdf text-sm"></i></button>
|
<button id="md-upload-pdf" title="Upload & link PDF" class="toolbar-btn"><i class="ph ph-file-pdf text-sm"></i></button>
|
||||||
<input type="file" id="md-upload-pdf-file" accept=".pdf,application/pdf" class="hidden">
|
<input type="file" id="md-upload-pdf-file" accept=".pdf,application/pdf" class="hidden">
|
||||||
|
<button id="md-asset-picker" title="Insert from assets" class="toolbar-btn" style="position:relative;"><i class="ph ph-images text-sm"></i></button>
|
||||||
<div class="w-px h-4 bg-t-border mx-1"></div>
|
<div class="w-px h-4 bg-t-border mx-1"></div>
|
||||||
<button id="md-find-replace" title="Find & replace (Ctrl+H)" class="toolbar-btn" onclick="openFindBar(true)"><i class="ph ph-magnifying-glass text-sm"></i></button>
|
<button id="md-find-replace" title="Find & replace (Ctrl+H)" class="toolbar-btn" onclick="openFindBar(true)"><i class="ph ph-magnifying-glass text-sm"></i></button>
|
||||||
<?= PluginManager::instance()->slot('md-toolbar') ?>
|
<?= PluginManager::instance()->slot('md-toolbar') ?>
|
||||||
|
|||||||
@@ -363,6 +363,7 @@ export function closeModal({ animate = true } = {}) {
|
|||||||
hideTagAc();
|
hideTagAc();
|
||||||
hideSnippetAc();
|
hideSnippetAc();
|
||||||
closeFindBar();
|
closeFindBar();
|
||||||
|
closeAssetPicker();
|
||||||
modal.classList.remove('open');
|
modal.classList.remove('open');
|
||||||
state.editingId = null;
|
state.editingId = null;
|
||||||
state.returnToGalleryAfterEdit = false;
|
state.returnToGalleryAfterEdit = false;
|
||||||
@@ -1184,6 +1185,110 @@ $('md-upload-pdf-file')?.addEventListener('change', e => {
|
|||||||
e.target.value = '';
|
e.target.value = '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ── Asset picker (insert from uploads) ──
|
||||||
|
|
||||||
|
const ASSET_IMAGE_EXT = /\.(png|jpe?g|gif|webp)$/i;
|
||||||
|
const ASSET_AUDIO_EXT = /\.(mp3|ogg|wav|m4a)$/i;
|
||||||
|
const ASSET_PDF_EXT = /\.pdf$/i;
|
||||||
|
|
||||||
|
function assetType(name) {
|
||||||
|
if (ASSET_IMAGE_EXT.test(name)) return 'image';
|
||||||
|
if (ASSET_AUDIO_EXT.test(name)) return 'audio';
|
||||||
|
if (ASSET_PDF_EXT.test(name)) return 'pdf';
|
||||||
|
return 'other';
|
||||||
|
}
|
||||||
|
|
||||||
|
let assetPickerEl = null;
|
||||||
|
|
||||||
|
function closeAssetPicker() {
|
||||||
|
if (assetPickerEl) { assetPickerEl.remove(); assetPickerEl = null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
$('md-asset-picker')?.addEventListener('click', async () => {
|
||||||
|
if (assetPickerEl) { closeAssetPicker(); return; }
|
||||||
|
|
||||||
|
let files = [];
|
||||||
|
try { files = await api('api/uploads'); } catch {}
|
||||||
|
if (!Array.isArray(files)) files = [];
|
||||||
|
|
||||||
|
const btn = $('md-asset-picker');
|
||||||
|
const rect = btn.getBoundingClientRect();
|
||||||
|
|
||||||
|
const picker = document.createElement('div');
|
||||||
|
picker.id = 'asset-picker-flyout';
|
||||||
|
picker.style.cssText = `position:fixed;top:${rect.bottom + 4}px;right:${window.innerWidth - rect.right}px;width:340px;max-height:400px;background:var(--t-surface);border:1px solid var(--t-border);border-radius:6px;box-shadow:0 12px 40px rgba(0,0,0,0.5);z-index:200;display:flex;flex-direction:column;overflow:hidden;`;
|
||||||
|
|
||||||
|
const searchHtml = `<div style="padding:8px;border-bottom:1px solid var(--t-border);">
|
||||||
|
<input id="asset-picker-search" type="text" placeholder="search assets..." autocomplete="off"
|
||||||
|
style="width:100%;background:var(--t-bg);border:1px solid var(--t-border);color:var(--t-bright);padding:5px 8px;font-size:11px;font-family:var(--t-font-content,'JetBrains Mono',monospace);border-radius:4px;outline:none;"
|
||||||
|
class="focus:border-t-accent">
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
const gridId = 'asset-picker-grid';
|
||||||
|
picker.innerHTML = searchHtml + `<div id="${gridId}" style="flex:1;overflow-y:auto;padding:8px;display:grid;grid-template-columns:repeat(4,1fr);gap:6px;"></div>`;
|
||||||
|
document.body.appendChild(picker);
|
||||||
|
assetPickerEl = picker;
|
||||||
|
|
||||||
|
const grid = picker.querySelector(`#${gridId}`);
|
||||||
|
const searchInput = picker.querySelector('#asset-picker-search');
|
||||||
|
|
||||||
|
function renderTiles(filter) {
|
||||||
|
const q = (filter || '').toLowerCase();
|
||||||
|
const filtered = q ? files.filter(f => f.name.toLowerCase().includes(q)) : files;
|
||||||
|
if (!filtered.length) {
|
||||||
|
grid.innerHTML = `<div style="grid-column:1/-1;text-align:center;padding:24px 0;color:var(--t-dim);font-size:10px;font-style:italic;">${files.length ? 'no matches' : 'no assets'}</div>`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
grid.innerHTML = filtered.map(f => {
|
||||||
|
const type = assetType(f.name);
|
||||||
|
const label = f.name.replace(/\.[^.]+$/, '');
|
||||||
|
if (type === 'image') {
|
||||||
|
return `<div class="asset-pick-tile" data-url="${esc(f.url)}" data-name="${esc(f.name)}" data-type="image" title="${esc(f.name)}" style="cursor:pointer;border-radius:4px;overflow:hidden;aspect-ratio:1;background:var(--t-bg);border:1px solid var(--t-border);">
|
||||||
|
<img src="${esc(f.url)}" style="width:100%;height:100%;object-fit:cover;" loading="lazy">
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
const icon = type === 'audio' ? 'ph-music-note' : type === 'pdf' ? 'ph-file-pdf' : 'ph-file';
|
||||||
|
const iconColor = type === 'pdf' ? 'color:var(--t-danger)' : 'color:var(--t-dim)';
|
||||||
|
return `<div class="asset-pick-tile" data-url="${esc(f.url)}" data-name="${esc(f.name)}" data-type="${type}" title="${esc(f.name)}" style="cursor:pointer;border-radius:4px;overflow:hidden;aspect-ratio:1;background:var(--t-bg);border:1px solid var(--t-border);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:4px;">
|
||||||
|
<i class="ph ${icon}" style="font-size:20px;${iconColor}"></i>
|
||||||
|
<span style="font-size:7px;color:var(--t-muted);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--t-font-pixel,'Silkscreen',monospace);">${esc(label)}</span>
|
||||||
|
</div>`;
|
||||||
|
}).join('');
|
||||||
|
|
||||||
|
grid.querySelectorAll('.asset-pick-tile').forEach(tile => {
|
||||||
|
tile.addEventListener('click', () => {
|
||||||
|
const url = tile.dataset.url;
|
||||||
|
const name = tile.dataset.name;
|
||||||
|
const type = tile.dataset.type;
|
||||||
|
let md;
|
||||||
|
if (type === 'image') md = `![${name.replace(/\.[^.]+$/, '')}](${url})`;
|
||||||
|
else if (type === 'pdf') md = `[📄 ${name}](${url})`;
|
||||||
|
else if (type === 'audio') md = `<audio controls src="${url}"></audio>`;
|
||||||
|
else md = `[${name}](${url})`;
|
||||||
|
insertMd(md);
|
||||||
|
closeAssetPicker();
|
||||||
|
});
|
||||||
|
tile.addEventListener('mouseenter', () => { tile.style.borderColor = 'var(--t-accent)'; });
|
||||||
|
tile.addEventListener('mouseleave', () => { tile.style.borderColor = 'var(--t-border)'; });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTiles('');
|
||||||
|
setTimeout(() => searchInput.focus(), 0);
|
||||||
|
searchInput.addEventListener('input', () => renderTiles(searchInput.value));
|
||||||
|
searchInput.addEventListener('keydown', e => {
|
||||||
|
if (e.key === 'Escape') { e.preventDefault(); e.stopPropagation(); closeAssetPicker(); }
|
||||||
|
});
|
||||||
|
|
||||||
|
const onClickOutside = e => {
|
||||||
|
if (!picker.contains(e.target) && e.target !== btn && !btn.contains(e.target)) {
|
||||||
|
closeAssetPicker();
|
||||||
|
document.removeEventListener('mousedown', onClickOutside);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.addEventListener('mousedown', onClickOutside);
|
||||||
|
});
|
||||||
|
|
||||||
// ── Image resize ──
|
// ── Image resize ──
|
||||||
|
|
||||||
document.addEventListener('mousedown', e => {
|
document.addEventListener('mousedown', e => {
|
||||||
|
|||||||
@@ -27,10 +27,16 @@ require_once __DIR__ . '/GiteaClient.php';
|
|||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
base_url TEXT NOT NULL,
|
base_url TEXT NOT NULL,
|
||||||
token TEXT NOT NULL,
|
token TEXT NOT NULL,
|
||||||
|
default_repo TEXT DEFAULT NULL,
|
||||||
position INTEGER NOT NULL DEFAULT 0,
|
position INTEGER NOT NULL DEFAULT 0,
|
||||||
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
)
|
)
|
||||||
");
|
");
|
||||||
|
// Migration: add default_repo column if missing
|
||||||
|
$cols = $db->query("PRAGMA table_info(gitea_accounts)")->fetchAll(PDO::FETCH_COLUMN, 1);
|
||||||
|
if (!in_array('default_repo', $cols)) {
|
||||||
|
$db->exec("ALTER TABLE gitea_accounts ADD COLUMN default_repo TEXT DEFAULT NULL");
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// ── Encryption helpers (mirrors email plugin / CalDavSync) ────────
|
// ── Encryption helpers (mirrors email plugin / CalDavSync) ────────
|
||||||
@@ -85,7 +91,7 @@ PluginManager::instance()->onApiRoute(function (string $route, string $method) {
|
|||||||
|
|
||||||
if ($route === '/api/gitea/accounts' && $method === 'GET') {
|
if ($route === '/api/gitea/accounts' && $method === 'GET') {
|
||||||
$db = Database::connect();
|
$db = Database::connect();
|
||||||
$rows = $db->query('SELECT id, name, base_url, position, created_at FROM gitea_accounts ORDER BY position ASC, id ASC')->fetchAll();
|
$rows = $db->query('SELECT id, name, base_url, default_repo, position, created_at FROM gitea_accounts ORDER BY position ASC, id ASC')->fetchAll();
|
||||||
giteaJson($rows);
|
giteaJson($rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +138,10 @@ PluginManager::instance()->onApiRoute(function (string $route, string $method) {
|
|||||||
if (!empty($input['token'])) {
|
if (!empty($input['token'])) {
|
||||||
$fields[] = 'token = :token'; $params['token'] = giteaEncrypt($input['token']);
|
$fields[] = 'token = :token'; $params['token'] = giteaEncrypt($input['token']);
|
||||||
}
|
}
|
||||||
|
if (array_key_exists('default_repo', $input)) {
|
||||||
|
$val = trim((string)($input['default_repo'] ?? ''));
|
||||||
|
$fields[] = 'default_repo = :default_repo'; $params['default_repo'] = $val ?: null;
|
||||||
|
}
|
||||||
if (!$fields) giteaJson(['ok' => true]);
|
if (!$fields) giteaJson(['ok' => true]);
|
||||||
$db = Database::connect();
|
$db = Database::connect();
|
||||||
$db->prepare('UPDATE gitea_accounts SET ' . implode(', ', $fields) . ' WHERE id = :id')->execute($params);
|
$db->prepare('UPDATE gitea_accounts SET ' . implode(', ', $fields) . ' WHERE id = :id')->execute($params);
|
||||||
|
|||||||
@@ -113,6 +113,10 @@ function buildSettingsPanel(panelEl) {
|
|||||||
<span class="font-pixel text-[9px] text-t-dim uppercase">access token <span id="gitea-tok-hint" class="text-t-muted normal-case text-[8px]"></span></span>
|
<span class="font-pixel text-[9px] text-t-dim uppercase">access token <span id="gitea-tok-hint" class="text-t-muted normal-case text-[8px]"></span></span>
|
||||||
<input id="gitea-acc-token" type="password" autocomplete="off" class="w-full bg-t-bg border border-t-border text-t-bright px-2 py-1.5 text-xs focus:border-t-accent focus:outline-none font-mono">
|
<input id="gitea-acc-token" type="password" autocomplete="off" class="w-full bg-t-bg border border-t-border text-t-bright px-2 py-1.5 text-xs focus:border-t-accent focus:outline-none font-mono">
|
||||||
</label>
|
</label>
|
||||||
|
<label class="block">
|
||||||
|
<span class="font-pixel text-[9px] text-t-dim uppercase">default repo <span class="text-t-muted normal-case text-[8px]">(owner/repo)</span></span>
|
||||||
|
<input id="gitea-acc-default-repo" type="text" placeholder="owner/repo" autocomplete="off" class="w-full bg-t-bg border border-t-border text-t-bright px-2 py-1.5 text-xs focus:border-t-accent focus:outline-none font-mono">
|
||||||
|
</label>
|
||||||
<div class="flex items-center gap-2 pt-1">
|
<div class="flex items-center gap-2 pt-1">
|
||||||
<button type="submit" id="gitea-acc-save" class="flex items-center gap-1.5 px-3 py-1.5 text-xs border border-t-accent text-t-accent hover:bg-t-accent/10 transition-colors"><i class="ph ph-floppy-disk text-sm"></i><span class="font-pixel text-[10px]">Save</span></button>
|
<button type="submit" id="gitea-acc-save" class="flex items-center gap-1.5 px-3 py-1.5 text-xs border border-t-accent text-t-accent hover:bg-t-accent/10 transition-colors"><i class="ph ph-floppy-disk text-sm"></i><span class="font-pixel text-[10px]">Save</span></button>
|
||||||
<button type="button" id="gitea-acc-test" class="flex items-center gap-1.5 px-3 py-1.5 text-xs border border-t-border text-t-muted hover:border-t-accent hover:text-t-accent transition-colors"><i class="ph ph-plug text-sm"></i><span class="font-pixel text-[10px]">Test</span></button>
|
<button type="button" id="gitea-acc-test" class="flex items-center gap-1.5 px-3 py-1.5 text-xs border border-t-border text-t-muted hover:border-t-accent hover:text-t-accent transition-colors"><i class="ph ph-plug text-sm"></i><span class="font-pixel text-[10px]">Test</span></button>
|
||||||
@@ -150,7 +154,7 @@ function renderAccountsList() {
|
|||||||
<i class="ph ph-git-pull-request text-t-accent text-base"></i>
|
<i class="ph ph-git-pull-request text-t-accent text-base"></i>
|
||||||
<div class="gitea-account-info">
|
<div class="gitea-account-info">
|
||||||
<div class="gitea-account-name">${escapeHtml(a.name)}</div>
|
<div class="gitea-account-name">${escapeHtml(a.name)}</div>
|
||||||
<div class="gitea-account-meta">${escapeHtml(a.base_url)}</div>
|
<div class="gitea-account-meta">${escapeHtml(a.base_url)}${a.default_repo ? ' · ' + escapeHtml(a.default_repo) : ''}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="gitea-account-actions">
|
<div class="gitea-account-actions">
|
||||||
<button class="toolbar-btn gitea-edit-btn" title="Edit"><i class="ph ph-pencil-simple text-sm"></i></button>
|
<button class="toolbar-btn gitea-edit-btn" title="Edit"><i class="ph ph-pencil-simple text-sm"></i></button>
|
||||||
@@ -201,6 +205,7 @@ function resetAccountForm() {
|
|||||||
$('gitea-acc-name').value = '';
|
$('gitea-acc-name').value = '';
|
||||||
$('gitea-acc-baseurl').value = '';
|
$('gitea-acc-baseurl').value = '';
|
||||||
$('gitea-acc-token').value = '';
|
$('gitea-acc-token').value = '';
|
||||||
|
$('gitea-acc-default-repo').value = '';
|
||||||
setAccountStatus('');
|
setAccountStatus('');
|
||||||
$('gitea-tok-hint').textContent = '';
|
$('gitea-tok-hint').textContent = '';
|
||||||
}
|
}
|
||||||
@@ -214,6 +219,7 @@ function editAccount(id) {
|
|||||||
$('gitea-acc-name').value = acc.name;
|
$('gitea-acc-name').value = acc.name;
|
||||||
$('gitea-acc-baseurl').value = acc.base_url;
|
$('gitea-acc-baseurl').value = acc.base_url;
|
||||||
$('gitea-acc-token').value = '';
|
$('gitea-acc-token').value = '';
|
||||||
|
$('gitea-acc-default-repo').value = acc.default_repo || '';
|
||||||
$('gitea-tok-hint').textContent = '(leave blank to keep existing)';
|
$('gitea-tok-hint').textContent = '(leave blank to keep existing)';
|
||||||
setAccountStatus('');
|
setAccountStatus('');
|
||||||
$('gitea-acc-name').focus();
|
$('gitea-acc-name').focus();
|
||||||
@@ -240,6 +246,7 @@ async function saveAccount(e) {
|
|||||||
name: $('gitea-acc-name').value.trim(),
|
name: $('gitea-acc-name').value.trim(),
|
||||||
base_url: $('gitea-acc-baseurl').value.trim(),
|
base_url: $('gitea-acc-baseurl').value.trim(),
|
||||||
token: $('gitea-acc-token').value,
|
token: $('gitea-acc-token').value,
|
||||||
|
default_repo: $('gitea-acc-default-repo').value.trim(),
|
||||||
};
|
};
|
||||||
if (!payload.name || !payload.base_url || (!editingAccountId && !payload.token)) {
|
if (!payload.name || !payload.base_url || (!editingAccountId && !payload.token)) {
|
||||||
setAccountStatus('name, base url, and token are required', 'error');
|
setAccountStatus('name, base url, and token are required', 'error');
|
||||||
@@ -713,8 +720,9 @@ async function openCreateForm() {
|
|||||||
$('gitea-create-form').classList.remove('hidden');
|
$('gitea-create-form').classList.remove('hidden');
|
||||||
$('gitea-create-form').classList.add('flex');
|
$('gitea-create-form').classList.add('flex');
|
||||||
|
|
||||||
// Reset form
|
// Reset form — pre-fill default repo if configured
|
||||||
$('gitea-create-repo').value = '';
|
const currentAccount = accounts.find(a => a.id === currentAccountId);
|
||||||
|
$('gitea-create-repo').value = currentAccount?.default_repo || '';
|
||||||
$('gitea-create-title').value = '';
|
$('gitea-create-title').value = '';
|
||||||
$('gitea-create-body').value = '';
|
$('gitea-create-body').value = '';
|
||||||
setCreateStatus('');
|
setCreateStatus('');
|
||||||
@@ -766,6 +774,8 @@ async function openCreateForm() {
|
|||||||
errBox.classList.remove('hidden');
|
errBox.classList.remove('hidden');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentAccount?.default_repo) loadCreateRepoLabels();
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateRepoHint() {
|
function updateRepoHint() {
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import { describe, it, afterEach, expect, $, $$, click, sleep, closeAll } from './runner.js?v=4';
|
||||||
|
|
||||||
|
async function openEditor() {
|
||||||
|
const card = document.querySelector('#board [data-id]');
|
||||||
|
if (!card) return false;
|
||||||
|
card.dispatchEvent(new MouseEvent('dblclick', { bubbles: true }));
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
if ($('#modal')?.classList.contains('open')) return true;
|
||||||
|
await sleep(100);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openPicker() {
|
||||||
|
click('#md-asset-picker');
|
||||||
|
for (let i = 0; i < 30; i++) {
|
||||||
|
if (document.getElementById('asset-picker-flyout')) return true;
|
||||||
|
await sleep(100);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Asset Picker', () => {
|
||||||
|
afterEach(async () => {
|
||||||
|
document.getElementById('asset-picker-flyout')?.remove();
|
||||||
|
await closeAll();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('toolbar button exists', () => {
|
||||||
|
expect($('#md-asset-picker')).toExist();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('opens flyout with search and grid, toggles closed on second click', async () => {
|
||||||
|
if (!await openEditor()) return;
|
||||||
|
if (!await openPicker()) return;
|
||||||
|
|
||||||
|
expect(document.getElementById('asset-picker-flyout')).toExist();
|
||||||
|
expect(document.getElementById('asset-picker-search')).toExist();
|
||||||
|
expect(document.getElementById('asset-picker-grid')).toExist();
|
||||||
|
|
||||||
|
// Second click closes
|
||||||
|
click('#md-asset-picker');
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
if (!document.getElementById('asset-picker-flyout')) break;
|
||||||
|
await sleep(50);
|
||||||
|
}
|
||||||
|
expect(document.getElementById('asset-picker-flyout')).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('search input filters tiles', async () => {
|
||||||
|
if (!await openEditor()) return;
|
||||||
|
if (!await openPicker()) return;
|
||||||
|
|
||||||
|
const search = document.getElementById('asset-picker-search');
|
||||||
|
if (!search) return;
|
||||||
|
|
||||||
|
search.value = 'zzz_nonexistent_zzz';
|
||||||
|
search.dispatchEvent(new Event('input', { bubbles: true }));
|
||||||
|
await sleep(50);
|
||||||
|
const grid = document.getElementById('asset-picker-grid');
|
||||||
|
expect(grid.querySelectorAll('.asset-pick-tile').length).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -180,6 +180,7 @@ export async function closeAll() {
|
|||||||
document.querySelector('.bucket-picker')?.remove();
|
document.querySelector('.bucket-picker')?.remove();
|
||||||
document.querySelector('.orphan-lightbox')?.remove();
|
document.querySelector('.orphan-lightbox')?.remove();
|
||||||
document.getElementById('bucket-super-popover')?.remove();
|
document.getElementById('bucket-super-popover')?.remove();
|
||||||
|
document.getElementById('asset-picker-flyout')?.remove();
|
||||||
document.getElementById('gitea-overlay')?.classList.remove('open');
|
document.getElementById('gitea-overlay')?.classList.remove('open');
|
||||||
// Clear multi-select
|
// Clear multi-select
|
||||||
document.querySelectorAll('.card-selected').forEach(el => {
|
document.querySelectorAll('.card-selected').forEach(el => {
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ const FILES = [
|
|||||||
'./relay.test.js',
|
'./relay.test.js',
|
||||||
'./notifications.test.js',
|
'./notifications.test.js',
|
||||||
'./quick-capture.test.js',
|
'./quick-capture.test.js',
|
||||||
|
'./asset-picker.test.js',
|
||||||
'./theme.test.js',
|
'./theme.test.js',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user