Compare commits
No commits in common. "de8227f4f46bb0515981cc14492da015fb6a56a8" and "207df76b69fc1e02e039a9e31ab640e97e7aa5e7" have entirely different histories.
de8227f4f4
...
207df76b69
|
|
@ -4,11 +4,6 @@ html, body { height: 100%; margin: 0; background: var(--bg); color: var(--text);
|
||||||
#bg { position: fixed; inset: 0; z-index: 0; pointer-events: none; opacity: .35; }
|
#bg { position: fixed; inset: 0; z-index: 0; pointer-events: none; opacity: .35; }
|
||||||
header { position: sticky; top: 0; z-index: 20; padding: 12px 16px; display:flex; gap:16px; align-items:center; justify-content:space-between; background: linear-gradient(180deg, rgba(11,21,38,.95), rgba(11,21,38,.55), transparent); backdrop-filter: blur(4px); border-bottom: 1px solid #1b2d45; }
|
header { position: sticky; top: 0; z-index: 20; padding: 12px 16px; display:flex; gap:16px; align-items:center; justify-content:space-between; background: linear-gradient(180deg, rgba(11,21,38,.95), rgba(11,21,38,.55), transparent); backdrop-filter: blur(4px); border-bottom: 1px solid #1b2d45; }
|
||||||
.toolbar { display:flex; gap:10px; align-items:center; flex-wrap:wrap; }
|
.toolbar { display:flex; gap:10px; align-items:center; flex-wrap:wrap; }
|
||||||
.app-brand { display:flex; align-items:center; gap:6px; white-space:nowrap; }
|
|
||||||
.app-live-status { display:inline-flex; gap:6px; align-items:center; }
|
|
||||||
.app-menu { margin-left:auto; }
|
|
||||||
.app-menu > summary { display:none; }
|
|
||||||
.app-menu-panel { display:flex; gap:10px; align-items:center; flex-wrap:wrap; }
|
|
||||||
button { background: linear-gradient(180deg,#1f3a5f,#15324d); border:1px solid #2a496e; color:#e5e7eb; padding:8px 12px; border-radius:10px; cursor:pointer; }
|
button { background: linear-gradient(180deg,#1f3a5f,#15324d); border:1px solid #2a496e; color:#e5e7eb; padding:8px 12px; border-radius:10px; cursor:pointer; }
|
||||||
#sign-out-all { min-height:44px; }
|
#sign-out-all { min-height:44px; }
|
||||||
button:hover { filter: brightness(1.15); }
|
button:hover { filter: brightness(1.15); }
|
||||||
|
|
@ -68,9 +63,6 @@ textarea { resize: vertical; min-height: 120px; }
|
||||||
.event:last-child { border-bottom: 0; }
|
.event:last-child { border-bottom: 0; }
|
||||||
.my-work { grid-column: 1 / -1; }
|
.my-work { grid-column: 1 / -1; }
|
||||||
.my-work-header { display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; }
|
.my-work-header { display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; }
|
||||||
.work-settings { width:100%; }
|
|
||||||
.work-settings > summary { display:none; }
|
|
||||||
.work-settings-panel { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
|
|
||||||
.work-filters { display:flex; gap:8px; flex-wrap:wrap; }
|
.work-filters { display:flex; gap:8px; flex-wrap:wrap; }
|
||||||
.work-filter { min-height: 44px; }
|
.work-filter { min-height: 44px; }
|
||||||
.work-filter[aria-pressed="true"] { border-color:var(--accent); background:#1d4f7a; }
|
.work-filter[aria-pressed="true"] { border-color:var(--accent); background:#1d4f7a; }
|
||||||
|
|
@ -276,22 +268,8 @@ textarea { resize: vertical; min-height: 120px; }
|
||||||
.mobile-task-count { min-width:18px; min-height:18px; padding:1px 5px; border-radius:999px; background:#31577f; font-size:11px; line-height:16px; }
|
.mobile-task-count { min-width:18px; min-height:18px; padding:1px 5px; border-radius:999px; background:#31577f; font-size:11px; line-height:16px; }
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
body { padding-bottom:calc(66px + env(safe-area-inset-bottom)); }
|
body { padding-bottom:calc(66px + env(safe-area-inset-bottom)); }
|
||||||
header { min-height:56px; max-height:64px; padding:6px 10px; align-items:center; gap:8px; background:rgba(11,21,38,.98); }
|
header { align-items:flex-start; }
|
||||||
.app-brand .muted, #clock { display:none; }
|
|
||||||
.app-live-status { margin-left:auto; }
|
|
||||||
.app-menu { position:relative; margin-left:0; }
|
|
||||||
.app-menu > summary { min-width:44px; min-height:44px; display:grid; place-items:center; cursor:pointer; border:1px solid #2a496e; border-radius:10px; list-style:none; }
|
|
||||||
.app-menu > summary::-webkit-details-marker { display:none; }
|
|
||||||
.app-menu:not([open]) > .app-menu-panel { display:none; }
|
|
||||||
.app-menu-panel { position:absolute; top:calc(100% + 6px); right:0; width:min(280px,calc(100vw - 20px)); display:grid; gap:8px; padding:10px; border:1px solid #2a496e; border-radius:12px; background:#0b1526; box-shadow:0 18px 45px rgba(0,0,0,.5); }
|
|
||||||
.app-menu-panel button { min-height:44px; width:100%; }
|
|
||||||
.my-work { margin:0; }
|
.my-work { margin:0; }
|
||||||
.my-work-header { align-items:flex-start; }
|
|
||||||
.my-work-actions { width:100%; flex-wrap:nowrap; }
|
|
||||||
.my-work-actions button { min-height:44px; flex:1 1 0; padding-inline:6px; }
|
|
||||||
.work-settings > summary { min-height:44px; display:flex; align-items:center; cursor:pointer; padding:0 10px; border:1px solid #2a496e; border-radius:10px; font-weight:700; }
|
|
||||||
.work-settings:not([open]) > .work-settings-panel { display:none; }
|
|
||||||
.work-settings-panel { display:grid; gap:10px; margin-top:8px; }
|
|
||||||
.my-work-list { grid-template-columns:1fr; }
|
.my-work-list { grid-template-columns:1fr; }
|
||||||
.work-filters { width:100%; }
|
.work-filters { width:100%; }
|
||||||
.work-filter { flex:1 1 calc(50% - 8px); }
|
.work-filter { flex:1 1 calc(50% - 8px); }
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,6 @@
|
||||||
(function(){
|
(function(){
|
||||||
const qs = (s, el=document) => el.querySelector(s);
|
const qs = (s, el=document) => el.querySelector(s);
|
||||||
const fmt = (d) => new Date(d).toLocaleString();
|
const fmt = (d) => new Date(d).toLocaleString();
|
||||||
[
|
|
||||||
[qs('.app-menu'), qs('#app-menu-toggle')],
|
|
||||||
[qs('.work-settings'), qs('#work-settings-toggle')],
|
|
||||||
].forEach(([disclosure, launcher]) => {
|
|
||||||
mobileLaunch.createDisclosure({disclosure, launcher}).start();
|
|
||||||
});
|
|
||||||
const PANEL_STATE_KEY = "stackchain.panel-state.v1";
|
const PANEL_STATE_KEY = "stackchain.panel-state.v1";
|
||||||
const panels = Array.from(document.querySelectorAll('details[data-panel-key]'));
|
const panels = Array.from(document.querySelectorAll('details[data-panel-key]'));
|
||||||
let savedState = {};
|
let savedState = {};
|
||||||
|
|
@ -72,15 +66,9 @@
|
||||||
const WORK_MILESTONE_KEY = 'stackchain.my-work-milestone.v1';
|
const WORK_MILESTONE_KEY = 'stackchain.my-work-milestone.v1';
|
||||||
let selectedWorkFilter = 'all';
|
let selectedWorkFilter = 'all';
|
||||||
let selectedWorkMilestone = 'all';
|
let selectedWorkMilestone = 'all';
|
||||||
let savedWorkFilter = null;
|
|
||||||
let launchFilterResolved = false;
|
|
||||||
try {
|
try {
|
||||||
const savedFilter = sessionStorage.getItem(WORK_FILTER_KEY);
|
const savedFilter = sessionStorage.getItem(WORK_FILTER_KEY);
|
||||||
if (['all', 'today', 'attention', 'issue', 'pull', 'review', 'update', 'later', 'draft'].includes(savedFilter)) {
|
if (['all', 'today', 'attention', 'issue', 'pull', 'review', 'update', 'later', 'draft'].includes(savedFilter)) selectedWorkFilter = savedFilter;
|
||||||
selectedWorkFilter = savedFilter;
|
|
||||||
savedWorkFilter = savedFilter;
|
|
||||||
launchFilterResolved = true;
|
|
||||||
}
|
|
||||||
const savedMilestone = sessionStorage.getItem(WORK_MILESTONE_KEY);
|
const savedMilestone = sessionStorage.getItem(WORK_MILESTONE_KEY);
|
||||||
if (savedMilestone) selectedWorkMilestone = savedMilestone;
|
if (savedMilestone) selectedWorkMilestone = savedMilestone;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -633,23 +621,11 @@
|
||||||
counts.today = todayMyWork.length;
|
counts.today = todayMyWork.length;
|
||||||
counts.later = laterMyWork.length;
|
counts.later = laterMyWork.length;
|
||||||
counts.draft = lastDrafts.length;
|
counts.draft = lastDrafts.length;
|
||||||
if (!launchFilterResolved) {
|
|
||||||
selectedWorkFilter = mobileLaunch.chooseFilter({
|
|
||||||
saved: savedWorkFilter, today: counts.today, attention: counts.attention,
|
|
||||||
});
|
|
||||||
launchFilterResolved = true;
|
|
||||||
document.querySelectorAll('[data-work-filter]').forEach(item =>
|
|
||||||
item.setAttribute('aria-pressed', String(item.dataset.workFilter === selectedWorkFilter))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Object.entries(counts).forEach(([filter, count]) => {
|
Object.entries(counts).forEach(([filter, count]) => {
|
||||||
const element = qs('[data-work-count="' + filter + '"]');
|
const element = qs('[data-work-count="' + filter + '"]');
|
||||||
if (element) element.textContent = count;
|
if (element) element.textContent = count;
|
||||||
});
|
});
|
||||||
mobileTaskDock.updateAttention(counts.attention);
|
mobileTaskDock.updateAttention(counts.attention);
|
||||||
const activeQueue = qs('[data-work-filter="' + selectedWorkFilter + '"]');
|
|
||||||
qs('#active-work-queue').textContent = activeQueue.firstChild.textContent.trim() +
|
|
||||||
' (' + (counts[selectedWorkFilter] || 0) + ')';
|
|
||||||
const milestoneSelect = qs('#work-milestone-filter');
|
const milestoneSelect = qs('#work-milestone-filter');
|
||||||
const lanes = milestoneLanes(lastMyWork);
|
const lanes = milestoneLanes(lastMyWork);
|
||||||
milestoneSelect.innerHTML = '<option value="all">All milestones</option>' +
|
milestoneSelect.innerHTML = '<option value="all">All milestones</option>' +
|
||||||
|
|
@ -2928,8 +2904,6 @@
|
||||||
button.setAttribute('aria-pressed', String(button.dataset.workFilter === selectedWorkFilter));
|
button.setAttribute('aria-pressed', String(button.dataset.workFilter === selectedWorkFilter));
|
||||||
button.addEventListener('click', () => {
|
button.addEventListener('click', () => {
|
||||||
selectedWorkFilter = button.dataset.workFilter;
|
selectedWorkFilter = button.dataset.workFilter;
|
||||||
savedWorkFilter = selectedWorkFilter;
|
|
||||||
launchFilterResolved = true;
|
|
||||||
try {
|
try {
|
||||||
sessionStorage.setItem(WORK_FILTER_KEY, selectedWorkFilter);
|
sessionStorage.setItem(WORK_FILTER_KEY, selectedWorkFilter);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -2938,8 +2912,6 @@
|
||||||
document.querySelectorAll('[data-work-filter]').forEach(item =>
|
document.querySelectorAll('[data-work-filter]').forEach(item =>
|
||||||
item.setAttribute('aria-pressed', String(item === button))
|
item.setAttribute('aria-pressed', String(item === button))
|
||||||
);
|
);
|
||||||
const selectedCount = button.querySelector('[data-work-count]').textContent;
|
|
||||||
qs('#active-work-queue').textContent = button.firstChild.textContent.trim() + ' (' + selectedCount + ')';
|
|
||||||
renderMyWork();
|
renderMyWork();
|
||||||
updateWorkPaginationControls();
|
updateWorkPaginationControls();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -11,18 +11,15 @@
|
||||||
<body>
|
<body>
|
||||||
<canvas id="bg"></canvas>
|
<canvas id="bg"></canvas>
|
||||||
<header>
|
<header>
|
||||||
<div class="app-brand"><span class="obi"></span><strong>Stackchain</strong><span class="muted">Dashboard</span></div>
|
<div><span class="obi"></span> <strong style="margin-left:6px;">Stackchain</strong> <span class="muted">Dashboard</span></div>
|
||||||
<div class="app-live-status"><span class="dot"></span><span class="small" id="status">Live</span></div>
|
<div class="toolbar">
|
||||||
<details class="app-menu">
|
<div class="status"><span class="dot"></span><span class="small" id="status">Live</span></div>
|
||||||
<summary id="app-menu-toggle" aria-label="Open dashboard menu">Menu</summary>
|
|
||||||
<div class="app-menu-panel">
|
|
||||||
<button id="refresh">Refresh</button>
|
<button id="refresh">Refresh</button>
|
||||||
<button id="open-palette">Command</button>
|
|
||||||
<button id="sign-out" type="button">Sign out & clear this device</button>
|
<button id="sign-out" type="button">Sign out & clear this device</button>
|
||||||
<button id="sign-out-all" type="button">Sign out all devices</button>
|
<button id="sign-out-all" type="button">Sign out all devices</button>
|
||||||
|
<button id="open-palette">Command</button>
|
||||||
<span class="small muted" id="clock"></span>
|
<span class="small muted" id="clock"></span>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
|
||||||
</header>
|
</header>
|
||||||
<div class="offline-status" id="offline-status" role="status" aria-live="polite" hidden>
|
<div class="offline-status" id="offline-status" role="status" aria-live="polite" hidden>
|
||||||
Offline · live Gitea data is unavailable. Saved drafts remain available on this device.
|
Offline · live Gitea data is unavailable. Saved drafts remain available on this device.
|
||||||
|
|
@ -40,9 +37,6 @@
|
||||||
<button class="find-work-action" id="find-work" type="button">Find work</button>
|
<button class="find-work-action" id="find-work" type="button">Find work</button>
|
||||||
<button class="new-issue" id="new-issue" type="button">New issue</button>
|
<button class="new-issue" id="new-issue" type="button">New issue</button>
|
||||||
</div>
|
</div>
|
||||||
<details class="work-settings">
|
|
||||||
<summary id="work-settings-toggle">Queue & settings · <span id="active-work-queue">All</span></summary>
|
|
||||||
<div class="work-settings-panel">
|
|
||||||
<div class="work-filters" aria-label="Filter My Work">
|
<div class="work-filters" aria-label="Filter My Work">
|
||||||
<button class="work-filter" data-work-filter="all" aria-pressed="true">All <span data-work-count="all">0</span></button>
|
<button class="work-filter" data-work-filter="all" aria-pressed="true">All <span data-work-count="all">0</span></button>
|
||||||
<button class="work-filter" data-work-filter="today" aria-pressed="false">Today <span data-work-count="today">0</span></button>
|
<button class="work-filter" data-work-filter="today" aria-pressed="false">Today <span data-work-count="today">0</span></button>
|
||||||
|
|
@ -75,8 +69,6 @@
|
||||||
<span class="small" id="install-app-status" role="status" aria-live="polite"></span>
|
<span class="small" id="install-app-status" role="status" aria-live="polite"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
|
||||||
</div>
|
|
||||||
<div class="my-work-list" id="my-work-list"></div>
|
<div class="my-work-list" id="my-work-list"></div>
|
||||||
<div class="small" id="work-page-status" aria-live="polite"></div>
|
<div class="small" id="work-page-status" aria-live="polite"></div>
|
||||||
<button class="load-more-work" id="load-more-work" type="button" hidden>Load older work</button>
|
<button class="load-more-work" id="load-more-work" type="button" hidden>Load older work</button>
|
||||||
|
|
@ -524,7 +516,6 @@
|
||||||
<script src="static/work-route.js"></script>
|
<script src="static/work-route.js"></script>
|
||||||
<script src="static/context-poller.js"></script>
|
<script src="static/context-poller.js"></script>
|
||||||
<script src="static/mobile-task-dock.js"></script>
|
<script src="static/mobile-task-dock.js"></script>
|
||||||
<script src="static/mobile-launch.js"></script>
|
|
||||||
<script src="static/install-app.js"></script>
|
<script src="static/install-app.js"></script>
|
||||||
<script src="static/dashboard.js"></script>
|
<script src="static/dashboard.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
(function (root, factory) {
|
|
||||||
const api = factory();
|
|
||||||
if (typeof module === 'object' && module.exports) module.exports = api;
|
|
||||||
else root.mobileLaunch = api;
|
|
||||||
})(typeof globalThis !== 'undefined' ? globalThis : this, function () {
|
|
||||||
const allowedFilters = new Set([
|
|
||||||
'all', 'today', 'attention', 'issue', 'pull', 'review', 'update', 'later', 'draft',
|
|
||||||
]);
|
|
||||||
|
|
||||||
function chooseFilter({ saved, today = 0, attention = 0 } = {}) {
|
|
||||||
if (allowedFilters.has(saved)) return saved;
|
|
||||||
if (today > 0) return 'today';
|
|
||||||
if (attention > 0) return 'attention';
|
|
||||||
return 'all';
|
|
||||||
}
|
|
||||||
|
|
||||||
function createDisclosure({ disclosure, launcher }) {
|
|
||||||
function onKeydown(event) {
|
|
||||||
if (event.key !== 'Escape' || !disclosure.open) return;
|
|
||||||
event.preventDefault();
|
|
||||||
disclosure.open = false;
|
|
||||||
launcher.focus();
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
start() {
|
|
||||||
disclosure.addEventListener('keydown', onKeydown);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return { chooseFilter, createDisclosure };
|
|
||||||
});
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
const BASE = new URL('./', self.location.href).pathname;
|
const BASE = new URL('./', self.location.href).pathname;
|
||||||
importScripts(BASE + 'static/background-issue-sync.js');
|
importScripts(BASE + 'static/background-issue-sync.js');
|
||||||
const CACHE = 'stackchain-dashboard-shell-v28';
|
const CACHE = 'stackchain-dashboard-shell-v27';
|
||||||
const OUTAGE_STATUSES = new Set([500, 502, 503, 504]);
|
const OUTAGE_STATUSES = new Set([500, 502, 503, 504]);
|
||||||
const SHELL = [
|
const SHELL = [
|
||||||
BASE,
|
BASE,
|
||||||
|
|
@ -32,7 +32,6 @@ const SHELL = [
|
||||||
BASE + 'static/work-route.js',
|
BASE + 'static/work-route.js',
|
||||||
BASE + 'static/context-poller.js',
|
BASE + 'static/context-poller.js',
|
||||||
BASE + 'static/mobile-task-dock.js',
|
BASE + 'static/mobile-task-dock.js',
|
||||||
BASE + 'static/mobile-launch.js',
|
|
||||||
BASE + 'static/install-app.js',
|
BASE + 'static/install-app.js',
|
||||||
BASE + 'static/background-issue-sync.js',
|
BASE + 'static/background-issue-sync.js',
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
import json
|
|
||||||
import subprocess
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from tests.dashboard_bundle import dashboard
|
|
||||||
|
|
||||||
|
|
||||||
MOBILE_LAUNCH = Path(__file__).resolve().parents[1] / "frontend" / "mobile-launch.js"
|
|
||||||
|
|
||||||
|
|
||||||
def test_mobile_launch_selects_priority_queue_without_overriding_saved_choice():
|
|
||||||
script = f"""
|
|
||||||
const mobileLaunch = require({json.dumps(str(MOBILE_LAUNCH))});
|
|
||||||
process.stdout.write(JSON.stringify({{
|
|
||||||
today: mobileLaunch.chooseFilter({{saved:null, today:2, attention:4}}),
|
|
||||||
attention: mobileLaunch.chooseFilter({{saved:null, today:0, attention:4}}),
|
|
||||||
all: mobileLaunch.chooseFilter({{saved:null, today:0, attention:0}}),
|
|
||||||
saved: mobileLaunch.chooseFilter({{saved:'review', today:2, attention:4}}),
|
|
||||||
}}));
|
|
||||||
"""
|
|
||||||
result = subprocess.run(["node", "-e", script], capture_output=True, text=True)
|
|
||||||
|
|
||||||
assert result.returncode == 0, result.stderr
|
|
||||||
assert json.loads(result.stdout) == {
|
|
||||||
"today": "today",
|
|
||||||
"attention": "attention",
|
|
||||||
"all": "all",
|
|
||||||
"saved": "review",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def test_mobile_disclosure_closes_on_escape_and_restores_launcher_focus():
|
|
||||||
script = f"""
|
|
||||||
const mobileLaunch = require({json.dumps(str(MOBILE_LAUNCH))});
|
|
||||||
const listeners = {{}};
|
|
||||||
const disclosure = {{open:true, addEventListener(name, fn) {{ listeners[name] = fn; }}}};
|
|
||||||
const launcher = {{focuses:0, focus() {{ this.focuses += 1; }}}};
|
|
||||||
const controller = mobileLaunch.createDisclosure({{disclosure, launcher}});
|
|
||||||
controller.start();
|
|
||||||
let prevented = false;
|
|
||||||
listeners.keydown({{key:'Escape', preventDefault() {{ prevented = true; }}}});
|
|
||||||
process.stdout.write(JSON.stringify({{open:disclosure.open, focuses:launcher.focuses, prevented}}));
|
|
||||||
"""
|
|
||||||
result = subprocess.run(["node", "-e", script], capture_output=True, text=True)
|
|
||||||
|
|
||||||
assert result.returncode == 0, result.stderr
|
|
||||||
assert json.loads(result.stdout) == {"open": False, "focuses": 1, "prevented": True}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.anyio
|
|
||||||
async def test_mobile_launch_progressively_discloses_secondary_controls():
|
|
||||||
html = await dashboard()
|
|
||||||
|
|
||||||
assert 'class="app-brand"' in html
|
|
||||||
assert 'class="app-live-status"' in html
|
|
||||||
assert 'class="app-menu"' in html
|
|
||||||
assert 'id="app-menu-toggle"' in html
|
|
||||||
assert 'class="work-settings"' in html
|
|
||||||
assert 'id="work-settings-toggle"' in html
|
|
||||||
assert 'id="active-work-queue"' in html
|
|
||||||
assert '<script src="static/mobile-launch.js"></script>' in html
|
|
||||||
service_worker = (Path(__file__).resolve().parents[1] / "frontend" / "service-worker.js").read_text()
|
|
||||||
assert "BASE + 'static/mobile-launch.js'" in service_worker
|
|
||||||
assert "mobileLaunch.chooseFilter" in html
|
|
||||||
assert "mobileLaunch.createDisclosure" in html
|
|
||||||
assert "@media (max-width: 600px)" in html
|
|
||||||
assert "header { min-height:56px; max-height:64px;" in html
|
|
||||||
assert ".work-settings:not([open]) > .work-settings-panel { display:none; }" in html
|
|
||||||
assert ".app-menu:not([open]) > .app-menu-panel { display:none; }" in html
|
|
||||||
assert ".my-work-actions button { min-height:44px;" in html
|
|
||||||
|
|
@ -95,7 +95,7 @@ async function dispatchNotificationClick(route) {{
|
||||||
def test_strict_browser_assets_ship_in_a_new_shell_cache():
|
def test_strict_browser_assets_ship_in_a_new_shell_cache():
|
||||||
source = WORKER.read_text()
|
source = WORKER.read_text()
|
||||||
|
|
||||||
assert "stackchain-dashboard-shell-v28" in source
|
assert "stackchain-dashboard-shell-v27" in source
|
||||||
assert "BASE + 'static/dashboard.css'" in source
|
assert "BASE + 'static/dashboard.css'" in source
|
||||||
assert "BASE + 'static/dashboard.js'" in source
|
assert "BASE + 'static/dashboard.js'" in source
|
||||||
assert "BASE + 'static/install-app.js'" in source
|
assert "BASE + 'static/install-app.js'" in source
|
||||||
|
|
@ -234,7 +234,6 @@ def test_install_precaches_complete_subpath_scoped_app_shell():
|
||||||
"/dashboard/static/work-route.js",
|
"/dashboard/static/work-route.js",
|
||||||
"/dashboard/static/context-poller.js",
|
"/dashboard/static/context-poller.js",
|
||||||
"/dashboard/static/mobile-task-dock.js",
|
"/dashboard/static/mobile-task-dock.js",
|
||||||
"/dashboard/static/mobile-launch.js",
|
|
||||||
"/dashboard/static/install-app.js",
|
"/dashboard/static/install-app.js",
|
||||||
"/dashboard/static/background-issue-sync.js",
|
"/dashboard/static/background-issue-sync.js",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user