[Calendar] Introduce permissions for editing events

This commit is contained in:
metacryst
2026-04-30 02:07:35 -05:00
parent 8b083ae7bb
commit 19a810ef78
7 changed files with 91 additions and 63 deletions

View File

@@ -1,4 +1,4 @@
import server from "/@server/server.js" import server from "/calendar/@server/calendar.js"
import calendarUtil from "../calendarUtil.js" import calendarUtil from "../calendarUtil.js"
import "./EventForm.js" import "./EventForm.js"
import "../../components/BottomSheet.js" import "../../components/BottomSheet.js"
@@ -39,10 +39,11 @@ class EventDetails extends Shadow {
render() { render() {
this.editSheet = BottomSheet(100) // separate sheet for the edit form, layered above this one this.editSheet = BottomSheet(100) // separate sheet for the edit form, layered above this one
const isOwner = this.event?.creator_id === global.profile?.id; // Editing is currently owner-only: this flag gates the mobile Edit/Delete actions.
const canEdit = global.currentNetwork.permissions.includes("events.edit")
VStack(() => { VStack(() => {
this.renderHeader(isOwner) this.renderHeader(canEdit)
// ── Error toast ─────────────────────────────────────── // ── Error toast ───────────────────────────────────────
VStack(() => { VStack(() => {
@@ -276,11 +277,12 @@ class EventDetails extends Shadow {
.height(100, pct) .height(100, pct)
} }
renderHeader(isOwner) { renderHeader(canEdit) {
VStack(() => { VStack(() => {
HStack(() => { HStack(() => {
BackButton(false, true, () => $("bottomsheet-").toggle()) BackButton(false, true, () => $("bottomsheet-").toggle())
if (isOwner) { // Non-owners never see the controls that open the edit sheet or delete flow.
if (canEdit) {
HStack(() => { HStack(() => {
// ── Delete button ───────────────────────────────── // ── Delete button ─────────────────────────────────
button("Delete") button("Delete")

View File

@@ -1,4 +1,4 @@
import server from "/@server/server.js" import server from "/calendar/@server/calendar.js"
import calendarUtil from "../../calendarUtil.js" import calendarUtil from "../../calendarUtil.js"
import "../../../components/Avatar.js" import "../../../components/Avatar.js"
@@ -19,10 +19,10 @@ class DesktopEventDetails extends Shadow {
if (!this.event) return if (!this.event) return
const eventCals = this.calendars.filter(c => this.event.calendars?.includes(c.id)) const eventCals = this.calendars.filter(c => this.event.calendars?.includes(c.id))
const isOwner = this.event.creator_id === global.profile?.id const canEdit = global.currentNetwork.permissions.includes("events.edit")
VStack(() => { VStack(() => {
this.renderHeader(isOwner) this.renderHeader(canEdit)
this.renderBody(eventCals) this.renderBody(eventCals)
HStack(() => { HStack(() => {
const members = global.currentNetwork.data?.members || [] const members = global.currentNetwork.data?.members || []
@@ -53,7 +53,7 @@ class DesktopEventDetails extends Shadow {
// ── Header ──────────────────────────────────────────────────────────────── // ── Header ────────────────────────────────────────────────────────────────
renderHeader(isOwner) { renderHeader(canEdit) {
HStack(() => { HStack(() => {
VStack(() => { VStack(() => {
h2(this.event.title || "Untitled") h2(this.event.title || "Untitled")
@@ -69,7 +69,8 @@ class DesktopEventDetails extends Shadow {
.paddingBottom(0.5, em) .paddingBottom(0.5, em)
.justifyContent("center") .justifyContent("center")
if (isOwner) { // Non-owners never see the controls that open the edit form or delete flow.
if (canEdit) {
button("Delete") button("Delete")
.paddingVertical(0.34, em) .paddingVertical(0.34, em)
.paddingHorizontal(0.85, em) .paddingHorizontal(0.85, em)

View File

@@ -1,9 +1,10 @@
import fs from 'fs'
export async function setEventTime(eventId, startHour, startMin, endHour, endMin, month, day, year = 2026) { export async function setEventTime(eventId, startHour, startMin, endHour, endMin, month, day, year = 2026) {
const start = new Date(`${year}-${String(month).padStart(2,'0')}-${String(day).padStart(2,'0')}T${String(startHour).padStart(2,'0')}:${String(startMin).padStart(2,'0')}:00-05:00`) const start = new Date(`${year}-${String(month).padStart(2,'0')}-${String(day).padStart(2,'0')}T${String(startHour).padStart(2,'0')}:${String(startMin).padStart(2,'0')}:00-05:00`)
const end = new Date(`${year}-${String(month).padStart(2,'0')}-${String(day).padStart(2,'0')}T${String(endHour).padStart(2,'0')}:${String(endMin).padStart(2,'0')}:00-05:00`) const end = new Date(`${year}-${String(month).padStart(2,'0')}-${String(day).padStart(2,'0')}T${String(endHour).padStart(2,'0')}:${String(endMin).padStart(2,'0')}:00-05:00`)
console.log(start, end) await context.sql`
await this.sql`
UPDATE events.events UPDATE events.events
SET time_start = ${start}, time_end = ${end} SET time_start = ${start}, time_end = ${end}
WHERE id = ${eventId} WHERE id = ${eventId}
@@ -22,7 +23,7 @@ export async function getEventsByNetwork(networkId) {
} }
// Returns each event with its linked calendar IDs, file attachments, and recurrence rule // Returns each event with its linked calendar IDs, file attachments, and recurrence rule
return await this.sql` return await context.sql`
SELECT e.*, SELECT e.*,
COALESCE(jsonb_agg(DISTINCT ec.calendar_id) FILTER (WHERE ec.calendar_id IS NOT NULL), '[]') AS calendars, COALESCE(jsonb_agg(DISTINCT ec.calendar_id) FILTER (WHERE ec.calendar_id IS NOT NULL), '[]') AS calendars,
COALESCE(jsonb_agg(DISTINCT jsonb_build_object('id', f.id, 'name', f.name, 'type', f.type, 'original_name', f.original_name, 'size_bytes', f.size_bytes)) FILTER (WHERE f.id IS NOT NULL), '[]') AS attachments, COALESCE(jsonb_agg(DISTINCT jsonb_build_object('id', f.id, 'name', f.name, 'type', f.type, 'original_name', f.original_name, 'size_bytes', f.size_bytes)) FILTER (WHERE f.id IS NOT NULL), '[]') AS attachments,
@@ -42,22 +43,23 @@ export async function getCalendarsByNetwork(networkId) {
throw new global.ServerError(400, "Invalid network ID!"); throw new global.ServerError(400, "Invalid network ID!");
} }
return await this.sql` return await context.sql`
SELECT c.* FROM events.calendars c SELECT c.* FROM events.calendars c
WHERE c.network_id = ${networkId} WHERE c.network_id = ${networkId}
`; `;
} }
export async function addCalendar(userId, newCalendar, networkId) { export async function addCalendar(newCalendar, networkId) {
//@ should have scoping here
const { name, description, color } = newCalendar; const { name, description, color } = newCalendar;
try { try {
let insertedCalendar; let insertedCalendar;
await this.sql.begin(async tx => { await context.sql.begin(async tx => {
const [calendar] = await tx` const [calendar] = await tx`
INSERT INTO events.calendars ${tx({ INSERT INTO events.calendars ${tx({
network_id: networkId, network_id: networkId,
owner_id: userId, owner_id: context.userId,
name: name, name: name,
description: description ?? null, description: description ?? null,
color: color color: color
@@ -74,10 +76,10 @@ export async function addCalendar(userId, newCalendar, networkId) {
} }
} }
export async function editCalendar(userId, id, updatedCalendar, networkId) { export async function editCalendar(id, updatedCalendar, networkId) {
const { name, description, color } = updatedCalendar; const { name, description, color } = updatedCalendar;
try { try {
const [calendar] = await this.sql` const [calendar] = await context.sql`
UPDATE events.calendars UPDATE events.calendars
SET SET
name = ${name}, name = ${name},
@@ -87,7 +89,8 @@ export async function editCalendar(userId, id, updatedCalendar, networkId) {
WHERE WHERE
id = ${id} id = ${id}
AND network_id = ${networkId} AND network_id = ${networkId}
AND owner_id = ${userId} --@ Calendar editing is owner-only on the backend.
AND owner_id = ${context.userId}
RETURNING * RETURNING *
`; `;
@@ -99,11 +102,12 @@ export async function editCalendar(userId, id, updatedCalendar, networkId) {
} }
} }
export async function deleteCalendar(userId, id, networkId) { export async function deleteCalendar(id, networkId) {
try { try {
const [calendar] = await this.sql` //@ Calendar deletion is owner-only on the backend.
const [calendar] = await context.sql`
DELETE FROM events.calendars DELETE FROM events.calendars
WHERE id = ${id} AND network_id = ${networkId} AND owner_id = ${userId} WHERE id = ${id} AND network_id = ${networkId} AND owner_id = ${context.userId}
RETURNING * RETURNING *
`; `;
if (!calendar) return { status: 403, error: "Calendar not found or not authorized" }; if (!calendar) return { status: 403, error: "Calendar not found or not authorized" };
@@ -114,12 +118,12 @@ export async function deleteCalendar(userId, id, networkId) {
} }
} }
export async function addEvent(userId, newEvent, networkId) { export async function addEvent(newEvent, networkId) {
const { title, description, location, time_start, time_end, all_day, calendars, recurrence } = newEvent; const { title, description, location, time_start, time_end, all_day, calendars, recurrence } = newEvent;
try { try {
let insertedEvent; let insertedEvent;
await this.sql.begin(async tx => { await context.sql.begin(async tx => {
let recurrenceId = null; let recurrenceId = null;
if (recurrence) { if (recurrence) {
const [rule] = await tx` const [rule] = await tx`
@@ -137,7 +141,7 @@ export async function addEvent(userId, newEvent, networkId) {
const [event] = await tx` const [event] = await tx`
INSERT INTO events.events ${tx({ INSERT INTO events.events ${tx({
network_id: networkId, network_id: networkId,
creator_id: userId, creator_id: context.userId,
title, title,
description: description ?? null, description: description ?? null,
location: location ?? null, location: location ?? null,
@@ -162,18 +166,30 @@ export async function addEvent(userId, newEvent, networkId) {
} }
} }
export async function networkFromEvent(eventId) {
return await context.sql`
SELECT c.network_id
FROM events.event_calendars ec
JOIN events.calendars c ON c.id = ec.calendar_id
WHERE ec.event_id = ${eventId};
`
}
export async function addAttachments(userId, eventId, files) { export async function addAttachments(userId, eventId, files) {
const [event] = await this.sql` let results = await networkFromEvent(eventId)
if(!(await global.permissions.canDo("events.edit", userId, results[0].network_id))) return { status: 403, error: "Forbidden" };
const [event] = await context.sql`
SELECT id FROM events.events SELECT id FROM events.events
WHERE id = ${eventId} AND creator_id = ${userId} WHERE id = ${eventId} AND creator_id = ${userId}
`; `;
if (!event) throw new global.ServerError(403, "Not authorized to add attachments to this event"); if (!event) throw new global.ServerError(403, "Not authorized to add attachments to this event");
try { try {
let insertedFiles = []; let insertedFiles = [];
// Will rollback changes if it encounters an error // Will rollback changes if it encounters an error
await this.sql.begin(async tx => { await context.sql.begin(async tx => {
insertedFiles = await Promise.all( insertedFiles = await Promise.all(
files.map(file => files.map(file =>
tx` tx`
@@ -207,13 +223,16 @@ export async function addAttachments(userId, eventId, files) {
} }
export async function deleteAttachment(userId, fileId, eventId) { export async function deleteAttachment(userId, fileId, eventId) {
const [event] = await this.sql` let results = await networkFromEvent(eventId)
if(!(await global.permissions.canDo("events.edit", userId, results[0].network_id))) return { status: 403, error: "Forbidden" };
const [event] = await context.sql`
SELECT id FROM events.events SELECT id FROM events.events
WHERE id = ${eventId} AND creator_id = ${userId} WHERE id = ${eventId} AND creator_id = ${userId}
`; `;
if (!event) throw new global.ServerError(403, "Not authorized to modify this event"); if (!event) throw new global.ServerError(403, "Not authorized to modify this event");
const [file] = await this.sql` const [file] = await context.sql`
SELECT f.* FROM public.files f SELECT f.* FROM public.files f
JOIN public.file_to_event fte ON fte.file_id = f.id JOIN public.file_to_event fte ON fte.file_id = f.id
WHERE f.id = ${fileId} AND fte.event_id = ${eventId} WHERE f.id = ${fileId} AND fte.event_id = ${eventId}
@@ -222,7 +241,7 @@ export async function deleteAttachment(userId, fileId, eventId) {
try { try {
let deletedFile = null; let deletedFile = null;
await this.sql.begin(async tx => { await context.sql.begin(async tx => {
await tx`DELETE FROM public.file_to_event WHERE file_id = ${fileId} AND event_id = ${eventId}`; await tx`DELETE FROM public.file_to_event WHERE file_id = ${fileId} AND event_id = ${eventId}`;
// Only remove the file record (and trigger disk unlink) if no other event still references it // Only remove the file record (and trigger disk unlink) if no other event still references it
const [stillReferenced] = await tx`SELECT 1 FROM public.file_to_event WHERE file_id = ${fileId} LIMIT 1`; const [stillReferenced] = await tx`SELECT 1 FROM public.file_to_event WHERE file_id = ${fileId} LIMIT 1`;
@@ -238,16 +257,17 @@ export async function deleteAttachment(userId, fileId, eventId) {
} }
} }
export async function editEvent(userId, id, updatedEvent, networkId) { export async function editEvent(id, updatedEvent, networkId) {
if(!(await global.permissions.canDo("events.edit", context.userId, networkId))) return { status: 403, error: "Forbidden" };
const { title, description, location, time_start, time_end, all_day, calendars, recurrence, scope, exception_date } = updatedEvent; const { title, description, location, time_start, time_end, all_day, calendars, recurrence, scope, exception_date } = updatedEvent;
try { try {
let editedEvent; let editedEvent;
await this.sql.begin(async tx => { await context.sql.begin(async tx => {
const [current] = await tx` const [current] = await tx`
SELECT * FROM events.events SELECT * FROM events.events
WHERE id = ${id} AND network_id = ${networkId} AND creator_id = ${userId} WHERE id = ${id} AND network_id = ${networkId}
`; `;
if (!current) return; if (!current) return;
@@ -299,7 +319,7 @@ export async function editEvent(userId, id, updatedEvent, networkId) {
all_day = ${all_day}, all_day = ${all_day},
recurrence_id = ${newRecurrenceId}, recurrence_id = ${newRecurrenceId},
updated_at = NOW() updated_at = NOW()
WHERE id = ${id} AND network_id = ${networkId} AND creator_id = ${userId} WHERE id = ${id} AND network_id = ${networkId} AND creator_id = ${context.userId}
RETURNING * RETURNING *
`; `;
if (!event) return; if (!event) return;
@@ -321,7 +341,7 @@ export async function editEvent(userId, id, updatedEvent, networkId) {
const [override] = await tx` const [override] = await tx`
INSERT INTO events.events ${tx({ INSERT INTO events.events ${tx({
network_id: networkId, network_id: networkId,
creator_id: userId, creator_id: context.userId,
title, title,
description: description ?? null, description: description ?? null,
location: location ?? null, location: location ?? null,
@@ -410,7 +430,7 @@ export async function editEvent(userId, id, updatedEvent, networkId) {
const [newEvent] = await tx` const [newEvent] = await tx`
INSERT INTO events.events ${tx({ INSERT INTO events.events ${tx({
network_id: networkId, network_id: networkId,
creator_id: userId, creator_id: context.userId,
title, title,
description: description ?? null, description: description ?? null,
location: location ?? null, location: location ?? null,
@@ -453,11 +473,12 @@ export async function editEvent(userId, id, updatedEvent, networkId) {
} }
} }
export async function deleteEvent(userId, eventId, networkId, scope, exception_date) { export async function deleteEvent(eventId, networkId, scope, exception_date) {
if(!global.permissions.canDo("events.delete", context.userId, networkId)) return { status: 403, error: "Forbidden" };
try { try {
const [event] = await this.sql` const [event] = await context.sql`
SELECT * FROM events.events SELECT * FROM events.events
WHERE id = ${eventId} AND network_id = ${networkId} AND creator_id = ${userId} WHERE id = ${eventId} AND network_id = ${networkId}
`; `;
if (!event) return { status: 403, error: "Event not found or not authorized" }; if (!event) return { status: 403, error: "Event not found or not authorized" };
@@ -466,16 +487,16 @@ export async function deleteEvent(userId, eventId, networkId, scope, exception_d
if (isOverride) { if (isOverride) {
// Already a concrete row — just mark it cancelled // Already a concrete row — just mark it cancelled
await this.sql`UPDATE events.events SET is_cancelled = true WHERE id = ${eventId}`; await context.sql`UPDATE events.events SET is_cancelled = true WHERE id = ${eventId}`;
return { status: 200 }; return { status: 200 };
} }
if (isRecurring && scope === 'single') { if (isRecurring && scope === 'single') {
// Virtual occurrence — insert a cancelled placeholder so it gets skipped // Virtual occurrence — insert a cancelled placeholder so it gets skipped
await this.sql` await context.sql`
INSERT INTO events.events ${this.sql({ INSERT INTO events.events ${context.sql({
network_id: networkId, network_id: networkId,
creator_id: userId, creator_id: context.userId,
title: event.title, title: event.title,
time_start: exception_date, time_start: exception_date,
time_end: exception_date, time_end: exception_date,
@@ -490,16 +511,16 @@ export async function deleteEvent(userId, eventId, networkId, scope, exception_d
if (isRecurring && scope === 'future' && new Date(exception_date) > new Date(event.time_start)) { if (isRecurring && scope === 'future' && new Date(exception_date) > new Date(event.time_start)) {
// Capture current end_date before modifying — marks the boundary of independent later splits // Capture current end_date before modifying — marks the boundary of independent later splits
const [existingRule] = await this.sql`SELECT end_date FROM events.event_recurrence WHERE id = ${event.recurrence_id}`; const [existingRule] = await context.sql`SELECT end_date FROM events.event_recurrence WHERE id = ${event.recurrence_id}`;
const oldEndDate = existingRule?.end_date ?? null; const oldEndDate = existingRule?.end_date ?? null;
// Cap the series at this date // Cap the series at this date
await this.sql` await context.sql`
UPDATE events.event_recurrence SET end_date = ${exception_date}, updated_at = NOW() UPDATE events.event_recurrence SET end_date = ${exception_date}, updated_at = NOW()
WHERE id = ${event.recurrence_id} WHERE id = ${event.recurrence_id}
`; `;
// Promote future non-cancelled overrides (single-event edits) to standalone events // Promote future non-cancelled overrides (single-event edits) to standalone events
await this.sql` await context.sql`
UPDATE events.events UPDATE events.events
SET recurrence_parent_id = NULL, recurrence_exception_date = NULL, updated_at = NOW() SET recurrence_parent_id = NULL, recurrence_exception_date = NULL, updated_at = NOW()
WHERE recurrence_parent_id = ${eventId} WHERE recurrence_parent_id = ${eventId}
@@ -507,24 +528,24 @@ export async function deleteEvent(userId, eventId, networkId, scope, exception_d
AND (is_cancelled IS NULL OR is_cancelled = false) AND (is_cancelled IS NULL OR is_cancelled = false)
`; `;
// Drop future cancelled placeholders — they are meaningless without the series // Drop future cancelled placeholders — they are meaningless without the series
await this.sql` await context.sql`
DELETE FROM events.events DELETE FROM events.events
WHERE recurrence_parent_id = ${eventId} AND recurrence_exception_date >= ${exception_date} WHERE recurrence_parent_id = ${eventId} AND recurrence_exception_date >= ${exception_date}
AND is_cancelled = true AND is_cancelled = true
`; `;
// Remove intermediate descendant templates in [exception_date, oldEndDate); independent splits at/beyond oldEndDate are preserved // Remove intermediate descendant templates in [exception_date, oldEndDate); independent splits at/beyond oldEndDate are preserved
const descendants = await this.sql` const descendants = await context.sql`
SELECT id, recurrence_id FROM events.events SELECT id, recurrence_id FROM events.events
WHERE parent_template_id = ${eventId} WHERE parent_template_id = ${eventId}
AND time_start >= ${exception_date} AND time_start >= ${exception_date}
${oldEndDate ? this.sql`AND time_start < ${oldEndDate}` : this.sql``} ${oldEndDate ? context.sql`AND time_start < ${oldEndDate}` : context.sql``}
`; `;
if (descendants.length > 0) { if (descendants.length > 0) {
const descIds = descendants.map(d => d.id); const descIds = descendants.map(d => d.id);
const descRuleIds = descendants.map(d => d.recurrence_id).filter(Boolean); const descRuleIds = descendants.map(d => d.recurrence_id).filter(Boolean);
await this.sql`DELETE FROM events.events WHERE id = ANY(${descIds})`; await context.sql`DELETE FROM events.events WHERE id = ANY(${descIds})`;
if (descRuleIds.length > 0) { if (descRuleIds.length > 0) {
await this.sql`DELETE FROM events.event_recurrence WHERE id = ANY(${descRuleIds})`; await context.sql`DELETE FROM events.event_recurrence WHERE id = ANY(${descRuleIds})`;
} }
} }
return { status: 200 }; return { status: 200 };
@@ -533,7 +554,7 @@ export async function deleteEvent(userId, eventId, networkId, scope, exception_d
// Delete the whole event/series — collect files from the template AND all overrides, // Delete the whole event/series — collect files from the template AND all overrides,
// but only those not shared with surviving events (e.g. a 'this and future' split // but only those not shared with surviving events (e.g. a 'this and future' split
// inherits the same file_ids; deleting the physical file would orphan that series) // inherits the same file_ids; deleting the physical file would orphan that series)
const files = await this.sql` const files = await context.sql`
SELECT DISTINCT f.* FROM public.files f SELECT DISTINCT f.* FROM public.files f
JOIN public.file_to_event fte ON fte.file_id = f.id JOIN public.file_to_event fte ON fte.file_id = f.id
JOIN events.events e ON e.id = fte.event_id JOIN events.events e ON e.id = fte.event_id
@@ -548,7 +569,7 @@ export async function deleteEvent(userId, eventId, networkId, scope, exception_d
`; `;
const recurrenceId = event.recurrence_id; const recurrenceId = event.recurrence_id;
await this.sql.begin(async tx => { await context.sql.begin(async tx => {
// Promote non-cancelled overrides (single-event edits) to standalone events before deleting the template // Promote non-cancelled overrides (single-event edits) to standalone events before deleting the template
await tx` await tx`
UPDATE events.events UPDATE events.events

View File

@@ -1,11 +1,11 @@
export async function getMoneyData(networkId) { export async function getMoneyData(networkId) {
const purchases = await this.sql` const purchases = await context.sql`
SELECT * FROM purchases SELECT * FROM purchases
WHERE network_id = ${networkId} WHERE network_id = ${networkId}
ORDER BY created DESC ORDER BY created DESC
`; `;
const subscriptions = await this.sql` const subscriptions = await context.sql`
SELECT mn.id, mn.created, mn.active, mn.network_plan_id, SELECT mn.id, mn.created, mn.active, mn.network_plan_id,
np.name AS plan_name, np.price AS plan_price, np.name AS plan_name, np.price AS plan_price,
m.first_name, m.last_name, m.email m.first_name, m.last_name, m.email

4
notes.txt Normal file
View File

@@ -0,0 +1,4 @@
reset permissions
sudo chown -R test:staff /Users/Shared/apps
chmod -R ug+w /Users/Shared/apps

View File

@@ -1,7 +1,7 @@
export async function saveMemberNote(email, text) { export async function saveMemberNote(email, text) {
console.log("saving note: ", email, text) console.log("saving note: ", email, text)
try { try {
await this.sql` await context.sql`
UPDATE members UPDATE members
SET notes = ${text} SET notes = ${text}
WHERE email = ${email} WHERE email = ${email}
@@ -14,7 +14,7 @@ export async function saveMemberNote(email, text) {
export async function getPeople(networkId) { export async function getPeople(networkId) {
try { try {
const people = await this.sql` const people = await context.sql`
SELECT SELECT
m.*, m.*,
mn.created AS joined_network, mn.created AS joined_network,

View File

@@ -1,5 +1,5 @@
export async function getTasks(networkId) { export async function getTasks(networkId) {
const tasks = await this.sql` const tasks = await context.sql`
SELECT * FROM tasks.tasks SELECT * FROM tasks.tasks
WHERE network_id = ${networkId} WHERE network_id = ${networkId}
AND is_active = true AND is_active = true
@@ -9,7 +9,7 @@ export async function getTasks(networkId) {
} }
export async function addTask(networkId, title) { export async function addTask(networkId, title) {
const [task] = await this.sql` const [task] = await context.sql`
INSERT INTO tasks.tasks (title, network_id) INSERT INTO tasks.tasks (title, network_id)
VALUES (${title}, ${networkId}) VALUES (${title}, ${networkId})
RETURNING * RETURNING *
@@ -18,7 +18,7 @@ export async function addTask(networkId, title) {
} }
export async function updateTaskDone(taskId, done) { export async function updateTaskDone(taskId, done) {
const [task] = await this.sql` const [task] = await context.sql`
UPDATE tasks.tasks UPDATE tasks.tasks
SET done = ${done} SET done = ${done}
WHERE id = ${taskId} WHERE id = ${taskId}
@@ -28,7 +28,7 @@ export async function updateTaskDone(taskId, done) {
} }
export async function editTaskTitle(taskId, title) { export async function editTaskTitle(taskId, title) {
const [task] = await this.sql` const [task] = await context.sql`
UPDATE tasks.tasks UPDATE tasks.tasks
SET title = ${title} SET title = ${title}
WHERE id = ${taskId} WHERE id = ${taskId}
@@ -38,7 +38,7 @@ export async function editTaskTitle(taskId, title) {
} }
export async function deleteTask(taskId) { export async function deleteTask(taskId) {
await this.sql` await context.sql`
UPDATE tasks.tasks UPDATE tasks.tasks
SET is_active = false SET is_active = false
WHERE id = ${taskId} WHERE id = ${taskId}