From beec4c3968dc79aa04821b52bb83ad6bc502557f Mon Sep 17 00:00:00 2001 From: Kevin Cameron Date: Sun, 25 Mar 2018 11:57:16 -0700 Subject: [PATCH] Delete songs, db update timestamp --- src/components/home/index.js | 19 ++++++++++++++++--- src/components/home/list.css | 33 ++++++++++++++++++++++++++++++--- src/components/home/list.js | 26 +++++++++++++++++++------- src/state/db.js | 28 ++++++++++++++++++---------- src/state/song.js | 17 +++++++++-------- 5 files changed, 92 insertions(+), 31 deletions(-) diff --git a/src/components/home/index.js b/src/components/home/index.js index dabc687..38b4d5a 100644 --- a/src/components/home/index.js +++ b/src/components/home/index.js @@ -10,9 +10,19 @@ import list from "./list"; export default { oninit : (vnode) => { + vnode.state.timestamp = db.timestamp(); vnode.state.defaultSongs = db.get("songs?default=true"); vnode.state.customSongs = db.get("songs?default=undefined"); }, + onbeforeupdate : (vnode) => { + if(vnode.state.timestamp !== db.timestamp()) { + vnode.state.timestamp = db.timestamp(); + vnode.state.defaultSongs = db.get("songs?default=true"); + vnode.state.customSongs = db.get("songs?default=undefined"); + + return true; + } + }, view : (vnode) => [ m("div", { class : css.home }, @@ -29,7 +39,7 @@ export default { m("div", { class : css.dash }, m("textarea", { class : vnode.state.focused ? css.textareaFocused : css.textarea, - value : vnode.state.lyricsValue, + value : vnode.state.lyricString, placeholder : vnode.state.hidePlaceholder ? "" : "paste or drop lyrics", onfocus : () => { vnode.state.focused = true; @@ -39,7 +49,7 @@ export default { vnode.state.hidePlaceholder = false; }, oninput : m.withAttr("value", (v) => { - vnode.state.lyricsValue = v; + vnode.state.lyricString = v; vnode.state.loadable = v.length; }) }) @@ -50,7 +60,10 @@ export default { m("button", { class : css.loadBtn, onclick : () => { - let slug = state.action("IMPORT SONG LYRICS", vnode.state.lyricsValue); + let slug = state.action("IMPORT SONG LYRICS", { + lyricString : vnode.state.lyricString, + userSong : true + }); delete vnode.state.textarea; delete vnode.state.load; diff --git a/src/components/home/list.css b/src/components/home/list.css index fb355dd..17d489e 100644 --- a/src/components/home/list.css +++ b/src/components/home/list.css @@ -1,5 +1,5 @@ @value * as colors from "../../palette.css"; -@value fontSans, fontSerif from "../../index.css"; +@value fontSans, fontSerif, animDur from "../../index.css"; .list { max-width: 30em; @@ -16,9 +16,36 @@ font: bold 1.15em/1 fontSans; } - a { - display: block; + div { + button { + position: relative; + top: -0.15em; + margin-left: 1em; + padding: 0.2em; + /* width: 1.3em; + height: 1.3em; */ + + opacity: 0; + + font-size: 0.8em; + color: #fff; + background: transparent; + border: solid 2px #fff6; + border-radius: 50%; + + transition: opacity animDur, background-color animDur; + &:hover { + background: red; + } + } + + &:hover button { + opacity: 1; + } + } + + a { font-family: fontSerif; text-transform: uppercase; text-decoration: none; diff --git a/src/components/home/list.js b/src/components/home/list.js index 86038eb..439a4d9 100644 --- a/src/components/home/list.js +++ b/src/components/home/list.js @@ -1,5 +1,7 @@ import m from "mithril"; +import state from "../../state"; + import css from "./list.css"; export default { @@ -8,13 +10,23 @@ export default { m("h3", vnode.attrs.header), Object.keys(vnode.attrs.songs).map((slug) => - m("a", { - oncreate : m.route.link, - href : `/${vnode.attrs.songs[slug].slug}` - }, - vnode.attrs.songs[slug].title, - vnode.attrs.songs[slug].artist ? - m("span", " - ", vnode.attrs.songs[slug].artist ) : + m("div", + m("a", { + oncreate : m.route.link, + href : `/${vnode.attrs.songs[slug].slug}` + }, + vnode.attrs.songs[slug].title, + vnode.attrs.songs[slug].artist ? + m("span", " - ", vnode.attrs.songs[slug].artist ) : + null + ), + vnode.attrs.songs[slug].userSong ? + m("button", { + onclick : () => { + state.action("DELETE SONG BY SLUG", slug); + }, + "aria-label" : "delete" + }, "🗙") : null ) ) diff --git a/src/state/db.js b/src/state/db.js index 9100937..b1bd939 100644 --- a/src/state/db.js +++ b/src/state/db.js @@ -41,10 +41,10 @@ function Table(key) { const data = _getTable(); if(!path) { - return _setTable({}); + return; } - set(data, path, undefined); + delete data[path]; return _setTable(data); }; @@ -54,11 +54,6 @@ function Table(key) { }; } -// create Tables -const db = { - songs : new Table("songs") -}; - function parseQueryParams(queryParams) { if(typeof queryParams !== "string") { return queryParams; @@ -128,7 +123,17 @@ function parseValue(value) { return value; } +// create Tables +const db = { + timestamp : Date.now(), + tables : { + songs : new Table("songs") + } +}; + export default { + timestamp : () => db.timestamp, + get : (query) => { const parsed = parseQuery(query); @@ -136,7 +141,7 @@ export default { return; } - const data = db[parsed.key].get(parsed.path); + const data = db.tables[parsed.key].get(parsed.path); if(!parsed.queryParams) { return data; @@ -151,7 +156,9 @@ export default { return; } - return db[parsed.key].set(parsed.path, data); + db.timestamp = Date.now(); + + return db.tables[parsed.key].set(parsed.path, data); }, del : (query) => { const parsed = parseQuery(query); @@ -160,7 +167,8 @@ export default { return; } - return db[parsed.key].del(parsed.path); + db.timestamp = Date.now(); + return db.tables[parsed.key].del(parsed.path); }, clear : () => { localStorage.clear(); diff --git a/src/state/song.js b/src/state/song.js index b7dec6a..8b27e5b 100644 --- a/src/state/song.js +++ b/src/state/song.js @@ -51,24 +51,25 @@ export default (State) => ({ }, // import song - "IMPORT SONG LYRICS" : (lyricString) => { + "IMPORT SONG LYRICS" : (songObj) => { const untitledSongs = db.get("songs?untitled"); const title = `untitled ${Object.keys(untitledSongs).length + 1}`; const slug = slugify(title); - let songObj = { - slug, + db.set(`songs.${slug}`, Object.assign(songObj, { title, - lyricString, - lyrics : parseLyricString(lyricString), + slug, + lyrics : parseLyricString(songObj.lyricString), untitled : true - }; - - db.set(`songs.${slug}`, songObj); + })); return slug; }, + "DELETE SONG BY SLUG" : (slug) => { + db.del(`songs.${slug}`); + }, + "SET TITLE" : (title) => { const oldSlug = State.song.slug;