diff --git a/sql/00006.sql b/sql/00006.sql index 6b0ea9b..453b260 100644 --- a/sql/00006.sql +++ b/sql/00006.sql @@ -1,16 +1 @@ -CREATE TABLE public.node_history ( - id serial4 NOT NULL, - user_id int4 NOT NULL, - uuid bpchar(36) NOT NULL, - parents varchar[] NULL, - created timestamptz NOT NULL, - updated timestamptz NOT NULL, - name varchar(256) NOT NULL, - "content" text NOT NULL, - content_encrypted text NOT NULL, - markdown bool DEFAULT false NOT NULL, - client bpchar(36) DEFAULT ''::bpchar NOT NULL, - CONSTRAINT node_history_pk PRIMARY KEY (id), - CONSTRAINT node_history_user_fk FOREIGN KEY (user_id) REFERENCES public."user"(id) ON DELETE RESTRICT ON UPDATE RESTRICT -); -CREATE INDEX node_history_uuid_idx ON public.node USING btree (uuid); +DROP INDEX public.node_uuid_idx; diff --git a/static/css/login.css b/static/css/login.css index 88a9140..7e19cb8 100644 --- a/static/css/login.css +++ b/static/css/login.css @@ -1,37 +1,44 @@ +@import "theme.css"; + #app { - display: grid; - justify-items: center; - margin-top: 128px; + display: grid; + justify-items: center; + margin-top: 128px; } + #logo { - margin-bottom: 48px; + margin-bottom: 48px; } + #box { - display: grid; - grid-gap: 16px 0; - justify-items: center; - width: 300px; - padding: 48px 0px; - background-color: #fff; - box-shadow: 0px 20px 52px -33px rgba(0, 0, 0, 0.75); - border-left: 8px solid #666; -} -#box input { - padding: 4px 8px; - font-size: 1em; - width: calc(100% - 64px); - border: 1px solid #aaa; - border-radius: 4px; -} -#box button { - padding: 6px 16px; - font-size: 1em; - border-radius: 4px; - border: none; - background-color: #fe5f55; - color: #fff; -} -#box #error { - color: #c33; - margin-top: 16px; + display: grid; + grid-gap: 16px 0; + justify-items: center; + width: 300px; + padding: 48px 0px; + background-color: #fff; + box-shadow: 0px 20px 52px -33px rgba(0,0,0,0.75); + border-left: 8px solid var(--color3); + + input { + padding: 4px 8px; + font-size: 1em; + width: calc(100% - 64px); + border: 1px solid #aaa; + border-radius: 4px; + } + + button { + padding: 6px 16px; + font-size: 1em; + border-radius: 4px; + border: none; + background-color: var(--color1); + color: #fff; + } + + #error { + color: #c33; + margin-top: 16px; + } } diff --git a/static/css/main.css b/static/css/main.css index 75f1925..a8924d9 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -1,23 +1,29 @@ +@import "theme.css"; + html { - box-sizing: border-box; - background: #efede8; - font-family: "Liberation Mono", monospace; - font-size: 14px; - margin: 0px; - padding: 0px; + box-sizing: border-box; + background: var(--color2); + font-family: "Liberation Mono", monospace; + font-size: 14px; + margin: 0px; + padding: 0px; } + body { - margin: 0px; - padding: 0px; + margin: 0px; + padding: 0px; } + *, *:before, *:after { - box-sizing: inherit; + box-sizing: inherit; } + *:focus { - outline: none; + outline: none; } + [onClick] { - cursor: pointer; + cursor: pointer; } diff --git a/static/css/notes2.css b/static/css/notes2.css index 0a23116..1104c8b 100644 --- a/static/css/notes2.css +++ b/static/css/notes2.css @@ -1,276 +1,369 @@ +@import "theme.css"; + html { - background-color: #fff; + background-color: #fff; } + #notes2 { - min-height: 100vh; - display: grid; - grid-template-areas: "tree crumbs" "tree sync" "tree name" "tree content" "tree blank"; - grid-template-columns: min-content 1fr; - grid-template-rows: 48px 56px 48px min-content 1fr; -} -@media only screen and (max-width: 600px) { - #notes2 { - grid-template-areas: "crumbs" "sync" "name" "content" "blank"; - grid-template-columns: 1fr; - } - #notes2 #tree { - display: none; - } + min-height: 100vh; + + display: grid; + grid-template-areas: + "tree crumbs" + "tree sync" + "tree name" + "tree content" + /* + "tree checklist" + "tree schedule" + "tree files" + */ + "tree blank" + ; + grid-template-columns: min-content 1fr; + grid-template-rows: + 48px + 56px + 48px + min-content + 1fr; + + + @media only screen and (max-width: 600px) { + grid-template-areas: + "crumbs" + "sync" + "name" + "content" + /* + "checklist" + "schedule" + "files" + */ + "blank" + ; + grid-template-columns: 1fr; + + #tree { + display: none; + } + } } + #tree { - grid-area: tree; - display: grid; - padding: 16px 0px 16px 16px; - color: #ddd; - z-index: 100; - border-left: 2px solid #333; -} -#tree:focus { - border-left: 2px solid #FE5F55; -} -#tree #logo { - display: grid; - position: relative; - justify-items: center; - margin-top: 8px; - margin-bottom: 8px; - margin-left: 24px; - margin-right: 24px; - cursor: pointer; -} -#tree #logo img { - width: 128px; - left: -20px; -} -#tree .icons { - display: flex; - justify-content: center; - margin-bottom: 32px; - gap: 8px; -} -#tree .node { - display: grid; - grid-template-columns: 24px min-content; - grid-template-rows: min-content 1fr; - margin-top: 12px; -} -#tree .node .expand-toggle { - user-select: none; -} -#tree .node .expand-toggle img { - width: 16px; - height: 16px; -} -#tree .node .name { - white-space: nowrap; - cursor: pointer; - user-select: none; -} -#tree .node .name:hover { - color: #fe5f55; -} -#tree .node .name.selected { - color: #fe5f55; - font-weight: bold; -} -#tree .node .children { - padding-left: 24px; - margin-left: 8px; - border-left: 1px solid #444; - grid-column: 1 / -1; -} -#tree .node .children.collapsed { - display: none; + grid-area: tree; + display: grid; + padding: 16px 0px 16px 16px; + color: #ddd; + z-index: 100; /* Over crumbs shadow */ + border-left: 2px solid #333; + + &:focus { + border-left: 2px solid #FE5F55; + } + + #logo { + display: grid; + position: relative; + justify-items: center; + margin-top: 8px; + margin-bottom: 8px; + margin-left: 24px; + margin-right: 24px; + cursor: pointer; + + img { + width: 128px; + left: -20px; + + } + } + + .icons { + display: flex; + justify-content: center; + margin-bottom: 32px; + gap: 8px; + } + + .node { + display: grid; + grid-template-columns: 24px min-content; + grid-template-rows: + min-content + 1fr; + margin-top: 12px; + + + .expand-toggle { + user-select: none; + img { + width: 16px; + height: 16px; + } + } + + .name { + white-space: nowrap; + cursor: pointer; + user-select: none; + + &:hover { + color: var(--color1); + } + &.selected { + color: var(--color1); + font-weight: bold; + } + + } + + .children { + padding-left: 24px; + margin-left: 8px; + border-left: 1px solid #444; + grid-column: 1 / -1; + + &.collapsed { + display: none; + } + } + } } + #tree-nodes { - padding: 16px 32px; - background-color: #333; - border-radius: 8px; - box-shadow: 5px 5px 10px -5px rgba(0, 0, 0, 0.75); + padding: 16px 32px; + background-color: #333; + border-radius: 8px; + box-shadow: 5px 5px 10px -5px rgba(0,0,0,0.75); } + #crumbs { - grid-area: crumbs; - display: grid; - align-items: start; - justify-items: center; - margin: 16px 16px; -} -#crumbs .crumbs { - display: flex; - flex-wrap: wrap; - padding: 8px 16px; - background: #e4e4e4; - color: #333; - border-bottom-left-radius: 5px; - border-bottom-right-radius: 5px; -} -#crumbs .crumbs.node-modified { - background-color: #fe5f55; - color: #efede8; -} -#crumbs .crumbs.node-modified .crumb:after { - color: #efede8; -} -#crumbs .crumbs .crumb { - margin-right: 8px; - cursor: pointer; - user-select: none; - -webkit-tap-highlight-color: transparent; -} -#crumbs .crumbs .crumb a { - text-decoration: none; - color: inherit; -} -#crumbs .crumbs .crumb:after { - content: "•"; - margin-left: 8px; - color: #fe5f55; -} -#crumbs .crumbs .crumb:last-child { - margin-right: 0; -} -#crumbs .crumbs .crumb:last-child:after { - content: ''; - margin-left: 0px; + grid-area: crumbs; + display: grid; + align-items: start; + justify-items: center; + margin: 16px 16px; + + .crumbs { + background: #e4e4e4; + display: flex; + flex-wrap: wrap; + padding: 8px 16px; + background: #e4e4e4; + color: #333; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + + &.node-modified { + background-color: var(--color1); + color: var(--color2); + .crumb:after { + color: var(--color2); + } + } + + .crumb { + margin-right: 8px; + cursor: pointer; + user-select: none; + -webkit-tap-highlight-color: transparent; + + a { + text-decoration: none; + color: inherit; + } + } + + .crumb:after { + content: "•"; + margin-left: 8px; + color: var(--color1) + } + + .crumb:last-child { + margin-right: 0; + } + .crumb:last-child:after { + content: ''; + margin-left: 0px; + } + + } + } + #sync-progress { - grid-area: sync; - display: grid; - justify-items: center; - width: 100%; - height: 56px; - position: relative; -} -#sync-progress progress { - width: 100%; - padding: 0 7px; - max-width: 900px; - height: 16px; - border-radius: 4px; -} -#sync-progress progress[value]::-webkit-progress-bar { - background-color: #eee; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25) inset; - border-radius: 4px; -} -#sync-progress progress[value]::-moz-progress-bar { - background-color: #eee; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25) inset; - border-radius: 4px; -} -#sync-progress progress[value]::-webkit-progress-value { - background: #ba5f59; - background: linear-gradient(180deg, #ba5f59 0%, #fe5f55 50%, #ba5f59 100%); - border-radius: 4px; -} -#sync-progress progress[value]::-moz-progress-value { - background: #ba5f59; - background: linear-gradient(180deg, #ba5f59 0%, #fe5f55 50%, #ba5f59 100%); - border-radius: 4px; -} -#sync-progress .count { - width: min-content; - white-space: nowrap; - margin-top: 0px; - color: #888; - position: absolute; - top: 22px; -} -#sync-progress.hidden { - visibility: hidden; - opacity: 0; - transition: visibility 0s 500ms, opacity 500ms linear; + grid-area: sync; + display: grid; + justify-items: center; + + width: 100%; + height: 56px; + position: relative; + + progress { + width: 100%; + padding: 0 7px; + max-width: 900px; + height: 16px; + border-radius: 4px; + } + + progress[value]::-webkit-progress-bar { + background-color: #eee; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25) inset; + border-radius: 4px; + } + + progress[value]::-moz-progress-bar { + background-color: #eee; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25) inset; + border-radius: 4px; + } + + progress[value]::-webkit-progress-value { + background: rgb(186,95,89); + background: linear-gradient(180deg, rgba(186,95,89,1) 0%, rgba(254,95,85,1) 50%, rgba(186,95,89,1) 100%); + border-radius: 4px; + } + + /* TODO: style the progress value for Firefox */ + progress[value]::-moz-progress-value { + background: rgb(186,95,89); + background: linear-gradient(180deg, rgba(186,95,89,1) 0%, rgba(254,95,85,1) 50%, rgba(186,95,89,1) 100%); + border-radius: 4px; + } + + .count { + width: min-content; + white-space: nowrap; + margin-top: 0px; + color: #888; + position: absolute; + top: 22px; + } + + &.hidden { + visibility: hidden; + opacity: 0; + transition: visibility 0s 500ms, opacity 500ms linear; + } + } + #name { - color: #333; - font-weight: bold; - text-align: center; - font-size: 1.15em; - margin-top: 0px; - margin-bottom: 16px; + color: #333; + font-weight: bold; + text-align: center; + font-size: 1.15em; + margin-top: 0px; + margin-bottom: 16px; } + /* ============================================================= * * Textarea replicates the height of an element expanding height * * ============================================================= */ .grow-wrap { - /* easy way to plop the elements on top of each other and have them both sized based on the tallest one's height */ - display: grid; - grid-area: content; - font-size: 1em; + /* easy way to plop the elements on top of each other and have them both sized based on the tallest one's height */ + display: grid; + grid-area: content; + font-size: 1.0em; } .grow-wrap::after { - /* Note the weird space! Needed to preventy jumpy behavior */ - content: attr(data-replicated-value) " "; - /* This is how textarea text behaves */ - width: calc(100% - 32px); - max-width: 900px; - white-space: pre-wrap; - word-wrap: break-word; - background: rgba(0, 255, 255, 0.5); - justify-self: center; - /* Hidden from view, clicks, and screen readers */ - visibility: hidden; + /* Note the weird space! Needed to preventy jumpy behavior */ + content: attr(data-replicated-value) " "; + + /* This is how textarea text behaves */ + width: calc(100% - 32px); + max-width: 900px; + white-space: pre-wrap; + word-wrap: break-word; + background: rgba(0, 255, 255, 0.5); + justify-self: center; + + /* Hidden from view, clicks, and screen readers */ + visibility: hidden; } .grow-wrap > textarea { - /* You could leave this, but after a user resizes, then it ruins the auto sizing */ - resize: none; - /* Firefox shows scrollbar on growth, you can hide like this. */ - overflow: hidden; + /* You could leave this, but after a user resizes, then it ruins the auto sizing */ + resize: none; + + /* Firefox shows scrollbar on growth, you can hide like this. */ + overflow: hidden; } .grow-wrap > textarea, .grow-wrap::after { - /* Identical styling required!! */ - padding: 0.5rem; - font: inherit; - /* Place on top of each other */ - grid-area: 1 / 1 / 2 / 2; + /* Identical styling required!! */ + padding: 0.5rem; + font: inherit; + + /* Place on top of each other */ + grid-area: 1 / 1 / 2 / 2; } /* ============================================================= */ + #node-content { - justify-self: center; - word-wrap: break-word; - font-family: monospace; - color: #333; - width: calc(100% - 32px); - max-width: 900px; - resize: none; - border: none; - outline: none; -} -#node-content:invalid { - background: #f5f5f5; - padding-top: 16px; + justify-self: center; + word-wrap: break-word; + font-family: monospace; + color: #333; + width: calc(100% - 32px); + max-width: 900px; + resize: none; + border: none; + outline: none; + + &:invalid { + background: #f5f5f5; + padding-top: 16px; + } } + #blank { - grid-area: blank; - height: 32px; + grid-area: blank; + height: 32px; } -dialog.op::backdrop { - background: rgba(0, 0, 0, 0.5); + +dialog.op { + &::backdrop { + background: rgba(0, 0, 0, 0.5); + } + + .header { + font-weight: bold; + margin-top: 16px; + + &:first-child { + margin-top: 0px; + } + } + } -dialog.op .header { - font-weight: bold; - margin-top: 16px; -} -dialog.op .header:first-child { - margin-top: 0px; -} -#op-search .results { - display: grid; - grid-template-columns: min-content min-content; - grid-gap: 6px 16px; -} -#op-search .results div { - white-space: nowrap; -} -#op-search .results .ancestors { - display: flex; -} -#op-search .results .ancestors .ancestor::after { - content: ">"; - margin: 0px 8px; - color: #a00; -} -#op-search .results .ancestors .ancestor:last-child::after { - content: ""; + +#op-search { + .results { + display: grid; + grid-template-columns: min-content min-content; + grid-gap: 6px 16px; + + div { + white-space: nowrap; + } + + + .ancestors { + display: flex; + + .ancestor::after { + content: ">"; + margin: 0px 8px; + color: #a00; + } + + .ancestor:last-child::after { + content: ""; + } + } + } } diff --git a/static/css/theme.css b/static/css/theme.css index e69de29..b9c47ed 100644 --- a/static/css/theme.css +++ b/static/css/theme.css @@ -0,0 +1,5 @@ +:root { + --color1: #fe5f55; + --color2: #efede8; + --color3: #666; +} diff --git a/static/less/theme.less b/static/less/theme.less index 255a49c..b9c47ed 100644 --- a/static/less/theme.less +++ b/static/less/theme.less @@ -1,3 +1,5 @@ -@color1: #fe5f55; -@color2: #efede8; -@color3: #666; +:root { + --color1: #fe5f55; + --color2: #efede8; + --color3: #666; +}