separate front end into modules for easier refactoring later

This commit is contained in:
Ondřej Synáček 2020-07-17 20:18:55 +02:00
parent c336f6998b
commit 6b7c0f8454
4 changed files with 138 additions and 112 deletions

87
lib/static/app/storage.js Normal file
View File

@ -0,0 +1,87 @@
import { useStorage } from './utils'
const migrateRecord = (record) => {
// NOTE: v3 records
const id = record.id || record.order
const startTime = record.startTime || null
return {
...record,
id,
startTime,
}
}
const getStorage = () => {
if (!useStorage()) {
return null
}
const storage = localStorage.getItem('fb-to-ical-events')
if (!storage) {
localStorage.setItem('fb-to-ical-events', JSON.stringify([]))
return "[]"
}
return storage
}
const getStorageContents = (storage) => {
return JSON.parse(storage)
}
const updateStorage = (storageContents) => {
const encodedStorage = JSON.stringify(storageContents)
localStorage.setItem('fb-to-ical-events', encodedStorage)
}
const saveRecord = ({ id, link, createdAt, startTime, title }) => {
if (!useStorage()) {
return
}
const storage = getStorage()
const storageContents = getStorageContents(storage)
const record = {
id,
link,
createdAt: createdAt.toString(),
startTime: startTime.toString(),
title,
}
updateStorage([ ...storageContents, record ])
}
const deleteRecord = (id) => {
if (!useStorage()) {
return
}
const storage = getStorage()
const storageContents = getStorageContents(storage)
const index = storageContents.findIndex((record) => {
return record.id === id
})
if (!Number.isFinite(index)) {
return
}
const nextStorage = [ ...storageContents ]
nextStorage.splice(index, 1)
updateStorage(nextStorage)
}
export {
migrateRecord,
getStorage,
getStorageContents,
updateStorage,
saveRecord,
deleteRecord,
}

35
lib/static/app/utils.js Normal file
View File

@ -0,0 +1,35 @@
const noJS = () => {
return Boolean(document.querySelector("#nojs").checked)
}
const useStorage = () => Boolean(window.localStorage)
// NOTE: Generate random IDs: https://stackoverflow.com/a/2117523/3056783
const uuidv4 = () => {
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
)
}
const parseStartTimeFromiCalString = (text = '') => {
const [ dateStr, timeStr ] = text.split('T')
const rawDate = dateStr || ''
const rawTime = timeStr || ''
const year = Number(rawDate.slice(0, 4))
const month = Number(Math.max(rawDate.slice(4, 6) - 1), 0)
const date = Number(rawDate.slice(6, 8))
const hour = Number(rawTime.slice(0, 2))
const minutes = Number(rawTime.slice(2, 4))
const seconds = Number(rawTime.slice(4, 6))
const parsedDate = new Date(year, month, date, hour, minutes, seconds)
return parsedDate.toString()
}
export {
noJS,
uuidv4,
parseStartTimeFromiCalString,
useStorage,
}

View File

@ -1,115 +1,19 @@
import { noJS, uuidv4, parseStartTimeFromiCalString, useStorage } from './app/utils'
import {
migrateRecord,
getStorage,
getStorageContents,
updateStorage,
saveRecord,
deleteRecord,
} from './app/storage'
(() => {
const noJS = () => {
return Boolean(document.querySelector("#nojs").checked)
}
const useStorage = Boolean(window.localStorage)
if (!window.fetch || !window.Promise || !window.URLSearchParams || !window.crypto) {
console.info('JS features not available.')
console.warn('JS features not available.')
return
}
// NOTE: Generate random IDs: https://stackoverflow.com/a/2117523/3056783
const uuidv4 = () => {
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
)
}
const parseStartTimeFromiCalString = (text = '') => {
const [ dateStr, timeStr ] = text.split('T')
const rawDate = dateStr || ''
const rawTime = timeStr || ''
const year = Number(rawDate.slice(0, 4))
const month = Number(Math.max(rawDate.slice(4, 6) - 1), 0)
const date = Number(rawDate.slice(6, 8))
const hour = Number(rawTime.slice(0, 2))
const minutes = Number(rawTime.slice(2, 4))
const seconds = Number(rawTime.slice(4, 6))
const parsedDate = new Date(year, month, date, hour, minutes, seconds)
return parsedDate.toString()
}
const migrateRecord = (record) => {
// NOTE: v3 records
const id = record.id || record.order
const startTime = record.startTime || null
return {
...record,
id,
startTime,
}
}
const getStorage = () => {
if (!useStorage) {
return null
}
const storage = localStorage.getItem('fb-to-ical-events')
if (!storage) {
localStorage.setItem('fb-to-ical-events', JSON.stringify([]))
return "[]"
}
return storage
}
const getStorageContents = (storage) => {
return JSON.parse(storage)
}
const updateStorage = (storageContents) => {
const encodedStorage = JSON.stringify(storageContents)
localStorage.setItem('fb-to-ical-events', encodedStorage)
}
const saveRecord = ({ id, link, createdAt, startTime, title }) => {
if (!useStorage) {
return
}
const storage = getStorage()
const storageContents = getStorageContents(storage)
const record = {
id,
link,
createdAt: createdAt.toString(),
startTime: startTime.toString(),
title,
}
updateStorage([ ...storageContents, record ])
}
const deleteRecord = (id) => {
if (!useStorage) {
return
}
const storage = getStorage()
const storageContents = getStorageContents(storage)
const index = storageContents.findIndex((record) => {
return record.id === id
})
if (!Number.isFinite(index)) {
return
}
const nextStorage = [ ...storageContents ]
nextStorage.splice(index, 1)
updateStorage(nextStorage)
}
const showTable = () => {
list.classList.remove('hidden')
}
@ -117,7 +21,7 @@
const deleteTableRow = (id, row) => {
deleteRecord(id)
if (!useStorage) {
if (!useStorage()) {
return
}
@ -182,7 +86,7 @@
}
const hydrateList = () => {
if (!useStorage) {
if (!useStorage()) {
return
}
@ -295,7 +199,7 @@
const noJScheckbox = document.querySelector('#nojs')
const loadNoJS = () => {
if (!useStorage) {
if (!useStorage()) {
return
}
const value = localStorage.getItem('fb-to-ical-nojs')
@ -343,7 +247,7 @@
}
noJScheckbox.addEventListener('click', (event) => {
if (!useStorage) {
if (!useStorage()) {
return
}

View File

@ -8,7 +8,7 @@ const destination = path.join(__dirname, 'dist')
const isDevelopment = Boolean(process.argv[2] && process.argv[2].includes('mode=development'))
module.exports = {
entry: path.join(__dirname, 'lib', 'static', 'scripts.js'),
entry: path.join(__dirname, 'lib', 'static', 'index.js'),
watch: isDevelopment,
output: {
filename: '[name].[hash].js',