-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sundry fixes #747
Sundry fixes #747
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,106 @@ | ||
import {LoaderFunctionArgs} from '@remix-run/cloudflare' | ||
import {reloadInBackgroundIfNeeded} from '~/server-utils/kv-cache' | ||
import {loadAllQuestions} from '~/server-utils/stampy' | ||
import {LoaderFunctionArgs, json} from '@remix-run/cloudflare' | ||
import {downloadZip} from 'client-zip' | ||
import '~/components/Chatbot/widgit.css' | ||
import {Question, QuestionStatus, loadAllQuestions} from '~/server-utils/stampy' | ||
import {isAuthorized} from '~/routesMapper' | ||
|
||
export const SINGLE_FILE_HTML = 'singleFileHtml' | ||
export const SINGLE_FILE_MARKDOWN = 'singleFileMarkdown' | ||
export const MULTI_FILE_HTML = 'multipleFilesMarkdown' | ||
export const MULTI_FILE_MARKDOWN = 'multipleFileHtml' | ||
export const SINGLE_FILE_JSON = 'singleFileJson' | ||
|
||
export const downloadOptions = { | ||
[SINGLE_FILE_HTML]: 'Single HTML file', | ||
[MULTI_FILE_HTML]: 'Multiple HTML files', | ||
[SINGLE_FILE_MARKDOWN]: 'Single markdown file', | ||
[MULTI_FILE_MARKDOWN]: 'Multiple markdown files', | ||
[SINGLE_FILE_JSON]: 'As JSON', | ||
} | ||
|
||
export const makeZipFile = async (questions: Question[], extention: string) => | ||
downloadZip( | ||
questions.map((q) => ({ | ||
name: `${q.title}.${extention}`, | ||
lastModified: q.updatedAt, | ||
input: (extention === 'md' ? q.markdown : q.text) || '', | ||
})) | ||
) | ||
|
||
export const toHtmlChunk = ({title, text}: Question) => | ||
[ | ||
' <div>', | ||
` <h2>${title}</h2>`, | ||
` <div>${text}</div>`, | ||
' </div>', | ||
].join('\n') | ||
|
||
export const toMarkdownChunk = ({title, markdown}: Question) => `# ${title}\n\n${markdown}` | ||
|
||
export const htmlFile = (contents: string) => | ||
['<!DOCTYPE html>', '<html>', ' <body>', contents, ' </body>', '/html>'].join('\n') | ||
|
||
const getData = async (questions: Question[], selectedOption: string) => { | ||
switch (selectedOption) { | ||
case SINGLE_FILE_HTML: | ||
return new Response(htmlFile(questions.map(toHtmlChunk).join('\n\n\n')), { | ||
headers: {'Content-Type': 'text/html'}, | ||
}) | ||
case MULTI_FILE_HTML: | ||
return makeZipFile(questions, 'html') | ||
case SINGLE_FILE_MARKDOWN: | ||
return new Response(questions.map(toMarkdownChunk).join('\n\n\n'), { | ||
headers: {'Content-Type': 'text/markdown'}, | ||
}) | ||
case MULTI_FILE_MARKDOWN: | ||
return makeZipFile(questions, 'md') | ||
case SINGLE_FILE_JSON: | ||
return json(questions) | ||
default: | ||
return json( | ||
{ | ||
error: | ||
'Invalid dataType provided. Must be one of ' + Object.keys(downloadOptions).join(', '), | ||
}, | ||
400 | ||
) | ||
} | ||
} | ||
|
||
export const headers = () => ({ | ||
'WWW-Authenticate': 'Basic', | ||
}) | ||
|
||
type QuestionsFilter = 'all' | 'live' | 'inProgress' | ||
const filteredQuestions = (questions: Question[], status: QuestionsFilter) => { | ||
switch (status) { | ||
case 'all': | ||
return questions | ||
case 'live': | ||
return questions?.filter((q) => q.status === QuestionStatus.LIVE_ON_SITE) | ||
case 'inProgress': | ||
return questions?.filter((q) => q.status !== QuestionStatus.LIVE_ON_SITE) | ||
default: | ||
throw 'Invalid questions filter provided. Must be one of "all", "live" or "inProgress"' | ||
} | ||
} | ||
|
||
export const loader = async ({request}: LoaderFunctionArgs) => { | ||
try { | ||
return await loadAllQuestions(request) | ||
if (!isAuthorized(request)) { | ||
return json({authorized: false, data: [] as Question[]}, {status: 401}) | ||
} | ||
|
||
const url = new URL(request.url) | ||
const params = new URLSearchParams(url.search) | ||
const dataType = params.get('dataType') || SINGLE_FILE_JSON | ||
const {data: allQuestions} = await loadAllQuestions(request) | ||
return getData( | ||
filteredQuestions(allQuestions, (params.get('questions') || 'all') as QuestionsFilter), | ||
dataType | ||
) | ||
} catch (e) { | ||
console.error(e) | ||
throw new Response('Could not fetch all articles', {status: 500}) | ||
throw new Response(`Could not fetch all articles: ${e}`, {status: 500}) | ||
} | ||
} | ||
type Data = ReturnType<typeof loader> | ||
|
||
export const fetchAllQuestions = async () => { | ||
const url = `/questions/allQuestions` | ||
const response = await fetch(url) | ||
const {data, timestamp}: Awaited<Data> = await response.json() | ||
const backgroundPromiseIfReloaded: Data | Promise<void> = reloadInBackgroundIfNeeded( | ||
url, | ||
timestamp | ||
) | ||
return {data, backgroundPromiseIfReloaded} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,4 +25,4 @@ MATOMO_DOMAIN = "{MATOMO_DOMAIN}" | |
DISCORD_LOGGING_CHANNEL_ID = "{DISCORD_LOGGING_CHANNEL_ID}" | ||
DISCORD_LOGGING_TOKEN = "{DISCORD_LOGGING_TOKEN}" | ||
EDITOR_USERNAME = "{EDITOR_USERNAME}" | ||
EDITOR_PASSWORD = "{EDITOR_PASSWORD}" | ||
EDITOR_PASSWORD = "{EDITOR_PASSWORD}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. trailing whitespace There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, why removing it? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from phone, but something like:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dunno if that's better... :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
disabling the eslint rule is unsafe for future changes which can more easily introduce bugs.. mutable refs might not look good, but you explicitly say "this is not a dependency which triggers a synchronization, I just want to use whatever value is has currently" without implying anything about any other variable that may or may not be a dependency