build-container / build (push) Successful in 4m14s
- Built-in Family calendar everyone with Calendar can edit (data/family) - Family task list shared by everyone with Tasks - New notes and lists start shared with the family - Phone chat sized above the bottom bar and mini player so the message box is visible - Family page cards no longer overflow on long chat previews - Tests added and updated Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
24 lines
3.0 KiB
JavaScript
24 lines
3.0 KiB
JavaScript
// The shared Family calendar and Family task list: every person with the tab sees and edits the same ones.
|
|
const http = require('http'), assert = require('assert'), fs = require('fs'), os = require('os'), path = require('path');
|
|
process.env.DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), 'nehub-fam-'));
|
|
const users = require('../users'), cal = require('../cal'), tasks = require('../tasks');
|
|
const P = { a: users.create({ name: 'Ann', role: 'admin', handle: 'YQ' }), b: users.create({ name: 'Bob', role: 'user', tabs: ['calendar', 'tasks'], handle: 'Yg' }), c: users.create({ name: 'Cy', role: 'user', tabs: ['notes'], handle: 'Yw' }) };
|
|
const hub = http.createServer((req, res) => users.runAs(P[req.headers['x-user'] || 'a'], () => req.url.startsWith('/api/tasks') ? tasks.handle(req, res) : cal.handle(req, res))).listen(0, async () => {
|
|
const B = 'http://127.0.0.1:' + hub.address().port, call = (p, o = {}, who) => fetch(B + p, { ...o, headers: { ...(o.headers || {}), ...(who ? { 'x-user': who } : {}) } }), post = (p, b, who) => call(p, { method: 'POST', body: JSON.stringify(b) }, who), j = r => r.json();
|
|
try {
|
|
const day = new Date().toISOString().slice(0, 10), ev = { summary: 'Dinner at Grandma\'s', start: day + 'T18:00', end: day + 'T19:00' };
|
|
let r = await j(await post('/api/cal/event', { cal: 'family~local', fields: { title: 'Dinner at 6', start: day, end: day, allDay: true } }, 'a')); assert.ok(r.ok, JSON.stringify(r));
|
|
const win = '/api/cal/events?' + new URLSearchParams({ from: Date.parse(day + 'T00:00:00Z') - 864e5, to: Date.parse(day + 'T00:00:00Z') + 2 * 864e5, fd: day, td: day });
|
|
let e = await j(await call(win, {}, 'b')); assert.ok(e.events.some(x => x.title === 'Dinner at 6' && x.editable), 'Bob sees and can edit the family event');
|
|
assert.ok(!(await j(await call(win, {}, 'c'))).events.some(x => x.title === 'Dinner at 6'), 'Cy has no calendar tab: nothing');
|
|
assert.ok((await j(await call('/api/cal/list', {}, 'b'))).some(c => c.id === 'family~local' && c.name === 'Family'));
|
|
const lists = (await j(await call('/api/tasks/lists', {}, 'b'))).lists; assert.deepEqual(lists.map(l => l.name), ['Tasks', 'Family']);
|
|
await post('/api/tasks', { list: 'local:family', fields: { title: 'Book the sitter', due: day } }, 'a');
|
|
let t = await j(await call('/api/tasks?list=local:family', {}, 'b')); assert.equal(t.length, 1, 'Bob sees the family task'); assert.equal((await j(await call('/api/tasks?list=local:inbox', {}, 'b'))).length, 0);
|
|
await post('/api/tasks/toggle', { id: t[0].id, list: 'local:family', done: true }, 'b'); t = await j(await call('/api/tasks?list=local:family', {}, 'a')); assert.equal(t[0].done, true, 'ticked by Bob, seen by Ann');
|
|
const del = await post('/api/tasks/lists/delete', { id: 'local:family' }, 'a'); assert.equal(del.status, 400, 'the Family list stays');
|
|
console.log('family ok');
|
|
} catch (e) { console.error(e); process.exitCode = 1; }
|
|
hub.close(); setTimeout(() => process.exit(process.exitCode || 0), 50);
|
|
});
|