create-pmos 0.52.0 → 0.53.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/KIT-VERSION +2 -2
- package/payload/mods/pmos-cockpit/README.md +13 -0
- package/payload/mods/pmos-cockpit/hooks/lib/commands.mjs +2 -1
- package/payload/mods/pmos-cockpit/hooks/lib/grants.mjs +41 -11
- package/payload/mods/pmos-cockpit/hooks/lib/guard.mjs +228 -8
- package/payload/mods/pmos-cockpit/hooks/register.tsx +11 -3
- package/payload/planning/evals/eval-calibration.md +1 -1
- package/payload/planning/okrs/health-budgets.md +1 -1
- package/payload/scripts/plan-items-stage.js +271 -0
- package/payload/scripts/pmos-log.sh +18 -7
- package/payload/scripts/workflow-state.js +28 -2
- package/payload/state/discoveries.md +1 -1
- package/payload/state/log.md +1 -1
- package/workspace/README.md +2 -0
- package/workspace/REMOTE.md +24 -63
- package/workspace/bin/pmos.js +19 -3
- package/workspace/cut-stub.js +40 -0
- package/workspace/first-paint-audit.js +145 -0
- package/workspace/fixtures/capture/requirements/capture-2026-10-04-1.md +10 -0
- package/workspace/fixtures/initiatives-api/list.json +176 -0
- package/workspace/fixtures/initiatives-api/post-403.json +5 -0
- package/workspace/fixtures/initiatives-api/post-ok.json +10 -0
- package/workspace/fixtures/initiatives-api/roadmap.json +208 -0
- package/workspace/fixtures/initiatives-api/sheet.json +112 -0
- package/workspace/fixtures/report-api/draft.json +177 -0
- package/workspace/fixtures/reports-page/draft-biweekly-2026-10-16.md +97 -0
- package/workspace/fixtures/today-api/provider-rows.json +204 -0
- package/workspace/fixtures/today-api/seam-probe-kinds.json +5 -0
- package/workspace/guide/board.md +81 -0
- package/workspace/guide/breakdown.md +154 -0
- package/workspace/guide/command-palette.md +75 -0
- package/workspace/guide/index.md +28 -17
- package/workspace/guide/initiatives-roadmap.md +130 -0
- package/workspace/guide/initiatives-screen.md +89 -0
- package/workspace/guide/initiatives-timeline.md +57 -0
- package/workspace/guide/integrated-work.md +94 -0
- package/workspace/guide/knowledge-graph.md +3 -68
- package/workspace/guide/launcher.md +51 -0
- package/workspace/guide/layout.md +102 -32
- package/workspace/guide/live-notes.md +3 -3
- package/workspace/guide/pm-only-acts.md +89 -0
- package/workspace/guide/pm-only-lines.md +61 -0
- package/workspace/guide/proactive-engine.md +21 -5
- package/workspace/guide/reports-page.md +80 -0
- package/workspace/guide/reports.md +73 -0
- package/workspace/guide/timeline.md +70 -0
- package/workspace/guide/today.md +85 -0
- package/workspace/guide/validate-with-typesafe.md +1 -1
- package/workspace/lib/actor.js +91 -0
- package/workspace/lib/board-cache.js +32 -2
- package/workspace/lib/board-cli.js +108 -0
- package/workspace/lib/board-fold.js +232 -0
- package/workspace/lib/breakdown-export.js +75 -0
- package/workspace/lib/brief.js +20 -2
- package/workspace/lib/capture.js +98 -0
- package/workspace/lib/engine/plan-items-stage.js +271 -0
- package/workspace/lib/engine/workflow-state.js +28 -2
- package/workspace/lib/factory-join.js +158 -0
- package/workspace/lib/goals.js +165 -0
- package/workspace/lib/grant-mint.js +113 -0
- package/workspace/lib/health-rules-factory.js +92 -0
- package/workspace/lib/health-rules-plan.js +164 -0
- package/workspace/lib/health.js +79 -0
- package/workspace/lib/initiative-cli.js +222 -0
- package/workspace/lib/initiative-display.js +183 -0
- package/workspace/lib/initiative-needs.js +127 -0
- package/workspace/lib/initiative-rows.js +210 -0
- package/workspace/lib/initiative-writer.js +141 -0
- package/workspace/lib/issues.js +206 -0
- package/workspace/lib/item-cli.js +195 -0
- package/workspace/lib/item-spans.js +137 -0
- package/workspace/lib/launcher-cli.js +207 -0
- package/workspace/lib/measure-cli.js +100 -0
- package/workspace/lib/measurements.js +189 -0
- package/workspace/lib/mobile-nav.js +57 -53
- package/workspace/lib/needs-providers.js +120 -0
- package/workspace/lib/placements.js +440 -0
- package/workspace/lib/plan-items.js +922 -0
- package/workspace/lib/plan-ledgers.js +85 -0
- package/workspace/lib/plan-rules.js +72 -0
- package/workspace/lib/plan-tree.js +380 -0
- package/workspace/lib/pm-guard.js +174 -0
- package/workspace/lib/pm-lines-needs.js +331 -0
- package/workspace/lib/pmos-verbs.js +69 -0
- package/workspace/lib/proactive-cli.js +58 -2
- package/workspace/lib/proactive.js +9 -6
- package/workspace/lib/qr.js +293 -0
- package/workspace/lib/remote-access.js +93 -1
- package/workspace/lib/report-cli.js +152 -0
- package/workspace/lib/report-draft.js +578 -0
- package/workspace/lib/report-needs.js +213 -0
- package/workspace/lib/route-modules.js +128 -0
- package/workspace/lib/routes-board.js +91 -0
- package/workspace/lib/routes-capture.js +52 -0
- package/workspace/lib/routes-initiatives.js +371 -0
- package/workspace/lib/routes-reports.js +163 -0
- package/workspace/lib/routes-timeline.js +197 -0
- package/workspace/lib/routes-today.js +32 -0
- package/workspace/lib/today-cli.js +99 -0
- package/workspace/lib/today.js +333 -0
- package/workspace/lib/triage.js +163 -0
- package/workspace/lib/verify-work-cli.js +81 -0
- package/workspace/lib/work-check-needs.js +99 -0
- package/workspace/package-lock.json +1 -1
- package/workspace/package.json +4 -5
- package/workspace/public/icons/apple-touch-icon.png +0 -0
- package/workspace/public/icons/icon-192.png +0 -0
- package/workspace/public/icons/icon-512.png +0 -0
- package/workspace/public/index.html +40 -19
- package/workspace/public/pm/app.js +330 -30
- package/workspace/public/pm/bd-board.js +113 -0
- package/workspace/public/pm/bd-drag.js +59 -0
- package/workspace/public/pm/bd-model.js +152 -0
- package/workspace/public/pm/bd-timeline.js +233 -0
- package/workspace/public/pm/bd-tree.js +244 -0
- package/workspace/public/pm/board-copy.js +57 -0
- package/workspace/public/pm/breakdown-api.js +58 -0
- package/workspace/public/pm/breakdown-copy.js +138 -0
- package/workspace/public/pm/components.css +3135 -0
- package/workspace/public/pm/cycle-review.js +125 -0
- package/workspace/public/pm/data.js +40 -187
- package/workspace/public/pm/dest-board.js +438 -0
- package/workspace/public/pm/dest-initiatives.js +134 -0
- package/workspace/public/pm/dest-reports.js +270 -0
- package/workspace/public/pm/dest-settings.js +217 -0
- package/workspace/public/pm/dest-today.js +182 -0
- package/workspace/public/pm/dialogs.js +88 -0
- package/workspace/public/pm/display-word.js +56 -0
- package/workspace/public/pm/dock.js +175 -0
- package/workspace/public/pm/fixture.js +8 -227
- package/workspace/public/pm/frame-copy.js +99 -0
- package/workspace/public/pm/handoff-box.js +82 -0
- package/workspace/public/pm/http.js +88 -0
- package/workspace/public/pm/icons.js +53 -0
- package/workspace/public/pm/initiative-list.js +218 -0
- package/workspace/public/pm/initiative-sheet.js +261 -0
- package/workspace/public/pm/initiatives-api.js +59 -0
- package/workspace/public/pm/initiatives-copy.js +215 -0
- package/workspace/public/pm/initiatives-timeline-copy.js +59 -0
- package/workspace/public/pm/initiatives-timeline.js +410 -0
- package/workspace/public/pm/initiatives-ui.js +123 -0
- package/workspace/public/pm/item-sheet.js +251 -0
- package/workspace/public/pm/keep-card.js +204 -0
- package/workspace/public/pm/lifecycle.js +7 -1
- package/workspace/public/pm/mobile.css +49 -20
- package/workspace/public/pm/mobile.js +157 -29
- package/workspace/public/pm/modes-live.js +7 -883
- package/workspace/public/pm/modes.js +32 -1024
- package/workspace/public/pm/new-initiative-sheet.js +74 -0
- package/workspace/public/pm/next-step-ui.js +3 -2
- package/workspace/public/pm/palette-copy.js +51 -0
- package/workspace/public/pm/palette.js +312 -0
- package/workspace/public/pm/panel-breakdown.js +702 -0
- package/workspace/public/pm/panel-cockpit.js +63 -295
- package/workspace/public/pm/panel-detail.js +25 -172
- package/workspace/public/pm/panel-initiatives.js +1 -19
- package/workspace/public/pm/panel-repos.js +31 -81
- package/workspace/public/pm/panel-tabs.js +200 -111
- package/workspace/public/pm/panel-trees.js +5 -2
- package/workspace/public/pm/portfolio-report.js +61 -0
- package/workspace/public/pm/primitives.js +656 -0
- package/workspace/public/pm/print.css +33 -0
- package/workspace/public/pm/provider-cards.js +136 -0
- package/workspace/public/pm/registry.js +194 -0
- package/workspace/public/pm/release-card.js +110 -0
- package/workspace/public/pm/report-view.js +309 -0
- package/workspace/public/pm/reports-copy.js +114 -0
- package/workspace/public/pm/roadmap.js +271 -0
- package/workspace/public/pm/sig-watch.js +41 -0
- package/workspace/public/pm/state.js +8 -4
- package/workspace/public/pm/status-banner.js +13 -5
- package/workspace/public/pm/tab-doc.js +2 -4
- package/workspace/public/pm/tab-term.js +12 -2
- package/workspace/public/pm/tab-web.js +3 -2
- package/workspace/public/pm/timeline-copy.js +48 -0
- package/workspace/public/pm/today-cards.js +244 -0
- package/workspace/public/pm/today-copy.js +126 -0
- package/workspace/public/pm/today-goals.js +172 -0
- package/workspace/public/pm/tokens.css +16 -18
- package/workspace/public/pm/topbar.js +102 -0
- package/workspace/public/pm/triage-card.js +60 -0
- package/workspace/public/pm/undo-hold.js +103 -0
- package/workspace/public/pm/view-addrepo.js +2 -1
- package/workspace/public/pm/view-livenotes.js +3 -1
- package/workspace/public/pm/view-today.js +7 -162
- package/workspace/public/vendor/Sortable.min.js +2 -0
- package/workspace/public/vendor/lucide-sprite.js +79 -0
- package/workspace/replaced-tests.json +2877 -0
- package/workspace/run-tests.js +56 -5
- package/workspace/server.js +446 -40
- package/workspace/sheet-answer.js +61 -0
- package/workspace/skills/measure.skill +41 -0
- package/workspace/skills/morning-brief.skill +15 -9
- package/workspace/skills/report-biweekly.skill +23 -25
- package/workspace/skills/tracker-refresh.skill +50 -0
- package/workspace/test-files.json +21 -3
- package/workspace/test-lists/base.json +6 -0
- package/workspace/test-lists/run2-a.json +6 -0
- package/workspace/test-lists/run2-b.json +13 -0
- package/workspace/test-lists/run2-c.json +19 -0
- package/workspace/test-lists/run2-d.json +22 -0
- package/workspace/test-lists/run3-0.json +5 -0
- package/workspace/test-lists/run3-a.json +5 -0
- package/workspace/test-lists/run3-b.json +6 -0
- package/workspace/test-lists/run3-c.json +15 -0
- package/workspace/test-lists/run3-d.json +6 -0
- package/workspace/test-lists/run4-a.json +8 -0
- package/workspace/test-lists/run4-b.json +6 -0
- package/workspace/test-lists/run4-c.json +13 -0
- package/workspace/test-lists/run4-d.json +9 -0
- package/workspace/test-lists/run5-a.json +6 -0
- package/workspace/test-lists/run5-b.json +6 -0
- package/workspace/test-lists/run5-c.json +15 -0
- package/workspace/test-lists/workspace-launcher.json +5 -0
- package/workspace/test-lists/workspace-phone-app.json +5 -0
- package/workspace/test-run.js +27 -1
- package/workspace/third-party/README.md +44 -0
- package/workspace/third-party/lucide-static-1.52.0.LICENSE +43 -0
- package/workspace/third-party/sortablejs-1.15.7.LICENSE +21 -0
- package/workspace/design-parity.js +0 -673
- package/workspace/public/pm/tab-task.js +0 -86
- package/workspace/public/pm/view-guide.js +0 -141
- package/workspace/public/pm/view-knowledge.js +0 -225
- package/workspace/public/pm/view-memory.js +0 -122
- package/workspace/public/pm/view-portfolio.js +0 -153
- package/workspace/public/pm/view-reports.js +0 -190
- package/workspace/public/pm/view-scheduled.js +0 -161
- package/workspace/public/pm/view-skills.js +0 -216
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/* pm/topbar.js — the frame's one top bar (pm-os-absorb Run 3, slice 3A; PRD R9, R10).
|
|
2
|
+
*
|
|
3
|
+
* Repository ▾ · Today Initiatives Board Reports · ⌘K · Sync (only when unsynced) · Settings
|
|
4
|
+
*
|
|
5
|
+
* The bar is built once and updated on every render: app.js calls `bar.update(model)` and the bar changes only what
|
|
6
|
+
* the model changed, so a focused control keeps its focus across a repaint. It holds no state of its own except the
|
|
7
|
+
* last sync reading of each repository, which it reads from local git through data.js (no network: GET /api/sync/status
|
|
8
|
+
* runs `git status` against the remote-tracking ref the last fetch left).
|
|
9
|
+
*
|
|
10
|
+
* createTopbar({ go, openPalette, repoMenu, sync }) → { node, update(model) }
|
|
11
|
+
* go(id) open destination id (today, initiatives, board, reports, settings)
|
|
12
|
+
* openPalette() open ⌘K
|
|
13
|
+
* repoMenu(anchor) open the Repository menu under `anchor`
|
|
14
|
+
* sync(repo) run Sync for `repo`; resolves to the server's answer
|
|
15
|
+
* model = { dest, repoLabel, needs, unsynced, syncing }
|
|
16
|
+
*
|
|
17
|
+
* Hooks the suites find things by: [data-fr="bar"], [data-fr="repo"], [data-fr-dest="<id>"] (aria-current="page" on
|
|
18
|
+
* the open one), [data-today-badge] (the Today count, seams §2.6), [data-fr="search"], [data-fr="sync"].
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { el, setChildren } from './dom.js';
|
|
22
|
+
import { button, needsDot, needsCount } from './primitives.js';
|
|
23
|
+
import { COPY } from './frame-copy.js';
|
|
24
|
+
|
|
25
|
+
/** The destinations the bar names, in order. Settings sits at the end of the bar, after Sync. */
|
|
26
|
+
export const BAR_DESTS = Object.freeze(['today', 'initiatives', 'board', 'reports']);
|
|
27
|
+
|
|
28
|
+
/** Is this sync reading "not in sync"? Behind, ahead or records not yet recorded. An unreadable status is not shown. */
|
|
29
|
+
export function unsyncedOf(st) {
|
|
30
|
+
return !!st && st.ok !== false && ((st.behind | 0) > 0 || (st.ahead | 0) > 0 || (st.dirty_records | 0) > 0);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function createTopbar({ go, openPalette, repoMenu, sync } = {}) {
|
|
34
|
+
const node = el('header', { class: 'fr-bar', 'data-shell': 'top', 'data-fr': 'bar' });
|
|
35
|
+
|
|
36
|
+
let repoBtn = null;
|
|
37
|
+
let repoLabel = null;
|
|
38
|
+
const repoSlot = el('div', { class: 'fr-bar__repo' });
|
|
39
|
+
|
|
40
|
+
const count = needsCount('0', { 'data-today-badge': '' });
|
|
41
|
+
const dot = needsDot();
|
|
42
|
+
const links = {};
|
|
43
|
+
for (const id of [...BAR_DESTS, 'settings']) {
|
|
44
|
+
links[id] = button({
|
|
45
|
+
label: COPY.nav[id], variant: 'ghost', icon: id === 'settings' ? 'settings' : undefined,
|
|
46
|
+
attrs: { class: 'fr-link', 'data-fr-dest': id, 'aria-current': 'false' },
|
|
47
|
+
onClick: () => go && go(id),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const todayMark = el('span', { class: 'fr-mark' }, dot, count);
|
|
51
|
+
links.today.appendChild(todayMark);
|
|
52
|
+
const nav = el('nav', { class: 'fr-nav', 'aria-label': COPY.nav.label }, BAR_DESTS.map((id) => links[id]));
|
|
53
|
+
|
|
54
|
+
const search = button({
|
|
55
|
+
label: COPY.search, variant: 'outline', icon: 'search',
|
|
56
|
+
attrs: { class: 'fr-search', 'data-fr': 'search', 'aria-keyshortcuts': 'Meta+K Control+K' },
|
|
57
|
+
onClick: () => openPalette && openPalette(),
|
|
58
|
+
});
|
|
59
|
+
search.appendChild(el('kbd', { class: 'fr-kbd' }, COPY.searchKey));
|
|
60
|
+
|
|
61
|
+
let syncBtn = null;
|
|
62
|
+
let syncLabel = null;
|
|
63
|
+
|
|
64
|
+
function repoButton(label) {
|
|
65
|
+
const b = button({
|
|
66
|
+
label, variant: 'ghost', iconEnd: 'chevron-down',
|
|
67
|
+
attrs: { class: 'fr-repo', 'data-fr': 'repo', 'aria-haspopup': 'menu', 'aria-label': COPY.repo.open(label) },
|
|
68
|
+
onClick: () => repoMenu && repoMenu(b),
|
|
69
|
+
});
|
|
70
|
+
return b;
|
|
71
|
+
}
|
|
72
|
+
function syncButton(label, busy) {
|
|
73
|
+
return button({
|
|
74
|
+
label, variant: 'outline', size: 'sm', disabled: busy,
|
|
75
|
+
attrs: { class: 'fr-sync', 'data-fr': 'sync', title: COPY.sync.title },
|
|
76
|
+
onClick: () => sync && sync(),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function update(m) {
|
|
81
|
+
const model = m || {};
|
|
82
|
+
if (model.repoLabel !== repoLabel) {
|
|
83
|
+
repoLabel = model.repoLabel;
|
|
84
|
+
repoBtn = repoButton(repoLabel || COPY.repo.none);
|
|
85
|
+
setChildren(repoSlot, [repoBtn]);
|
|
86
|
+
}
|
|
87
|
+
for (const id of Object.keys(links)) links[id].setAttribute('aria-current', id === model.dest ? 'page' : 'false');
|
|
88
|
+
const n = Math.max(0, Number(model.needs) || 0);
|
|
89
|
+
if (count.textContent !== String(n)) count.textContent = String(n);
|
|
90
|
+
todayMark.hidden = n === 0;
|
|
91
|
+
count.setAttribute('aria-label', COPY.needs(n));
|
|
92
|
+
const want = model.unsynced || model.syncing ? (model.syncing ? COPY.sync.busy : COPY.sync.label) : null;
|
|
93
|
+
if (want !== syncLabel) {
|
|
94
|
+
syncLabel = want;
|
|
95
|
+
syncBtn = want ? syncButton(want, !!model.syncing) : null;
|
|
96
|
+
}
|
|
97
|
+
setChildren(node, [repoSlot, nav, search, syncBtn, links.settings]);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
update({});
|
|
101
|
+
return { node, update, links };
|
|
102
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/* pm/triage-card.js — the triage card of Today, kind 6 (pm-os-absorb Run 2, slice 2D; PRD R12, R17).
|
|
2
|
+
*
|
|
3
|
+
* "Proposed: <title> · <lane> · <anchor> · Add". A capture was triaged by an agent; one press of Add writes the
|
|
4
|
+
* initiative (`pmos initiative new --from <capture>`), and it starts in Later. The row's run id ends with the capture's id.
|
|
5
|
+
*
|
|
6
|
+
* The writer takes a title, a lane and an anchor and no more, so the card reads them back from the row's own line. When the
|
|
7
|
+
* line says "no anchor yet", the writer would refuse the initiative: the card opens the New-initiative form with the title
|
|
8
|
+
* and the lane filled in, and the PM chooses the anchor.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { button, card, toast, ensureComponentsCss } from './primitives.js';
|
|
12
|
+
import { registerTodayCard } from './registry.js';
|
|
13
|
+
import { COPY } from './initiatives-copy.js';
|
|
14
|
+
import { createInitiative } from './initiatives-api.js';
|
|
15
|
+
import { changed } from './initiative-sheet.js';
|
|
16
|
+
import { openNewInitiative } from './new-initiative-sheet.js';
|
|
17
|
+
|
|
18
|
+
const captureOf = (row) => String(row.run_id || '').replace(/^initiative-needs:triage:/, '');
|
|
19
|
+
const titleOf = (q) => String(q || '').replace(/^Proposed:\s*/, '').split(' · ')[0];
|
|
20
|
+
|
|
21
|
+
/** "Proposed: <title> · <lane label> · <anchor>" → { title, lane, anchor }, or null. The anchor is null for "no anchor yet". */
|
|
22
|
+
export function proposalOf(question) {
|
|
23
|
+
const parts = String(question || '').replace(/^Proposed:\s*/, '').split(' · ');
|
|
24
|
+
if (parts.length < 3) return null;
|
|
25
|
+
const anchor = parts.pop().trim();
|
|
26
|
+
const lane = parts.pop().trim().replace(/\s+/g, '-');
|
|
27
|
+
const title = parts.join(' · ').trim();
|
|
28
|
+
return title && lane ? { title, lane, anchor: /^no anchor yet$/i.test(anchor) ? null : anchor } : null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function renderTriageCard(row, ctx) {
|
|
32
|
+
ensureComponentsCss();
|
|
33
|
+
let busy = false;
|
|
34
|
+
const add = button({
|
|
35
|
+
label: (row.today && row.today.act && row.today.act.label) || COPY.triage.add, variant: 'primary', attrs: { 'data-in-triage-add': '' },
|
|
36
|
+
onClick: async () => {
|
|
37
|
+
if (busy) return;
|
|
38
|
+
const p = proposalOf(row.question);
|
|
39
|
+
if (!p) { toast({ text: COPY.triage.addFailed(COPY.triage.unreadable), tone: 'error', timeout: 8000 }); return; }
|
|
40
|
+
if (!p.anchor) {
|
|
41
|
+
openNewInitiative({ repo: ctx.repo, ws: ctx.ws, anchors: [], prefill: { title: p.title, lane: p.lane, from: captureOf(row) }, onAdded: () => { changed(); try { window.dispatchEvent(new CustomEvent('pmos:ledgers', { detail: { changed: [ctx.ws] } })); } catch { /* no window */ } } });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
busy = true; add.disabled = true;
|
|
45
|
+
const out = await createInitiative(ctx.ws, { title: p.title, lane: p.lane, anchor: p.anchor, from: captureOf(row) });
|
|
46
|
+
busy = false; add.disabled = false;
|
|
47
|
+
if (out && out.ok) {
|
|
48
|
+
toast({ text: COPY.triage.added(titleOf(row.question)), timeout: 4000 });
|
|
49
|
+
changed();
|
|
50
|
+
try { window.dispatchEvent(new CustomEvent('pmos:ledgers', { detail: { changed: [ctx.ws] } })); } catch { /* no window */ }
|
|
51
|
+
} else toast({ text: COPY.triage.addFailed((out && out.error) || 'The server did not answer.'), tone: 'error', timeout: 8000 });
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
return card({
|
|
55
|
+
title: row.question, meta: [row.today && row.today.cause, row.today && row.today.evidence], trail: [add],
|
|
56
|
+
attrs: { class: 'in-today-card', 'data-today-row': 'triage', 'data-provider': row.provider || null, 'data-capture': captureOf(row) },
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
registerTodayCard('triage', renderTriageCard);
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/* pm/undo-hold.js — the Undo hold (pm-os-absorb Run 1, PRD R13/R21).
|
|
2
|
+
*
|
|
3
|
+
* A change that is hard to take back (Done, Withdraw, Withdraw all) is held in the page for 8 seconds before it is
|
|
4
|
+
* written. During the hold the screen already shows the change (an overlay on every fetched layout), and a toast offers
|
|
5
|
+
* Undo. Undo drops the change and writes nothing; otherwise the events are posted when the 8 seconds end. Leaving the page,
|
|
6
|
+
* or hiding it (iOS fires no `pagehide` when the phone locks or the PM switches apps, and may then discard the tab),
|
|
7
|
+
* posts every held change at once, with `keepalive`, so a held change is not lost by closing the tab. The Undo window
|
|
8
|
+
* then simply ends early.
|
|
9
|
+
*
|
|
10
|
+
* The hold is client state only. Nothing about it reaches a ledger until the write, and the write is the same POST any
|
|
11
|
+
* other change makes.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { postEvents } from './breakdown-api.js';
|
|
15
|
+
import { toast } from './primitives.js';
|
|
16
|
+
import { COPY } from './breakdown-copy.js';
|
|
17
|
+
|
|
18
|
+
export const HOLD_MS = 8000;
|
|
19
|
+
|
|
20
|
+
const pending = new Map(); // key -> { key, ws, events, apply, timer, note, onDone }
|
|
21
|
+
let unloadHooked = false;
|
|
22
|
+
|
|
23
|
+
function hookUnload() {
|
|
24
|
+
if (unloadHooked || typeof window === 'undefined') return;
|
|
25
|
+
unloadHooked = true;
|
|
26
|
+
window.addEventListener('pagehide', flushAll);
|
|
27
|
+
if (typeof document !== 'undefined') {
|
|
28
|
+
document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'hidden') flushAll(); });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function write(h, keepalive) {
|
|
33
|
+
pending.delete(h.key);
|
|
34
|
+
if (h.note) h.note.close();
|
|
35
|
+
/* A dying page cannot wait between requests: send every 50-line chunk at once, each with keepalive, or only the
|
|
36
|
+
* first chunk of a big "Withdraw all" would leave before the page is gone. */
|
|
37
|
+
if (keepalive) {
|
|
38
|
+
for (let i = 0; i < h.events.length; i += 50) postEvents(h.ws, h.events.slice(i, i + 50), { keepalive: true });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
let ok = true; let error = null;
|
|
42
|
+
for (let i = 0; i < h.events.length; i += 50) {
|
|
43
|
+
const out = await postEvents(h.ws, h.events.slice(i, i + 50), { keepalive });
|
|
44
|
+
if (!out || out.ok === false) { ok = false; error = (out && out.error) || 'nothing was saved'; break; }
|
|
45
|
+
}
|
|
46
|
+
if (!ok && !keepalive) toast({ text: error, tone: 'error' });
|
|
47
|
+
if (h.onDone) h.onDone({ ok, error });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* hold({ key, ws, events, apply(layout), text, onDone({ok,error}), onUndo() })
|
|
52
|
+
* Shows the change at once (through `overlay`), raises the Undo toast and writes `events` after HOLD_MS. A second hold
|
|
53
|
+
* with the same key replaces the first without writing it.
|
|
54
|
+
*/
|
|
55
|
+
export function hold({ key, ws, events, apply, text, onDone, onUndo }) {
|
|
56
|
+
hookUnload();
|
|
57
|
+
cancel(key);
|
|
58
|
+
const h = { key, ws, events, apply, onDone, timer: null, note: null };
|
|
59
|
+
h.timer = setTimeout(() => { if (pending.get(key) === h) write(h, false); }, HOLD_MS);
|
|
60
|
+
h.note = toast({
|
|
61
|
+
text, actionLabel: COPY.undo, icon: 'undo-2', timeout: HOLD_MS,
|
|
62
|
+
onAction: () => { if (pending.get(key) === h) { clearTimeout(h.timer); pending.delete(key); if (onUndo) onUndo(); } },
|
|
63
|
+
});
|
|
64
|
+
pending.set(key, h);
|
|
65
|
+
return h;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Drop a held change without writing it. Returns true when there was one. */
|
|
69
|
+
export function cancel(key) {
|
|
70
|
+
const h = pending.get(key);
|
|
71
|
+
if (!h) return false;
|
|
72
|
+
clearTimeout(h.timer);
|
|
73
|
+
if (h.note) h.note.close();
|
|
74
|
+
pending.delete(key);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Write a held change NOW instead of at the end of its hold (it can no longer be undone). True when there was one. */
|
|
79
|
+
export function flush(key) {
|
|
80
|
+
const h = pending.get(key);
|
|
81
|
+
if (!h) return false;
|
|
82
|
+
clearTimeout(h.timer);
|
|
83
|
+
write(h, false);
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** True while a change with this key is held. */
|
|
88
|
+
export function isHeld(key) { return pending.has(key); }
|
|
89
|
+
|
|
90
|
+
/** True while any change is held. */
|
|
91
|
+
export function anyHeld() { return pending.size > 0; }
|
|
92
|
+
|
|
93
|
+
/** Apply every held change to a freshly fetched layout, so a poll during the hold does not undo it on screen. */
|
|
94
|
+
export function overlay(layout) {
|
|
95
|
+
if (!layout || !pending.size) return layout;
|
|
96
|
+
for (const h of pending.values()) { try { if (h.apply) h.apply(layout); } catch { /* a stale overlay is skipped */ } }
|
|
97
|
+
return layout;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Post every held change now. Runs on `pagehide`, with keepalive so the request outlives the page. */
|
|
101
|
+
export function flushAll() {
|
|
102
|
+
for (const h of [...pending.values()]) { clearTimeout(h.timer); write(h, true); }
|
|
103
|
+
}
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { el } from './dom.js';
|
|
20
20
|
import { addProductBody } from './panel-repos.js';
|
|
21
|
+
import { pressFetch } from './http.js'; // the per-launch nonce: /api/ingest/confirm is a guarded anchor change
|
|
21
22
|
|
|
22
23
|
const BTN = 'font:500 12.5px var(--sans);background:transparent;color:var(--foreground);border:1px solid var(--input);border-radius:8px;padding:0 12px;height:30px;min-height:30px;display:inline-grid;place-items:center;cursor:pointer;flex:none;white-space:nowrap';
|
|
23
24
|
const BTNP = 'font:500 12.5px var(--sans);background:var(--foreground);color:var(--background);border:0;border-radius:8px;padding:0 12px;height:30px;min-height:30px;display:inline-grid;place-items:center;cursor:pointer;flex:none;white-space:nowrap';
|
|
@@ -70,7 +71,7 @@ function proposals(ctx) {
|
|
|
70
71
|
|
|
71
72
|
async function act(ctx, url, body, done) {
|
|
72
73
|
let out;
|
|
73
|
-
try { out = await
|
|
74
|
+
try { out = await pressFetch(url, { method: 'POST', body: JSON.stringify(body) }).then((r) => r.json()); }
|
|
74
75
|
catch (e) { out = { ok: false, error: (e && e.message) || String(e) }; }
|
|
75
76
|
say = !out || out.ok === false ? { tone: 'bad', text: (out && out.error) || 'the server did not answer. Nothing was written.' } : { tone: 'ok', text: done(out) };
|
|
76
77
|
ing = { ...ing, state: 'idle' };
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
* POST /api/live-notes/switch { ws, live }: the switch; the reply carries the gates again
|
|
26
26
|
*/
|
|
27
27
|
import { el } from './dom.js';
|
|
28
|
+
import { askConfirm } from './dialogs.js';
|
|
28
29
|
|
|
29
30
|
const BTN = 'font:500 12.5px var(--sans);background:transparent;color:var(--foreground);border:1px solid var(--input);border-radius:8px;padding:0 12px;height:30px;min-height:30px;display:inline-grid;place-items:center;cursor:pointer;flex:none;white-space:nowrap';
|
|
30
31
|
const BTNP = 'font:500 12.5px var(--sans);background:var(--foreground);color:var(--background);border:0;border-radius:8px;padding:0 12px;height:30px;min-height:30px;display:inline-grid;place-items:center;cursor:pointer;flex:none;white-space:nowrap';
|
|
@@ -221,7 +222,8 @@ async function markPrivate(ctx, ws, session) {
|
|
|
221
222
|
}
|
|
222
223
|
|
|
223
224
|
async function closeSession(ctx, ws, session) {
|
|
224
|
-
|
|
225
|
+
const sure = await askConfirm({ title: 'End this session?', body: 'The points are filed in today\'s requirements note and the raw transcript is deleted.', confirmLabel: 'End session', danger: true });
|
|
226
|
+
if (!sure) return;
|
|
225
227
|
if (listen && listen.session === session) { const l = listen; stopListening(); await flush(ctx, l); }
|
|
226
228
|
const r = await post('/api/live-notes/close', { ws, session });
|
|
227
229
|
banner = r && r.ok ? { tone: 'ok', text: r.already ? 'This session was already closed.' : 'Filed in ' + r.note + '. Raw transcript: ' + r.transcript + '.' } : { tone: 'bad', text: (r && r.error) || 'the session did not close' };
|
|
@@ -1,168 +1,13 @@
|
|
|
1
|
-
/* pm/view-today.js — the Today view tab,
|
|
1
|
+
/* pm/view-today.js — the Today view tab of the old shell, retired into the Today destination (pm-os-absorb Run 3, slice 3B).
|
|
2
2
|
*
|
|
3
|
-
* The board
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Every fact comes from a read that exists: derived status (`state.statuses`, the same as Run 2's board) and the morning
|
|
8
|
-
* brief (`/api/proactive/brief`, the route the engine list reads). The mockup's mail, Jira and Confluence badges and its
|
|
9
|
-
* calendar events show only when a brief reports them. Without a brief the board says that nothing was read.
|
|
10
|
-
* The Run 2 hooks are kept: data-today = board, greeting, count, sources, needs, prepared, events, card, open, dismiss, and
|
|
11
|
-
* data-today-scope on the toggle.
|
|
3
|
+
* The board is dest-today.js: eight kinds of card, ranked, one button each. This file only gives the old shell's tab the same
|
|
4
|
+
* board, until the frame (3A) is the default. The greeting, the source badges, the Prepared and Events columns and the
|
|
5
|
+
* proactive-engine list are gone from Today (R12: Today holds the eight kinds and nothing else). The registry hook that
|
|
6
|
+
* view-today.js had, `todayCards`, is called from dest-today.js the same way.
|
|
12
7
|
*/
|
|
13
8
|
|
|
14
|
-
import {
|
|
15
|
-
import { currentProduct } from './board-read.js';
|
|
16
|
-
import { repoTuples, selectRepo } from './panel-repos.js';
|
|
17
|
-
import { needsCards } from './panel-cockpit.js';
|
|
18
|
-
|
|
19
|
-
const DISMISS_REASONS = ['not now', 'wrong priority', 'already handled'];
|
|
20
|
-
const NEEDS_SHOWN = 5; // the mockup shows a few cards and then "+ N more"
|
|
21
|
-
let needsAll = false; // the only module state: has the person asked for every card
|
|
22
|
-
|
|
23
|
-
const LBL = 'font:500 10px var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--muted-foreground)';
|
|
24
|
-
const BADGE = 'font:500 11px var(--sans);border:1px solid var(--border);border-radius:999px;padding:0 8px;line-height:18px;color:var(--foreground);white-space:nowrap;flex:none';
|
|
25
|
-
const TONE = {
|
|
26
|
-
d: 'border-color:transparent;background:color-mix(in oklab, var(--destructive) 18%, transparent);color:var(--destructive)',
|
|
27
|
-
w: 'border-color:transparent;background:color-mix(in oklab, var(--warning) 16%, transparent);color:var(--warning)',
|
|
28
|
-
s: 'border-color:transparent;background:color-mix(in oklab, var(--success) 16%, transparent);color:var(--success)',
|
|
29
|
-
};
|
|
30
|
-
const badge = (text, tone, extra) => el('span', { style: BADGE + (tone ? ';' + TONE[tone] : '') + (extra ? ';' + extra : '') }, text);
|
|
31
|
-
const CARD = 'border:1px solid var(--border);background:var(--card);border-radius:10px;padding:12px 14px;display:flex;flex-direction:column;gap:8px';
|
|
32
|
-
const BTN_P = 'font:500 12.5px var(--sans);background:var(--foreground);color:var(--background);border:0;border-radius:8px;padding:0 12px;height:30px;display:inline-grid;place-items:center;cursor:pointer';
|
|
33
|
-
const BTN = 'font:500 12.5px var(--sans);background:transparent;color:var(--foreground);border:1px solid var(--input);border-radius:8px;padding:0 12px;height:30px;display:inline-grid;place-items:center;cursor:pointer';
|
|
34
|
-
const GHOST = 'font:12px var(--sans);color:var(--muted-foreground);padding:0 8px;height:28px;display:inline-grid;place-items:center;cursor:pointer;background:transparent;border:0';
|
|
35
|
-
const MUTED = 'color:var(--muted-foreground)';
|
|
36
|
-
|
|
37
|
-
const DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
|
38
|
-
const MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
|
39
|
-
|
|
40
|
-
/* ── the morning brief: the same route the engine list reads, kept for 15 seconds ─────────────────── */
|
|
41
|
-
let brief = { state: 'idle', data: null, at: 0 };
|
|
42
|
-
function readBrief(ctx) {
|
|
43
|
-
if (ctx.FIXTURE) return null;
|
|
44
|
-
const fresh = brief.state === 'ok' && Date.now() - brief.at < 15000;
|
|
45
|
-
if (brief.state === 'loading' || brief.state === 'error' && Date.now() - brief.at < 15000 || fresh) return brief.data;
|
|
46
|
-
brief = { state: 'loading', data: brief.data, at: brief.at };
|
|
47
|
-
fetch('/api/proactive/brief').then((r) => r.json()).then(
|
|
48
|
-
(d) => { brief = { state: d && d.ok !== false ? 'ok' : 'error', data: d && d.ok !== false ? d : null, at: Date.now() }; ctx.setState({}); },
|
|
49
|
-
() => { brief = { state: 'error', data: null, at: Date.now() }; ctx.setState({}); },
|
|
50
|
-
);
|
|
51
|
-
return brief.data;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const keyOf = (repo, slug, state) => {
|
|
55
|
-
const sg = typeof window !== 'undefined' ? window.PMOSStatusGroups : null;
|
|
56
|
-
return sg ? sg.keyOf(((state.statuses || {})[repo] || {})[slug]) : 'unknown';
|
|
57
|
-
};
|
|
58
|
-
const meaning = (key) => {
|
|
59
|
-
const sg = typeof window !== 'undefined' ? window.PMOSStatusGroups : null;
|
|
60
|
-
return (sg && sg.BY_KEY && sg.BY_KEY[key] && sg.BY_KEY[key].meaning) || '';
|
|
61
|
-
};
|
|
9
|
+
import { mountToday } from './dest-today.js';
|
|
62
10
|
|
|
63
11
|
export function renderBoard(inner, ctx) {
|
|
64
|
-
|
|
65
|
-
const all = state.todayScope === 'all';
|
|
66
|
-
const repo = currentProduct();
|
|
67
|
-
const cards = needsCards(all);
|
|
68
|
-
const repos = repoTuples();
|
|
69
|
-
const prepared = [];
|
|
70
|
-
for (const t of repos) {
|
|
71
|
-
if (!all && t[0] !== repo) continue;
|
|
72
|
-
for (const slug of Object.keys((state.statuses && state.statuses[t[0]]) || {})) {
|
|
73
|
-
if (keyOf(t[0], slug, state) === 'in-progress') prepared.push({ repo: t[0], slug });
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
const b = readBrief(ctx);
|
|
77
|
-
const br = b && b.brief && !b.stale ? b.brief : null;
|
|
78
|
-
const now = new Date();
|
|
79
|
-
const hour = now.getHours();
|
|
80
|
-
const greet = b && b.greeting ? String(b.greeting).replace(/\.$/, '') : (hour < 12 ? 'Good morning' : hour < 18 ? 'Good afternoon' : 'Good evening');
|
|
81
|
-
const open = (c) => { selectRepo(c.repo); setState({ sel: c.slug, detail: { kind: 'init' }, col2: true }); };
|
|
82
|
-
|
|
83
|
-
/* header: greeting and count line on the left, the scope toggle on the right */
|
|
84
|
-
const toggle = el('div', { 'data-today': 'scope', style: 'display:flex;gap:2px;background:var(--accent);border-radius:8px;padding:3px;font-size:12.5px' },
|
|
85
|
-
...[['repo', 'Repository'], ['all', 'All']].map(([k, label]) => el('button', {
|
|
86
|
-
'data-today-scope': k, 'aria-pressed': (k === 'all') === all ? 'true' : 'false',
|
|
87
|
-
title: k === 'all' ? 'Show every repository' : 'Show ' + (repo || 'this repository') + ' only',
|
|
88
|
-
onClick: () => setState({ todayScope: k === 'all' ? 'all' : 'repo' }),
|
|
89
|
-
style: 'font:12.5px var(--sans);padding:3px 12px;border-radius:6px;border:0;cursor:pointer;' + ((k === 'all') === all ? 'background:var(--background);font-weight:500;color:var(--foreground)' : 'background:transparent;color:var(--muted-foreground)'),
|
|
90
|
-
}, label)));
|
|
91
|
-
const date = DAYS[now.getDay()] + ' ' + now.getDate() + ' ' + MONTHS[now.getMonth()];
|
|
92
|
-
const count = cards.length + (cards.length === 1 ? ' needs you' : ' need you') + (all ? ' across ' + repos.length + ' repositories' : ' in ' + (repo || 'this repository'))
|
|
93
|
-
+ ' · ' + prepared.length + ' in progress';
|
|
94
|
-
const header = el('div', { 'data-board-part': 'header', style: 'display:flex;justify-content:space-between;align-items:flex-end;gap:12px;flex-wrap:wrap' },
|
|
95
|
-
el('div', { style: 'min-width:0' },
|
|
96
|
-
el('div', { 'data-today': 'greeting', style: 'font:600 22px var(--sans)' }, greet),
|
|
97
|
-
el('div', { 'data-today': 'count', style: MUTED }, date + ' · ' + count)),
|
|
98
|
-
el('div', { style: 'display:flex;align-items:center;gap:10px' }, toggle));
|
|
99
|
-
|
|
100
|
-
/* the source badges: what was read, and nothing else */
|
|
101
|
-
const srcBadges = [badge('records · read', 's')];
|
|
102
|
-
if (br) {
|
|
103
|
-
for (const [k, v] of Object.entries(br.sources || {})) {
|
|
104
|
-
srcBadges.push(v === 'read' ? badge(k + ' · read', 's') : v === 'off' ? badge(k + ' · off', null, 'opacity:.6') : badge(k + ' · not reached'));
|
|
105
|
-
}
|
|
106
|
-
} else srcBadges.push(badge(b && b.stale ? 'brief · out of date' : ctx.FIXTURE ? 'brief · not read here' : 'brief · none yet', b && b.stale ? 'w' : null));
|
|
107
|
-
const sources = el('div', { 'data-today': 'sources', style: 'display:flex;gap:6px;flex-wrap:wrap;align-items:center' },
|
|
108
|
-
...srcBadges,
|
|
109
|
-
el('span', { style: MUTED + ';font-size:11px' }, br
|
|
110
|
-
? 'Read from the derived status of ' + Object.keys(state.statuses || {}).length + ' repositories and the brief for ' + br.date + '.'
|
|
111
|
-
: 'Read from the derived status of ' + Object.keys(state.statuses || {}).length + ' repositories. No mail or calendar is read here.'));
|
|
112
|
-
|
|
113
|
-
/* Needs you */
|
|
114
|
-
const card = (c) => {
|
|
115
|
-
const needs = c.key === 'needs-you';
|
|
116
|
-
return el('div', { 'data-today': 'card', 'data-slug': c.slug, 'data-repo': c.repo, style: CARD },
|
|
117
|
-
el('div', { style: 'display:flex;align-items:center;gap:8px;min-width:0' },
|
|
118
|
-
badge(c.repo),
|
|
119
|
-
el('b', { style: 'min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap' }, c.slug),
|
|
120
|
-
badge(needs ? 'needs you' : 'acceptance', needs ? 'd' : 'w', 'margin-left:auto')),
|
|
121
|
-
meaning(c.key) ? el('div', { style: MUTED }, meaning(c.key)) : null,
|
|
122
|
-
el('div', { style: 'display:flex;gap:6px;align-items:center;flex-wrap:wrap' },
|
|
123
|
-
el('button', { 'data-today': 'open', onClick: () => open(c), style: BTN_P }, needs ? 'Unblock' : 'Review'),
|
|
124
|
-
...DISMISS_REASONS.map((r, i) => el('button', { 'data-today': 'dismiss', 'data-reason': r, title: 'Dismiss: ' + r,
|
|
125
|
-
onClick: () => setState((s) => ({ todayDismissed: { ...(s.todayDismissed || {}), [c.repo + '/' + c.slug]: r } })),
|
|
126
|
-
style: GHOST + (i === 0 ? ';margin-left:auto' : ''), hover: 'color:var(--foreground)' }, r.charAt(0).toUpperCase() + r.slice(1)))));
|
|
127
|
-
};
|
|
128
|
-
const shown = needsAll ? cards : cards.slice(0, NEEDS_SHOWN);
|
|
129
|
-
const needsCol = el('div', { 'data-today': 'needs', style: 'flex:1 1 320px;min-width:0;display:flex;flex-direction:column;gap:10px' },
|
|
130
|
-
el('div', { style: LBL }, 'Needs you · only a person can close these'),
|
|
131
|
-
...(cards.length ? shown.map(card) : [el('div', { style: MUTED }, 'Nothing is waiting on you.')]),
|
|
132
|
-
cards.length > NEEDS_SHOWN ? el('button', { 'data-today': 'more', onClick: () => { needsAll = !needsAll; setState({}); },
|
|
133
|
-
style: 'text-align:left;background:transparent;border:0;padding:0;cursor:pointer;' + MUTED, hover: 'color:var(--foreground)' },
|
|
134
|
-
needsAll ? 'Show fewer' : '+ ' + (cards.length - NEEDS_SHOWN) + ' more') : null);
|
|
135
|
-
|
|
136
|
-
/* Prepared for you, then today's events */
|
|
137
|
-
const prep = (c) => el('div', { 'data-today': 'prepared', 'data-slug': c.slug, 'data-repo': c.repo, style: CARD },
|
|
138
|
-
el('b', { style: 'overflow:hidden;text-overflow:ellipsis;white-space:nowrap' }, c.slug),
|
|
139
|
-
el('div', { style: MUTED }, meaning('in-progress') || 'In progress.'),
|
|
140
|
-
el('div', { style: 'display:flex;gap:6px' }, el('button', { 'data-today': 'prepared-open', onClick: () => open(c), style: BTN, hover: 'background:var(--accent)' }, 'Open')));
|
|
141
|
-
let events;
|
|
142
|
-
if (!br) events = [el('div', { style: MUTED }, b && b.stale ? 'The brief is out of date, so no events are shown.' : 'No calendar was read. Events come from the morning brief.')];
|
|
143
|
-
else if (br.sources && br.sources.calendar !== 'read') events = [el('div', { style: MUTED }, 'The brief did not read the calendar, so this says nothing about your day.')];
|
|
144
|
-
else if (!(br.calendar || []).length) events = [el('div', { style: MUTED }, 'No events today.')];
|
|
145
|
-
else events = [el('div', { style: 'display:flex;flex-direction:column;gap:6px' }, ...br.calendar.map((e) => el('div', { 'data-today': 'event', style: 'display:flex;gap:10px' },
|
|
146
|
-
el('span', { style: 'font:12px var(--mono);' + MUTED }, new Date(e.start).toTimeString().slice(0, 5)), e.title + (e.with ? ' · ' + e.with : ''))))];
|
|
147
|
-
const side = el('div', { style: 'flex:0 1 360px;min-width:260px;display:flex;flex-direction:column;gap:10px' },
|
|
148
|
-
el('div', { 'data-today': 'prepared', style: 'display:flex;flex-direction:column;gap:10px' },
|
|
149
|
-
el('div', { style: LBL }, 'Prepared for you · in progress'),
|
|
150
|
-
...(prepared.length ? prepared.map(prep) : [el('div', { style: MUTED }, 'Nothing is being prepared.')])),
|
|
151
|
-
el('div', { 'data-today': 'events', style: 'display:flex;flex-direction:column;gap:10px;margin-top:6px' },
|
|
152
|
-
el('div', { style: LBL }, "Today's events"), ...events));
|
|
153
|
-
|
|
154
|
-
const board = el('div', { 'data-today': 'board', 'data-board': 'today', style: 'display:flex;flex-direction:column;gap:16px;font-size:13px;line-height:1.45' },
|
|
155
|
-
header, sources,
|
|
156
|
-
el('div', { 'data-board-part': 'columns', style: 'display:flex;gap:20px;flex-wrap:wrap;align-items:flex-start;min-height:0' }, needsCol, side));
|
|
157
|
-
|
|
158
|
-
/* the live list: the proactive engine, the brief, background prepare, learning and settings */
|
|
159
|
-
const host = el('div', { 'data-today': 'engine', style: 'display:flex;flex-direction:column;gap:2px;border:1px solid var(--border);border-radius:10px;background:var(--background);padding:4px 0' });
|
|
160
|
-
ctx.renderMode(host);
|
|
161
|
-
if (!host.firstChild) host.appendChild(el('div', { style: MUTED + ';padding:8px 14px;font-size:12px' }, ctx.ready ? 'This list has nothing to show.' : 'Reading the list …'));
|
|
162
|
-
const lower = el('div', { 'data-board-part': 'engine', style: 'display:flex;flex-direction:column;gap:10px;padding-top:16px;margin-top:6px;border-top:1px solid var(--border)' },
|
|
163
|
-
el('div', { style: LBL }, 'From the records · scanned on this computer'), host);
|
|
164
|
-
|
|
165
|
-
inner.style.gap = '16px';
|
|
166
|
-
inner.appendChild(board);
|
|
167
|
-
inner.appendChild(lower);
|
|
12
|
+
mountToday(inner, ctx);
|
|
168
13
|
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! Sortable 1.15.7 - MIT | git://github.com/SortableJS/Sortable.git */
|
|
2
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Sortable=e()}(this,function(){"use strict";function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=Array(e);n<e;n++)o[n]=t[n];return o}function i(t,e,n){return(e=function(t){t=function(t,e){if("object"!=typeof t||!t)return t;var n=t[Symbol.toPrimitive];if(void 0===n)return("string"===e?String:Number)(t);e=n.call(t,e||"default");if("object"!=typeof e)return e;throw new TypeError("@@toPrimitive must return a primitive value.")}(t,"string");return"symbol"==typeof t?t:t+""}(e))in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function a(){return(a=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n,o=arguments[e];for(n in o)!{}.hasOwnProperty.call(o,n)||(t[n]=o[n])}return t}).apply(null,arguments)}function r(e,t){var n,o=Object.keys(e);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(e),t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),o.push.apply(o,n)),o}function I(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach(function(t){i(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function l(t,e){if(null==t)return{};var n,o=function(t,e){if(null==t)return{};var n,o={};for(n in t)if({}.hasOwnProperty.call(t,n)){if(-1!==e.indexOf(n))continue;o[n]=t[n]}return o}(t,e);if(Object.getOwnPropertySymbols)for(var i=Object.getOwnPropertySymbols(t),r=0;r<i.length;r++)n=i[r],-1===e.indexOf(n)&&{}.propertyIsEnumerable.call(t,n)&&(o[n]=t[n]);return o}function e(t){return function(t){if(Array.isArray(t))return o(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return o(t,e);var n={}.toString.call(t).slice(8,-1);return"Map"===(n="Object"===n&&t.constructor?t.constructor.name:n)||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?o(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function s(t){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function t(t){if("undefined"!=typeof window&&window.navigator)return!!navigator.userAgent.match(t)}var y=t(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i),w=t(/Edge/i),c=t(/firefox/i),u=t(/safari/i)&&!t(/chrome/i)&&!t(/android/i),d=t(/iP(ad|od|hone)/i),n=t(/chrome/i)&&t(/android/i),h={capture:!1,passive:!1};function f(t,e,n){t.addEventListener(e,n,!y&&h)}function p(t,e,n){t.removeEventListener(e,n,!y&&h)}function g(t,e){if(e&&(">"===e[0]&&(e=e.substring(1)),t))try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return}}function m(t){return t.host&&t!==document&&t.host.nodeType&&t.host!==t?t.host:t.parentNode}function P(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"!==e[0]||t.parentNode===n)&&g(t,e)||o&&t===n)return t}while(t!==n&&(t=m(t)))}return null}var v,b=/\s+/g;function k(t,e,n){var o;t&&e&&(t.classList?t.classList[n?"add":"remove"](e):(o=(" "+t.className+" ").replace(b," ").replace(" "+e+" "," "),t.className=(o+(n?" "+e:"")).replace(b," ")))}function R(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];o[e=!(e in o||-1!==e.indexOf("webkit"))?"-webkit-"+e:e]=n+("string"==typeof n?"":"px")}}function D(t,e){var n="";if("string"==typeof t)n=t;else do{var o=R(t,"transform")}while(o&&"none"!==o&&(n=o+" "+n),!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function E(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i<r;i++)n(o[i],i);return o}return[]}function O(){var t=document.scrollingElement;return t||document.documentElement}function X(t,e,n,o,i){if(t.getBoundingClientRect||t===window){var r,a,l,s,c,u,d=t!==window&&t.parentNode&&t!==O()?(a=(r=t.getBoundingClientRect()).top,l=r.left,s=r.bottom,c=r.right,u=r.height,r.width):(l=a=0,s=window.innerHeight,c=window.innerWidth,u=window.innerHeight,window.innerWidth);if((e||n)&&t!==window&&(i=i||t.parentNode,!y))do{if(i&&i.getBoundingClientRect&&("none"!==R(i,"transform")||n&&"static"!==R(i,"position"))){var h=i.getBoundingClientRect();a-=h.top+parseInt(R(i,"border-top-width")),l-=h.left+parseInt(R(i,"border-left-width")),s=a+r.height,c=l+r.width;break}}while(i=i.parentNode);return o&&t!==window&&(o=(e=D(i||t))&&e.a,t=e&&e.d,e&&(s=(a/=t)+(u/=t),c=(l/=o)+(d/=o))),{top:a,left:l,bottom:s,right:c,width:d,height:u}}}function Y(t,e,n){for(var o=M(t,!0),i=X(t)[e];o;){var r=X(o)[n];if(!("top"===n||"left"===n?r<=i:i<=r))return o;if(o===O())break;o=M(o,!1)}return!1}function B(t,e,n,o){for(var i=0,r=0,a=t.children;r<a.length;){if("none"!==a[r].style.display&&a[r]!==Ht.ghost&&(o||a[r]!==Ht.dragged)&&P(a[r],n.draggable,t,!1)){if(i===e)return a[r];i++}r++}return null}function F(t,e){for(var n=t.lastElementChild;n&&(n===Ht.ghost||"none"===R(n,"display")||e&&!g(n,e));)n=n.previousElementSibling;return n||null}function j(t,e){var n=0;if(!t||!t.parentNode)return-1;for(;t=t.previousElementSibling;)"TEMPLATE"===t.nodeName.toUpperCase()||t===Ht.clone||e&&!g(t,e)||n++;return n}function S(t){var e=0,n=0,o=O();if(t)do{var i=D(t),r=i.a,i=i.d}while(e+=t.scrollLeft*r,n+=t.scrollTop*i,t!==o&&(t=t.parentNode));return[e,n]}function M(t,e){if(!t||!t.getBoundingClientRect)return O();var n=t,o=!1;do{if(n.clientWidth<n.scrollWidth||n.clientHeight<n.scrollHeight){var i=R(n);if(n.clientWidth<n.scrollWidth&&("auto"==i.overflowX||"scroll"==i.overflowX)||n.clientHeight<n.scrollHeight&&("auto"==i.overflowY||"scroll"==i.overflowY)){if(!n.getBoundingClientRect||n===document.body)return O();if(o||e)return n;o=!0}}}while(n=n.parentNode);return O()}function _(t,e){return Math.round(t.top)===Math.round(e.top)&&Math.round(t.left)===Math.round(e.left)&&Math.round(t.height)===Math.round(e.height)&&Math.round(t.width)===Math.round(e.width)}function C(e,n){return function(){var t;v||(1===(t=arguments).length?e.call(this,t[0]):e.apply(this,t),v=setTimeout(function(){v=void 0},n))}}function H(t,e,n){t.scrollLeft+=e,t.scrollTop+=n}function T(t){var e=window.Polymer,n=window.jQuery||window.Zepto;return e&&e.dom?e.dom(t).cloneNode(!0):n?n(t).clone(!0)[0]:t.cloneNode(!0)}function x(t,e){R(t,"position","absolute"),R(t,"top",e.top),R(t,"left",e.left),R(t,"width",e.width),R(t,"height",e.height)}function A(t){R(t,"position",""),R(t,"top",""),R(t,"left",""),R(t,"width",""),R(t,"height","")}function L(n,o,i){var r={};return Array.from(n.children).forEach(function(t){var e;P(t,o.draggable,n,!1)&&!t.animated&&t!==i&&(e=X(t),r.left=Math.min(null!==(t=r.left)&&void 0!==t?t:1/0,e.left),r.top=Math.min(null!==(t=r.top)&&void 0!==t?t:1/0,e.top),r.right=Math.max(null!==(t=r.right)&&void 0!==t?t:-1/0,e.right),r.bottom=Math.max(null!==(t=r.bottom)&&void 0!==t?t:-1/0,e.bottom))}),r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}var K="Sortable"+(new Date).getTime();function N(){var e,o=[];return{captureAnimationState:function(){o=[],this.options.animation&&[].slice.call(this.el.children).forEach(function(t){var e,n;"none"!==R(t,"display")&&t!==Ht.ghost&&(o.push({target:t,rect:X(t)}),e=I({},o[o.length-1].rect),!t.thisAnimationDuration||(n=D(t,!0))&&(e.top-=n.f,e.left-=n.e),t.fromRect=e)})},addAnimationState:function(t){o.push(t)},removeAnimationState:function(t){o.splice(function(t,e){for(var n in t)if(t.hasOwnProperty(n))for(var o in e)if(e.hasOwnProperty(o)&&e[o]===t[n][o])return Number(n);return-1}(o,{target:t}),1)},animateAll:function(t){var c=this;if(!this.options.animation)return clearTimeout(e),void("function"==typeof t&&t());var u=!1,d=0;o.forEach(function(t){var e=0,n=t.target,o=n.fromRect,i=X(n),r=n.prevFromRect,a=n.prevToRect,l=t.rect,s=D(n,!0);s&&(i.top-=s.f,i.left-=s.e),n.toRect=i,n.thisAnimationDuration&&_(r,i)&&!_(o,i)&&(l.top-i.top)/(l.left-i.left)==(o.top-i.top)/(o.left-i.left)&&(t=l,s=r,r=a,a=c.options,e=Math.sqrt(Math.pow(s.top-t.top,2)+Math.pow(s.left-t.left,2))/Math.sqrt(Math.pow(s.top-r.top,2)+Math.pow(s.left-r.left,2))*a.animation),_(i,o)||(n.prevFromRect=o,n.prevToRect=i,e=e||c.options.animation,c.animate(n,l,i,e)),e&&(u=!0,d=Math.max(d,e),clearTimeout(n.animationResetTimer),n.animationResetTimer=setTimeout(function(){n.animationTime=0,n.prevFromRect=null,n.fromRect=null,n.prevToRect=null,n.thisAnimationDuration=null},e),n.thisAnimationDuration=e)}),clearTimeout(e),u?e=setTimeout(function(){"function"==typeof t&&t()},d):"function"==typeof t&&t(),o=[]},animate:function(t,e,n,o){var i,r;o&&(R(t,"transition",""),R(t,"transform",""),i=(r=D(this.el))&&r.a,r=r&&r.d,i=(e.left-n.left)/(i||1),r=(e.top-n.top)/(r||1),t.animatingX=!!i,t.animatingY=!!r,R(t,"transform","translate3d("+i+"px,"+r+"px,0)"),this.forRepaintDummy=t.offsetWidth,R(t,"transition","transform "+o+"ms"+(this.options.easing?" "+this.options.easing:"")),R(t,"transform","translate3d(0,0,0)"),"number"==typeof t.animated&&clearTimeout(t.animated),t.animated=setTimeout(function(){R(t,"transition",""),R(t,"transform",""),t.animated=!1,t.animatingX=!1,t.animatingY=!1},o))}}}var W=[],z={initializeByDefault:!0},G={mount:function(e){for(var t in z)!z.hasOwnProperty(t)||t in e||(e[t]=z[t]);W.forEach(function(t){if(t.pluginName===e.pluginName)throw"Sortable: Cannot mount plugin ".concat(e.pluginName," more than once")}),W.push(e)},pluginEvent:function(e,n,o){var t=this;this.eventCanceled=!1,o.cancel=function(){t.eventCanceled=!0};var i=e+"Global";W.forEach(function(t){n[t.pluginName]&&(n[t.pluginName][i]&&n[t.pluginName][i](I({sortable:n},o)),n.options[t.pluginName]&&n[t.pluginName][e]&&n[t.pluginName][e](I({sortable:n},o)))})},initializePlugins:function(n,o,i,t){for(var e in W.forEach(function(t){var e=t.pluginName;(n.options[e]||t.initializeByDefault)&&((t=new t(n,o,n.options)).sortable=n,t.options=n.options,n[e]=t,a(i,t.defaults))}),n.options){var r;n.options.hasOwnProperty(e)&&(void 0!==(r=this.modifyOption(n,e,n.options[e]))&&(n.options[e]=r))}},getEventProperties:function(e,n){var o={};return W.forEach(function(t){"function"==typeof t.eventProperties&&a(o,t.eventProperties.call(n[t.pluginName],e))}),o},modifyOption:function(e,n,o){var i;return W.forEach(function(t){e[t.pluginName]&&t.optionListeners&&"function"==typeof t.optionListeners[n]&&(i=t.optionListeners[n].call(e[t.pluginName],o))}),i}};function U(t){var e=t.sortable,n=t.rootEl,o=t.name,i=t.targetEl,r=t.cloneEl,a=t.toEl,l=t.fromEl,s=t.oldIndex,c=t.newIndex,u=t.oldDraggableIndex,d=t.newDraggableIndex,h=t.originalEvent,f=t.putSortable,p=t.extraEventProperties;if(e=e||n&&n[K]){var g,m=e.options,t="on"+o.charAt(0).toUpperCase()+o.substr(1);!window.CustomEvent||y||w?(g=document.createEvent("Event")).initEvent(o,!0,!0):g=new CustomEvent(o,{bubbles:!0,cancelable:!0}),g.to=a||n,g.from=l||n,g.item=i||n,g.clone=r,g.oldIndex=s,g.newIndex=c,g.oldDraggableIndex=u,g.newDraggableIndex=d,g.originalEvent=h,g.pullMode=f?f.lastPutMode:void 0;var v,b=I(I({},p),G.getEventProperties(o,e));for(v in b)g[v]=b[v];n&&n.dispatchEvent(g),m[t]&&m[t].call(e,g)}}function q(t,e){var n=(o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{}).evt,o=l(o,V);G.pluginEvent.bind(Ht)(t,e,I({dragEl:$,parentEl:Q,ghostEl:J,rootEl:tt,nextEl:et,lastDownEl:nt,cloneEl:ot,cloneHidden:it,dragStarted:vt,putSortable:ut,activeSortable:Ht.active,originalEvent:n,oldIndex:rt,oldDraggableIndex:lt,newIndex:at,newDraggableIndex:st,hideGhostForTarget:Yt,unhideGhostForTarget:Bt,cloneNowHidden:function(){it=!0},cloneNowShown:function(){it=!1},dispatchSortableEvent:function(t){Z({sortable:e,name:t,originalEvent:n})}},o))}var V=["evt"];function Z(t){U(I({putSortable:ut,cloneEl:ot,targetEl:$,rootEl:tt,oldIndex:rt,oldDraggableIndex:lt,newIndex:at,newDraggableIndex:st},t))}var $,Q,J,tt,et,nt,ot,it,rt,at,lt,st,ct,ut,dt,ht,ft,pt,gt,mt,vt,bt,yt,wt,Dt,Et=!1,St=!1,_t=[],Ct=!1,Tt=!1,xt=[],Ot=!1,Mt=[],At="undefined"!=typeof document,Nt=d,It=w||y?"cssFloat":"float",Pt=At&&!n&&!d&&"draggable"in document.createElement("div"),kt=function(){if(At){if(y)return!1;var t=document.createElement("x");return t.style.cssText="pointer-events:auto","auto"===t.style.pointerEvents}}(),Rt=function(t,e){var n=R(t),o=parseInt(n.width)-parseInt(n.paddingLeft)-parseInt(n.paddingRight)-parseInt(n.borderLeftWidth)-parseInt(n.borderRightWidth),i=B(t,0,e),r=B(t,1,e),a=i&&R(i),l=r&&R(r),s=a&&parseInt(a.marginLeft)+parseInt(a.marginRight)+X(i).width,t=l&&parseInt(l.marginLeft)+parseInt(l.marginRight)+X(r).width;if("flex"===n.display)return"column"===n.flexDirection||"column-reverse"===n.flexDirection?"vertical":"horizontal";if("grid"===n.display)return n.gridTemplateColumns.split(" ").length<=1?"vertical":"horizontal";if(i&&a.float&&"none"!==a.float){e="left"===a.float?"left":"right";return!r||"both"!==l.clear&&l.clear!==e?"horizontal":"vertical"}return i&&("block"===a.display||"flex"===a.display||"table"===a.display||"grid"===a.display||o<=s&&"none"===n[It]||r&&"none"===n[It]&&o<s+t)?"vertical":"horizontal"},Xt=function(t){function l(r,a){return function(t,e,n,o){var i=t.options.group.name&&e.options.group.name&&t.options.group.name===e.options.group.name;if(null==r&&(a||i))return!0;if(null==r||!1===r)return!1;if(a&&"clone"===r)return r;if("function"==typeof r)return l(r(t,e,n,o),a)(t,e,n,o);e=(a?t:e).options.group.name;return!0===r||"string"==typeof r&&r===e||r.join&&-1<r.indexOf(e)}}var e={},n=t.group;n&&"object"==s(n)||(n={name:n}),e.name=n.name,e.checkPull=l(n.pull,!0),e.checkPut=l(n.put),e.revertClone=n.revertClone,t.group=e},Yt=function(){!kt&&J&&R(J,"display","none")},Bt=function(){!kt&&J&&R(J,"display","")};At&&!n&&document.addEventListener("click",function(t){if(St)return t.preventDefault(),t.stopPropagation&&t.stopPropagation(),t.stopImmediatePropagation&&t.stopImmediatePropagation(),St=!1},!0);function Ft(t){if($){t=t.touches?t.touches[0]:t;var e=(i=t.clientX,r=t.clientY,_t.some(function(t){var e=t[K].options.emptyInsertThreshold;if(e&&!F(t)){var n=X(t),o=i>=n.left-e&&i<=n.right+e,e=r>=n.top-e&&r<=n.bottom+e;return o&&e?a=t:void 0}}),a);if(e){var n,o={};for(n in t)t.hasOwnProperty(n)&&(o[n]=t[n]);o.target=o.rootEl=e,o.preventDefault=void 0,o.stopPropagation=void 0,e[K]._onDragOver(o)}}var i,r,a}function jt(t){$&&$.parentNode[K]._isOutsideThisEl(t.target)}function Ht(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[K]=this;var n,o,i={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Rt(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Ht.supportPointer&&"PointerEvent"in window&&(!u||d),emptyInsertThreshold:5};for(n in G.initializePlugins(this,t,i),i)n in e||(e[n]=i[n]);for(o in Xt(e),this)"_"===o.charAt(0)&&"function"==typeof this[o]&&(this[o]=this[o].bind(this));this.nativeDraggable=!e.forceFallback&&Pt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?f(t,"pointerdown",this._onTapStart):(f(t,"mousedown",this._onTapStart),f(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(f(t,"dragover",this),f(t,"dragenter",this)),_t.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,N())}function Lt(t,e,n,o,i,r,a,l){var s,c,u=t[K],d=u.options.onMove;return!window.CustomEvent||y||w?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||X(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),c=d?d.call(u,s,a):c}function Kt(t){t.draggable=!1}function Wt(){Ot=!1}function zt(t){return setTimeout(t,0)}function Gt(t){return clearTimeout(t)}Ht.prototype={constructor:Ht,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(bt=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,$):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(!function(t){Mt.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&Mt.push(o)}}(o),!$&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled)&&!s.isContentEditable&&(this.nativeDraggable||!u||!l||"SELECT"!==l.tagName.toUpperCase())&&!((l=P(l,t.draggable,o,!1))&&l.animated||nt===l)){if(rt=j(l),lt=j(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return Z({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),q("filter",n,{evt:e}),void(i&&e.preventDefault())}else if(c=c&&c.split(",").some(function(t){if(t=P(s,t.trim(),o,!1))return Z({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),q("filter",n,{evt:e}),!0}))return void(i&&e.preventDefault());t.handle&&!P(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;n&&!$&&n.parentNode===r&&(o=X(n),tt=r,Q=($=n).parentNode,et=$.nextSibling,nt=n,ct=a.group,dt={target:Ht.dragged=$,clientX:(e||t).clientX,clientY:(e||t).clientY},gt=dt.clientX-o.left,mt=dt.clientY-o.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,$.style["will-change"]="all",o=function(){q("delayEnded",i,{evt:t}),Ht.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!c&&i.nativeDraggable&&($.draggable=!0),i._triggerDragStart(t,e),Z({sortable:i,name:"choose",originalEvent:t}),k($,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){E($,t.trim(),Kt)}),f(l,"dragover",Ft),f(l,"mousemove",Ft),f(l,"touchmove",Ft),a.supportPointer?(f(l,"pointerup",i._onDrop),this.nativeDraggable||f(l,"pointercancel",i._onDrop)):(f(l,"mouseup",i._onDrop),f(l,"touchend",i._onDrop),f(l,"touchcancel",i._onDrop)),c&&this.nativeDraggable&&(this.options.touchStartThreshold=4,$.draggable=!0),q("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(w||y)?o():Ht.eventCanceled?this._onDrop():(a.supportPointer?(f(l,"pointerup",i._disableDelayedDrag),f(l,"pointercancel",i._disableDelayedDrag)):(f(l,"mouseup",i._disableDelayedDrag),f(l,"touchend",i._disableDelayedDrag),f(l,"touchcancel",i._disableDelayedDrag)),f(l,"mousemove",i._delayedDragTouchMoveHandler),f(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&f(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)))},_delayedDragTouchMoveHandler:function(t){t=t.touches?t.touches[0]:t;Math.max(Math.abs(t.clientX-this._lastX),Math.abs(t.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){$&&Kt($),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;p(t,"mouseup",this._disableDelayedDrag),p(t,"touchend",this._disableDelayedDrag),p(t,"touchcancel",this._disableDelayedDrag),p(t,"pointerup",this._disableDelayedDrag),p(t,"pointercancel",this._disableDelayedDrag),p(t,"mousemove",this._delayedDragTouchMoveHandler),p(t,"touchmove",this._delayedDragTouchMoveHandler),p(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?f(document,"pointermove",this._onTouchMove):f(document,e?"touchmove":"mousemove",this._onTouchMove):(f($,"dragend",this),f(tt,"dragstart",this._onDragStart));try{document.selection?zt(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){var n;Et=!1,tt&&$?(q("dragStarted",this,{evt:e}),this.nativeDraggable&&f(document,"dragover",jt),n=this.options,t||k($,n.dragClass,!1),k($,n.ghostClass,!0),Ht.active=this,t&&this._appendGhost(),Z({sortable:this,name:"start",originalEvent:e})):this._nulling()},_emulateDragOver:function(){if(ht){this._lastX=ht.clientX,this._lastY=ht.clientY,Yt();for(var t=document.elementFromPoint(ht.clientX,ht.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(ht.clientX,ht.clientY))!==e;)e=t;if($.parentNode[K]._isOutsideThisEl(t),e)do{if(e[K])if(e[K]._onDragOver({clientX:ht.clientX,clientY:ht.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}while(e=m(t=e));Bt()}},_onTouchMove:function(t){if(dt){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=J&&D(J,!0),a=J&&r&&r.a,l=J&&r&&r.d,e=Nt&&Dt&&S(Dt),a=(i.clientX-dt.clientX+o.x)/(a||1)+(e?e[0]-xt[0]:0)/(a||1),l=(i.clientY-dt.clientY+o.y)/(l||1)+(e?e[1]-xt[1]:0)/(l||1);if(!Ht.active&&!Et){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))<n)return;this._onDragStart(t,!0)}J&&(r?(r.e+=a-(ft||0),r.f+=l-(pt||0)):r={a:1,b:0,c:0,d:1,e:a,f:l},r="matrix(".concat(r.a,",").concat(r.b,",").concat(r.c,",").concat(r.d,",").concat(r.e,",").concat(r.f,")"),R(J,"webkitTransform",r),R(J,"mozTransform",r),R(J,"msTransform",r),R(J,"transform",r),ft=a,pt=l,ht=i),t.cancelable&&t.preventDefault()}},_appendGhost:function(){if(!J){var t=this.options.fallbackOnBody?document.body:tt,e=X($,!0,Nt,!0,t),n=this.options;if(Nt){for(Dt=t;"static"===R(Dt,"position")&&"none"===R(Dt,"transform")&&Dt!==document;)Dt=Dt.parentNode;Dt!==document.body&&Dt!==document.documentElement?(Dt===document&&(Dt=O()),e.top+=Dt.scrollTop,e.left+=Dt.scrollLeft):Dt=O(),xt=S(Dt)}k(J=$.cloneNode(!0),n.ghostClass,!1),k(J,n.fallbackClass,!0),k(J,n.dragClass,!0),R(J,"transition",""),R(J,"transform",""),R(J,"box-sizing","border-box"),R(J,"margin",0),R(J,"top",e.top),R(J,"left",e.left),R(J,"width",e.width),R(J,"height",e.height),R(J,"opacity","0.8"),R(J,"position",Nt?"absolute":"fixed"),R(J,"zIndex","100000"),R(J,"pointerEvents","none"),Ht.ghost=J,t.appendChild(J),R(J,"transform-origin",gt/parseInt(J.style.width)*100+"% "+mt/parseInt(J.style.height)*100+"%")}},_onDragStart:function(t,e){var n=this,o=t.dataTransfer,i=n.options;q("dragStart",this,{evt:t}),Ht.eventCanceled?this._onDrop():(q("setupClone",this),Ht.eventCanceled||((ot=T($)).removeAttribute("id"),ot.draggable=!1,ot.style["will-change"]="",this._hideClone(),k(ot,this.options.chosenClass,!1),Ht.clone=ot),n.cloneId=zt(function(){q("clone",n),Ht.eventCanceled||(n.options.removeCloneOnHide||tt.insertBefore(ot,$),n._hideClone(),Z({sortable:n,name:"clone"}))}),e||k($,i.dragClass,!0),e?(St=!0,n._loopId=setInterval(n._emulateDragOver,50)):(p(document,"mouseup",n._onDrop),p(document,"touchend",n._onDrop),p(document,"touchcancel",n._onDrop),o&&(o.effectAllowed="move",i.setData&&i.setData.call(n,o,$)),f(document,"drop",n),R($,"transform","translateZ(0)")),Et=!0,n._dragStartId=zt(n._dragStarted.bind(n,e,t)),f(document,"selectstart",n),vt=!0,window.getSelection().removeAllRanges(),u&&R(document.body,"user-select","none"))},_onDragOver:function(n){var o,i,r,t,e,a=this.el,l=n.target,s=this.options,c=s.group,u=Ht.active,d=ct===c,h=s.sort,f=ut||u,p=this,g=!1;if(!Ot){if(void 0!==n.preventDefault&&n.cancelable&&n.preventDefault(),l=P(l,s.draggable,a,!0),O("dragOver"),Ht.eventCanceled)return g;if($.contains(n.target)||l.animated&&l.animatingX&&l.animatingY||p._ignoreWhileAnimating===l)return A(!1);if(St=!1,u&&!s.disabled&&(d?h||(i=Q!==tt):ut===this||(this.lastPutMode=ct.checkPull(this,u,$,n))&&c.checkPut(this,u,$,n))){if(r="vertical"===this._getDirection(n,l),o=X($),O("dragOverValid"),Ht.eventCanceled)return g;if(i)return Q=tt,M(),this._hideClone(),O("revert"),Ht.eventCanceled||(et?tt.insertBefore($,et):tt.appendChild($)),A(!0);var m=F(a,s.draggable);if(m&&(S=n,c=r,x=X(F((E=this).el,E.options.draggable)),E=L(E.el,E.options,J),!(c?S.clientX>E.right+10||S.clientY>x.bottom&&S.clientX>x.left:S.clientY>E.bottom+10||S.clientX>x.right&&S.clientY>x.top)||m.animated)){if(m&&(t=n,e=r,C=X(B((_=this).el,0,_.options,!0)),_=L(_.el,_.options,J),e?t.clientX<_.left-10||t.clientY<C.top&&t.clientX<C.right:t.clientY<_.top-10||t.clientY<C.bottom&&t.clientX<C.left)){var v=B(a,0,s,!0);if(v===$)return A(!1);if(D=X(l=v),!1!==Lt(tt,a,$,o,l,D,n,!1))return M(),a.insertBefore($,v),Q=a,N(),A(!0)}else if(l.parentNode===a){var b,y,w,D=X(l),E=$.parentNode!==a,S=(S=$.animated&&$.toRect||o,x=l.animated&&l.toRect||D,_=(e=r)?S.left:S.top,t=e?S.right:S.bottom,C=e?S.width:S.height,v=e?x.left:x.top,S=e?x.right:x.bottom,x=e?x.width:x.height,!(_===v||t===S||_+C/2===v+x/2)),_=r?"top":"left",C=Y(l,"top","top")||Y($,"top","top"),v=C?C.scrollTop:void 0;if(bt!==l&&(y=D[_],Ct=!1,Tt=!S&&s.invertSwap||E),0!==(b=function(t,e,n,o,i,r,a,l){var s=o?t.clientY:t.clientX,c=o?n.height:n.width,t=o?n.top:n.left,o=o?n.bottom:n.right,n=!1;if(!a)if(l&&wt<c*i){if(Ct=!Ct&&(1===yt?t+c*r/2<s:s<o-c*r/2)?!0:Ct)n=!0;else if(1===yt?s<t+wt:o-wt<s)return-yt}else if(t+c*(1-i)/2<s&&s<o-c*(1-i)/2)return function(t){return j($)<j(t)?1:-1}(e);if((n=n||a)&&(s<t+c*r/2||o-c*r/2<s))return t+c/2<s?1:-1;return 0}(n,l,D,r,S?1:s.swapThreshold,null==s.invertedSwapThreshold?s.swapThreshold:s.invertedSwapThreshold,Tt,bt===l)))for(var T=j($);(w=Q.children[T-=b])&&("none"===R(w,"display")||w===J););if(0===b||w===l)return A(!1);yt=b;var x=(bt=l).nextElementSibling,E=!1,S=Lt(tt,a,$,o,l,D,n,E=1===b);if(!1!==S)return 1!==S&&-1!==S||(E=1===S),Ot=!0,setTimeout(Wt,30),M(),E&&!x?a.appendChild($):l.parentNode.insertBefore($,E?x:l),C&&H(C,0,v-C.scrollTop),Q=$.parentNode,void 0===y||Tt||(wt=Math.abs(y-X(l)[_])),N(),A(!0)}}else{if(m===$)return A(!1);if((l=m&&a===n.target?m:l)&&(D=X(l)),!1!==Lt(tt,a,$,o,l,D,n,!!l))return M(),m&&m.nextSibling?a.insertBefore($,m.nextSibling):a.appendChild($),Q=a,N(),A(!0)}if(a.contains($))return A(!1)}return!1}function O(t,e){q(t,p,I({evt:n,isOwner:d,axis:r?"vertical":"horizontal",revert:i,dragRect:o,targetRect:D,canSort:h,fromSortable:f,target:l,completed:A,onMove:function(t,e){return Lt(tt,a,$,o,t,X(t),n,e)},changed:N},e))}function M(){O("dragOverAnimationCapture"),p.captureAnimationState(),p!==f&&f.captureAnimationState()}function A(t){return O("dragOverCompleted",{insertion:t}),t&&(d?u._hideClone():u._showClone(p),p!==f&&(k($,(ut||u).options.ghostClass,!1),k($,s.ghostClass,!0)),ut!==p&&p!==Ht.active?ut=p:p===Ht.active&&ut&&(ut=null),f===p&&(p._ignoreWhileAnimating=l),p.animateAll(function(){O("dragOverAnimationComplete"),p._ignoreWhileAnimating=null}),p!==f&&(f.animateAll(),f._ignoreWhileAnimating=null)),(l===$&&!$.animated||l===a&&!l.animated)&&(bt=null),s.dragoverBubble||n.rootEl||l===document||($.parentNode[K]._isOutsideThisEl(n.target),t||Ft(n)),!s.dragoverBubble&&n.stopPropagation&&n.stopPropagation(),g=!0}function N(){at=j($),st=j($,s.draggable),Z({sortable:p,name:"change",toEl:a,newIndex:at,newDraggableIndex:st,originalEvent:n})}},_ignoreWhileAnimating:null,_offMoveEvents:function(){p(document,"mousemove",this._onTouchMove),p(document,"touchmove",this._onTouchMove),p(document,"pointermove",this._onTouchMove),p(document,"dragover",Ft),p(document,"mousemove",Ft),p(document,"touchmove",Ft)},_offUpEvents:function(){var t=this.el.ownerDocument;p(t,"mouseup",this._onDrop),p(t,"touchend",this._onDrop),p(t,"pointerup",this._onDrop),p(t,"pointercancel",this._onDrop),p(t,"touchcancel",this._onDrop),p(document,"selectstart",this)},_onDrop:function(t){var e=this.el,n=this.options;at=j($),st=j($,n.draggable),q("drop",this,{evt:t}),Q=$&&$.parentNode,at=j($),st=j($,n.draggable),Ht.eventCanceled||(Ct=Tt=Et=!1,clearInterval(this._loopId),clearTimeout(this._dragStartTimer),Gt(this.cloneId),Gt(this._dragStartId),this.nativeDraggable&&(p(document,"drop",this),p(e,"dragstart",this._onDragStart)),this._offMoveEvents(),this._offUpEvents(),u&&R(document.body,"user-select",""),R($,"transform",""),t&&(vt&&(t.cancelable&&t.preventDefault(),n.dropBubble||t.stopPropagation()),J&&J.parentNode&&J.parentNode.removeChild(J),(tt===Q||ut&&"clone"!==ut.lastPutMode)&&ot&&ot.parentNode&&ot.parentNode.removeChild(ot),$&&(this.nativeDraggable&&p($,"dragend",this),Kt($),$.style["will-change"]="",vt&&!Et&&k($,(ut||this).options.ghostClass,!1),k($,this.options.chosenClass,!1),Z({sortable:this,name:"unchoose",toEl:Q,newIndex:null,newDraggableIndex:null,originalEvent:t}),tt!==Q?(0<=at&&(Z({rootEl:Q,name:"add",toEl:Q,fromEl:tt,originalEvent:t}),Z({sortable:this,name:"remove",toEl:Q,originalEvent:t}),Z({rootEl:Q,name:"sort",toEl:Q,fromEl:tt,originalEvent:t}),Z({sortable:this,name:"sort",toEl:Q,originalEvent:t})),ut&&ut.save()):at!==rt&&0<=at&&(Z({sortable:this,name:"update",toEl:Q,originalEvent:t}),Z({sortable:this,name:"sort",toEl:Q,originalEvent:t})),Ht.active&&(null!=at&&-1!==at||(at=rt,st=lt),Z({sortable:this,name:"end",toEl:Q,originalEvent:t}),this.save())))),this._nulling()},_nulling:function(){q("nulling",this),tt=$=Q=J=et=ot=nt=it=dt=ht=vt=at=st=rt=lt=bt=yt=ut=ct=Ht.dragged=Ht.ghost=Ht.clone=Ht.active=null;var e=this.el;Mt.forEach(function(t){e.contains(t)&&(t.checked=!0)}),Mt.length=ft=pt=0},handleEvent:function(t){switch(t.type){case"drop":case"dragend":this._onDrop(t);break;case"dragenter":case"dragover":$&&(this._onDragOver(t),function(t){t.dataTransfer&&(t.dataTransfer.dropEffect="move");t.cancelable&&t.preventDefault()}(t));break;case"selectstart":t.preventDefault()}},toArray:function(){for(var t,e=[],n=this.el.children,o=0,i=n.length,r=this.options;o<i;o++)P(t=n[o],r.draggable,this.el,!1)&&e.push(t.getAttribute(r.dataIdAttr)||function(t){var e=t.tagName+t.className+t.src+t.href+t.textContent,n=e.length,o=0;for(;n--;)o+=e.charCodeAt(n);return o.toString(36)}(t));return e},sort:function(t,e){var n={},o=this.el;this.toArray().forEach(function(t,e){e=o.children[e];P(e,this.options.draggable,o,!1)&&(n[t]=e)},this),e&&this.captureAnimationState(),t.forEach(function(t){n[t]&&(o.removeChild(n[t]),o.appendChild(n[t]))}),e&&this.animateAll()},save:function(){var t=this.options.store;t&&t.set&&t.set(this)},closest:function(t,e){return P(t,e||this.options.draggable,this.el,!1)},option:function(t,e){var n=this.options;if(void 0===e)return n[t];var o=G.modifyOption(this,t,e);n[t]=void 0!==o?o:e,"group"===t&&Xt(n)},destroy:function(){q("destroy",this);var t=this.el;t[K]=null,p(t,"mousedown",this._onTapStart),p(t,"touchstart",this._onTapStart),p(t,"pointerdown",this._onTapStart),this.nativeDraggable&&(p(t,"dragover",this),p(t,"dragenter",this)),Array.prototype.forEach.call(t.querySelectorAll("[draggable]"),function(t){t.removeAttribute("draggable")}),this._onDrop(),this._disableDelayedDragEvents(),_t.splice(_t.indexOf(this.el),1),this.el=t=null},_hideClone:function(){it||(q("hideClone",this),Ht.eventCanceled||(R(ot,"display","none"),this.options.removeCloneOnHide&&ot.parentNode&&ot.parentNode.removeChild(ot),it=!0))},_showClone:function(t){"clone"===t.lastPutMode?it&&(q("showClone",this),Ht.eventCanceled||($.parentNode!=tt||this.options.group.revertClone?et?tt.insertBefore(ot,et):tt.appendChild(ot):tt.insertBefore(ot,$),this.options.group.revertClone&&this.animate($,ot),R(ot,"display",""),it=!1)):this._hideClone()}},At&&f(document,"touchmove",function(t){(Ht.active||Et)&&t.cancelable&&t.preventDefault()}),Ht.utils={on:f,off:p,css:R,find:E,is:function(t,e){return!!P(t,e,t,!1)},extend:function(t,e){if(t&&e)for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t},throttle:C,closest:P,toggleClass:k,clone:T,index:j,nextTick:zt,cancelNextTick:Gt,detectDirection:Rt,getChild:B,expando:K},Ht.get=function(t){return t[K]},Ht.mount=function(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];(e=e[0].constructor===Array?e[0]:e).forEach(function(t){if(!t.prototype||!t.prototype.constructor)throw"Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(t));t.utils&&(Ht.utils=I(I({},Ht.utils),t.utils)),G.mount(t)})},Ht.create=function(t,e){return new Ht(t,e)};var Ut,qt,Vt,Zt,$t,Qt,Jt=[],te=!(Ht.version="1.15.7");function ee(){Jt.forEach(function(t){clearInterval(t.pid)}),Jt=[]}function ne(){clearInterval(Qt)}var oe,ie=C(function(n,t,e,o){if(t.scroll){var i,r=(n.touches?n.touches[0]:n).clientX,a=(n.touches?n.touches[0]:n).clientY,l=t.scrollSensitivity,s=t.scrollSpeed,c=O(),u=!1;qt!==e&&(qt=e,ee(),Ut=t.scroll,i=t.scrollFn,!0===Ut&&(Ut=M(e,!0)));var d=0,h=Ut;do{var f=h,p=X(f),g=p.top,m=p.bottom,v=p.left,b=p.right,y=p.width,w=p.height,D=void 0,E=void 0,S=f.scrollWidth,_=f.scrollHeight,C=R(f),T=f.scrollLeft,p=f.scrollTop,E=f===c?(D=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX||"visible"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY||"visible"===C.overflowY)):(D=y<S&&("auto"===C.overflowX||"scroll"===C.overflowX),w<_&&("auto"===C.overflowY||"scroll"===C.overflowY)),T=D&&(Math.abs(b-r)<=l&&T+y<S)-(Math.abs(v-r)<=l&&!!T),p=E&&(Math.abs(m-a)<=l&&p+w<_)-(Math.abs(g-a)<=l&&!!p);if(!Jt[d])for(var x=0;x<=d;x++)Jt[x]||(Jt[x]={});Jt[d].vx==T&&Jt[d].vy==p&&Jt[d].el===f||(Jt[d].el=f,Jt[d].vx=T,Jt[d].vy=p,clearInterval(Jt[d].pid),0==T&&0==p||(u=!0,Jt[d].pid=setInterval(function(){o&&0===this.layer&&Ht.active._onTouchMove($t);var t=Jt[this.layer].vy?Jt[this.layer].vy*s:0,e=Jt[this.layer].vx?Jt[this.layer].vx*s:0;"function"==typeof i&&"continue"!==i.call(Ht.dragged.parentNode[K],e,t,n,$t,Jt[this.layer].el)||H(Jt[this.layer].el,e,t)}.bind({layer:d}),24))),d++}while(t.bubbleScroll&&h!==c&&(h=M(h,!1)));te=u}},30),n=function(t){var e=t.originalEvent,n=t.putSortable,o=t.dragEl,i=t.activeSortable,r=t.dispatchSortableEvent,a=t.hideGhostForTarget,t=t.unhideGhostForTarget;e&&(i=n||i,a(),e=e.changedTouches&&e.changedTouches.length?e.changedTouches[0]:e,e=document.elementFromPoint(e.clientX,e.clientY),t(),i&&!i.el.contains(e)&&(r("spill"),this.onSpill({dragEl:o,putSortable:n})))};function re(){}function ae(){}re.prototype={startIndex:null,dragStart:function(t){t=t.oldDraggableIndex;this.startIndex=t},onSpill:function(t){var e=t.dragEl,n=t.putSortable;this.sortable.captureAnimationState(),n&&n.captureAnimationState();t=B(this.sortable.el,this.startIndex,this.options);t?this.sortable.el.insertBefore(e,t):this.sortable.el.appendChild(e),this.sortable.animateAll(),n&&n.animateAll()},drop:n},a(re,{pluginName:"revertOnSpill"}),ae.prototype={onSpill:function(t){var e=t.dragEl,t=t.putSortable||this.sortable;t.captureAnimationState(),e.parentNode&&e.parentNode.removeChild(e),t.animateAll()},drop:n},a(ae,{pluginName:"removeOnSpill"});var le,se,ce,ue,de,he=[],fe=[],pe=!1,ge=!1,me=!1;function ve(n,o){fe.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)})}function be(){he.forEach(function(t){t!==ce&&t.parentNode&&t.parentNode.removeChild(t)})}return Ht.mount(new function(){function t(){for(var t in this.defaults={scroll:!0,forceAutoScrollFallback:!1,scrollSensitivity:30,scrollSpeed:10,bubbleScroll:!0},this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this))}return t.prototype={dragStarted:function(t){t=t.originalEvent;this.sortable.nativeDraggable?f(document,"dragover",this._handleAutoScroll):this.options.supportPointer?f(document,"pointermove",this._handleFallbackAutoScroll):t.touches?f(document,"touchmove",this._handleFallbackAutoScroll):f(document,"mousemove",this._handleFallbackAutoScroll)},dragOverCompleted:function(t){t=t.originalEvent;this.options.dragOverBubble||t.rootEl||this._handleAutoScroll(t)},drop:function(){this.sortable.nativeDraggable?p(document,"dragover",this._handleAutoScroll):(p(document,"pointermove",this._handleFallbackAutoScroll),p(document,"touchmove",this._handleFallbackAutoScroll),p(document,"mousemove",this._handleFallbackAutoScroll)),ne(),ee(),clearTimeout(v),v=void 0},nulling:function(){$t=qt=Ut=te=Qt=Vt=Zt=null,Jt.length=0},_handleFallbackAutoScroll:function(t){this._handleAutoScroll(t,!0)},_handleAutoScroll:function(e,n){var o,i=this,r=(e.touches?e.touches[0]:e).clientX,a=(e.touches?e.touches[0]:e).clientY,t=document.elementFromPoint(r,a);$t=e,n||this.options.forceAutoScrollFallback||w||y||u?(ie(e,this.options,t,n),o=M(t,!0),!te||Qt&&r===Vt&&a===Zt||(Qt&&ne(),Qt=setInterval(function(){var t=M(document.elementFromPoint(r,a),!0);t!==o&&(o=t,ee()),ie(e,i.options,t,n)},10),Vt=r,Zt=a)):this.options.bubbleScroll&&M(t,!0)!==O()?ie(e,this.options,M(t,!1),!1):ee()}},a(t,{pluginName:"scroll",initializeByDefault:!0})}),Ht.mount(ae,re),Ht.mount(new function(){function t(){this.defaults={swapClass:"sortable-swap-highlight"}}return t.prototype={dragStart:function(t){t=t.dragEl;oe=t},dragOverValid:function(t){var e=t.completed,n=t.target,o=t.onMove,i=t.activeSortable,r=t.changed,a=t.cancel;i.options.swap&&(t=this.sortable.el,i=this.options,n&&n!==t&&(t=oe,oe=!1!==o(n)?(k(n,i.swapClass,!0),n):null,t&&t!==oe&&k(t,i.swapClass,!1)),r(),e(!0),a())},drop:function(t){var e,n,o=t.activeSortable,i=t.putSortable,r=t.dragEl,a=i||this.sortable,l=this.options;oe&&k(oe,l.swapClass,!1),oe&&(l.swap||i&&i.options.swap)&&r!==oe&&(a.captureAnimationState(),a!==o&&o.captureAnimationState(),n=oe,t=(e=r).parentNode,l=n.parentNode,t&&l&&!t.isEqualNode(n)&&!l.isEqualNode(e)&&(i=j(e),r=j(n),t.isEqualNode(l)&&i<r&&r++,t.insertBefore(n,t.children[i]),l.insertBefore(e,l.children[r])),a.animateAll(),a!==o&&o.animateAll())},nulling:function(){oe=null}},a(t,{pluginName:"swap",eventProperties:function(){return{swapItem:oe}}})}),Ht.mount(new function(){function t(o){for(var t in this)"_"===t.charAt(0)&&"function"==typeof this[t]&&(this[t]=this[t].bind(this));o.options.avoidImplicitDeselect||(o.options.supportPointer?f(document,"pointerup",this._deselectMultiDrag):(f(document,"mouseup",this._deselectMultiDrag),f(document,"touchend",this._deselectMultiDrag))),f(document,"keydown",this._checkKeyDown),f(document,"keyup",this._checkKeyUp),this.defaults={selectedClass:"sortable-selected",multiDragKey:null,avoidImplicitDeselect:!1,setData:function(t,e){var n="";he.length&&se===o?he.forEach(function(t,e){n+=(e?", ":"")+t.textContent}):n=e.textContent,t.setData("Text",n)}}}return t.prototype={multiDragKeyDown:!1,isMultiDrag:!1,delayStartGlobal:function(t){t=t.dragEl;ce=t},delayEnded:function(){this.isMultiDrag=~he.indexOf(ce)},setupClone:function(t){var e=t.sortable,t=t.cancel;if(this.isMultiDrag){for(var n=0;n<he.length;n++)fe.push(T(he[n])),fe[n].sortableIndex=he[n].sortableIndex,fe[n].draggable=!1,fe[n].style["will-change"]="",k(fe[n],this.options.selectedClass,!1),he[n]===ce&&k(fe[n],this.options.chosenClass,!1);e._hideClone(),t()}},clone:function(t){var e=t.sortable,n=t.rootEl,o=t.dispatchSortableEvent,t=t.cancel;this.isMultiDrag&&(this.options.removeCloneOnHide||he.length&&se===e&&(ve(!0,n),o("clone"),t()))},showClone:function(t){var e=t.cloneNowShown,n=t.rootEl,t=t.cancel;this.isMultiDrag&&(ve(!1,n),fe.forEach(function(t){R(t,"display","")}),e(),de=!1,t())},hideClone:function(t){var e=this,n=(t.sortable,t.cloneNowHidden),t=t.cancel;this.isMultiDrag&&(fe.forEach(function(t){R(t,"display","none"),e.options.removeCloneOnHide&&t.parentNode&&t.parentNode.removeChild(t)}),n(),de=!0,t())},dragStartGlobal:function(t){t.sortable;!this.isMultiDrag&&se&&se.multiDrag._deselectMultiDrag(),he.forEach(function(t){t.sortableIndex=j(t)}),he=he.sort(function(t,e){return t.sortableIndex-e.sortableIndex}),me=!0},dragStarted:function(t){var e,n=this,t=t.sortable;this.isMultiDrag&&(this.options.sort&&(t.captureAnimationState(),this.options.animation&&(he.forEach(function(t){t!==ce&&R(t,"position","absolute")}),e=X(ce,!1,!0,!0),he.forEach(function(t){t!==ce&&x(t,e)}),pe=ge=!0)),t.animateAll(function(){pe=ge=!1,n.options.animation&&he.forEach(function(t){A(t)}),n.options.sort&&be()}))},dragOver:function(t){var e=t.target,n=t.completed,t=t.cancel;ge&&~he.indexOf(e)&&(n(!1),t())},revert:function(t){var n,o,e=t.fromSortable,i=t.rootEl,r=t.sortable,a=t.dragRect;1<he.length&&(he.forEach(function(t){r.addAnimationState({target:t,rect:ge?X(t):a}),A(t),t.fromRect=a,e.removeAnimationState(t)}),ge=!1,n=!this.options.removeCloneOnHide,o=i,he.forEach(function(t,e){e=o.children[t.sortableIndex+(n?Number(e):0)];e?o.insertBefore(t,e):o.appendChild(t)}))},dragOverCompleted:function(t){var e,n=t.sortable,o=t.isOwner,i=t.insertion,r=t.activeSortable,a=t.parentEl,l=t.putSortable,t=this.options;i&&(o&&r._hideClone(),pe=!1,t.animation&&1<he.length&&(ge||!o&&!r.options.sort&&!l)&&(e=X(ce,!1,!0,!0),he.forEach(function(t){t!==ce&&(x(t,e),a.appendChild(t))}),ge=!0),o||(ge||be(),1<he.length?(o=de,r._showClone(n),r.options.animation&&!de&&o&&fe.forEach(function(t){r.addAnimationState({target:t,rect:ue}),t.fromRect=ue,t.thisAnimationDuration=null})):r._showClone(n)))},dragOverAnimationCapture:function(t){var e=t.dragRect,n=t.isOwner,t=t.activeSortable;he.forEach(function(t){t.thisAnimationDuration=null}),t.options.animation&&!n&&t.multiDrag.isMultiDrag&&(ue=a({},e),e=D(ce,!0),ue.top-=e.f,ue.left-=e.e)},dragOverAnimationComplete:function(){ge&&(ge=!1,be())},drop:function(t){var o,i,r,a,n,e,l,s=t.originalEvent,c=t.rootEl,u=t.parentEl,d=t.sortable,h=t.dispatchSortableEvent,f=t.oldIndex,t=t.putSortable,p=t||this.sortable;s&&(o=this.options,i=u.children,me||(o.multiDragKey&&!this.multiDragKeyDown&&this._deselectMultiDrag(),k(ce,o.selectedClass,!~he.indexOf(ce)),~he.indexOf(ce)?(he.splice(he.indexOf(ce),1),le=null,U({sortable:d,rootEl:c,name:"deselect",targetEl:ce,originalEvent:s})):(he.push(ce),U({sortable:d,rootEl:c,name:"select",targetEl:ce,originalEvent:s}),s.shiftKey&&le&&d.el.contains(le)?(r=j(le),a=j(ce),~r&&~a&&r!==a&&function(){for(var e,t=r<a?(e=r,a):(e=a,r+1),n=o.filter;e<t;e++)~he.indexOf(i[e])||P(i[e],o.draggable,u,!1)&&(n&&("function"==typeof n?n.call(d,s,i[e],d):n.split(",").some(function(t){return P(i[e],t.trim(),u,!1)}))||(k(i[e],o.selectedClass,!0),he.push(i[e]),U({sortable:d,rootEl:c,name:"select",targetEl:i[e],originalEvent:s})))}()):le=ce,se=p)),me&&this.isMultiDrag&&(ge=!1,(u[K].options.sort||u!==c)&&1<he.length&&(n=X(ce),e=j(ce,":not(."+this.options.selectedClass+")"),!pe&&o.animation&&(ce.thisAnimationDuration=null),p.captureAnimationState(),pe||(o.animation&&(ce.fromRect=n,he.forEach(function(t){var e;t.thisAnimationDuration=null,t!==ce&&(e=ge?X(t):n,t.fromRect=e,p.addAnimationState({target:t,rect:e}))})),be(),he.forEach(function(t){i[e]?u.insertBefore(t,i[e]):u.appendChild(t),e++}),f===j(ce)&&(l=!1,he.forEach(function(t){t.sortableIndex!==j(t)&&(l=!0)}),l&&(h("update"),h("sort")))),he.forEach(function(t){A(t)}),p.animateAll()),se=p),(c===u||t&&"clone"!==t.lastPutMode)&&fe.forEach(function(t){t.parentNode&&t.parentNode.removeChild(t)}))},nullingGlobal:function(){this.isMultiDrag=me=!1,fe.length=0},destroyGlobal:function(){this._deselectMultiDrag(),p(document,"pointerup",this._deselectMultiDrag),p(document,"mouseup",this._deselectMultiDrag),p(document,"touchend",this._deselectMultiDrag),p(document,"keydown",this._checkKeyDown),p(document,"keyup",this._checkKeyUp)},_deselectMultiDrag:function(t){if(!(void 0!==me&&me||se!==this.sortable||t&&P(t.target,this.options.draggable,this.sortable.el,!1)||t&&0!==t.button))for(;he.length;){var e=he[0];k(e,this.options.selectedClass,!1),he.shift(),U({sortable:this.sortable,rootEl:this.sortable.el,name:"deselect",targetEl:e,originalEvent:t})}},_checkKeyDown:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!0)},_checkKeyUp:function(t){t.key===this.options.multiDragKey&&(this.multiDragKeyDown=!1)}},a(t,{pluginName:"multiDrag",utils:{select:function(t){var e=t.parentNode[K];e&&e.options.multiDrag&&!~he.indexOf(t)&&(se&&se!==e&&(se.multiDrag._deselectMultiDrag(),se=e),k(t,e.options.selectedClass,!0),he.push(t))},deselect:function(t){var e=t.parentNode[K],n=he.indexOf(t);e&&e.options.multiDrag&&~n&&(k(t,e.options.selectedClass,!1),he.splice(n,1))}},eventProperties:function(){var n=this,o=[],i=[];return he.forEach(function(t){var e;o.push({multiDragElement:t,index:t.sortableIndex}),e=ge&&t!==ce?-1:ge?j(t,":not(."+n.options.selectedClass+")"):j(t),i.push({multiDragElement:t,index:e})}),{items:e(he),clones:[].concat(fe),oldIndicies:o,newIndicies:i}},optionListeners:{multiDragKey:function(t){return"ctrl"===(t=t.toLowerCase())?t="Control":1<t.length&&(t=t.charAt(0).toUpperCase()+t.substr(1)),t}}})}),Ht});
|