import { parse } from "date-fns"; import keyBy from "lodash/keyBy"; import pick from "lodash/pick"; import property from "lodash/property"; import { createAsyncAction, errorResult, successResult } from "pullstate"; import { fetch } from "api"; import { markdownConverter } from "markdown"; import { ProgramStore } from "stores"; import { loadPosts } from "./posts"; export const loadProgram = createAsyncAction( async () => { try { const resp = await fetch("/program"); const mappings = await resp.json(); return successResult(mappings); } catch (err) { return errorResult([], err.toString()); } }, { postActionHook: ({ result }) => { if (!result.error) { const entries = result.payload .map( /** * * @param {any} entry * @returns {CF2021.ProgramScheduleEntry} */ (entry) => { return { ...pick(entry, [ "id", "number", "title", "description", "proposer", "speakers", ]), fullTitle: entry.number !== "" ? `${entry.number}. ${entry.title}` : entry.title, htmlContent: markdownConverter.makeHtml(entry.description), discussionOpened: entry.discussion_opened, expectedStartAt: parse( entry.expected_start_at, "yyyy-MM-dd HH:mm:ss", new Date() ), expectedFinishAt: entry.expected_finish_at ? parse( entry.expected_finish_at, "yyyy-MM-dd HH:mm:ss", new Date() ) : undefined, }; } ) .sort((a, b) => a.expectedStartAt - b.expectedStartAt); const currentEntry = result.payload.find((entry) => entry.is_live); ProgramStore.update((state) => { state.items = keyBy(entries, property("id")); state.scheduleIds = entries.map((entry) => entry.id); if (currentEntry) { state.currentId = currentEntry.id; } }); } }, } ); /** * Rename program point. */ export const renameProgramPoint = createAsyncAction( async ({ programEntry, newTitle }) => { try { const body = JSON.stringify({ title: newTitle, }); await fetch(`/program/${programEntry.id}`, { method: "PUT", body, expectedStatus: 204, }); return successResult({ programEntry, newTitle }); } catch (err) { return errorResult([], err.toString()); } }, { postActionHook: ({ result }) => { if (!result.error) { ProgramStore.update((state) => { if (state.items[result.payload.programEntry.id]) { state.items[result.payload.programEntry.id].title = result.payload.newTitle; } }); } }, } ); /** * End program point. */ export const endProgramPoint = createAsyncAction( /** * * @param {CF2021.ProgramScheduleEntry} programEntry */ async (programEntry) => { try { const body = JSON.stringify({ is_live: false, }); await fetch(`/program/${programEntry.id}`, { method: "PUT", body, expectedStatus: 204, }); return successResult(programEntry); } catch (err) { return errorResult([], err.toString()); } }, { postActionHook: ({ result }) => { if (!result.error) { ProgramStore.update((state) => { state.currentId = null; }); } }, } ); /** * Activate program point. */ export const activateProgramPoint = createAsyncAction( /** * * @param {CF2021.ProgramScheduleEntry} programEntry */ async (programEntry) => { try { const body = JSON.stringify({ is_live: true, }); await fetch(`/program/${programEntry.id}`, { method: "PUT", body, expectedStatus: 204, }); return successResult(programEntry); } catch (err) { return errorResult([], err.toString()); } }, { postActionHook: async ({ result }) => { if (!result.error) { ProgramStore.update((state) => { state.currentId = result.payload.id; }); // Re-load posts - these are bound directly to the program schedule entry. loadPosts.run({}, { respectCache: false }); } }, } ); /** * Open discussion. */ export const openDiscussion = createAsyncAction( /** * * @param {CF2021.ProgramScheduleEntry} programEntry */ async (programEntry) => { try { const body = JSON.stringify({ discussion_opened: true, }); await fetch(`/program/${programEntry.id}`, { method: "PUT", body, expectedStatus: 204, }); return successResult(programEntry); } catch (err) { return errorResult([], err.toString()); } }, { postActionHook: ({ result }) => { if (!result.error) { ProgramStore.update((state) => { if (state.items[result.payload.id]) { state.items[result.payload.id].discussionOpened = true; } }); } }, } ); /** * Close discussion. */ export const closeDiscussion = createAsyncAction( async (programEntry) => { try { const body = JSON.stringify({ discussion_opened: false, }); await fetch(`/program/${programEntry.id}`, { method: "PUT", body, expectedStatus: 204, }); return successResult(programEntry); } catch (err) { return errorResult([], err.toString()); } }, { postActionHook: ({ result }) => { if (!result.error) { ProgramStore.update((state) => { if (state.items[result.payload.id]) { state.items[result.payload.id].discussionOpened = false; } }); } }, } );