lots of changes

Added a creation_time field to thinks - using the modified time on the
  filesystem wasn't reliable.

Styled the login page.

The index shows the most recent thinks at the top.

Allow authentication by an Authorization header, with a token specified
in settings.py.

Lots of improvements to the editor, including showing the log, and a
form to install Elm packages when editing .elm files.

The Makefile for a project is automatically run each time a file is saved.
This commit is contained in:
Christian Lawson-Perfect 2025-02-07 07:02:35 +00:00
parent 3d5c0c6c73
commit 500eb38774
13 changed files with 1474 additions and 396 deletions

View file

@ -1,7 +1,19 @@
import './code-editor.mjs';
export default async function init_app() {
const flags = JSON.parse(document.getElementById('think-editor-data').textContent);
flags.csrf_token = document.getElementById('csrftoken')?.textContent || '';
const app = Elm.App.init({node: document.body, flags});
}
import './code-editor.mjs';
export default async function init_app() {
const flags = JSON.parse(document.getElementById('think-editor-data').textContent);
flags.csrf_token = document.getElementById('csrftoken')?.textContent || '';
const app = Elm.App.init({node: document.body, flags});
app.ports.reload_preview.subscribe(() => {
console.log('reload preview');
const iframe = document.getElementById('preview-frame');
if(iframe) {
const src = iframe.src;
iframe.src = "";
setTimeout(() => {
iframe.src = src;
},10);
}
})
}

View file

@ -1,201 +1,237 @@
:root {
--spacing: 1em;
--half-spacing: calc(0.5 * var(--spacing));
--double-spacing: calc(2 * var(--spacing));
--editor-size: 50%;
}
* {
box-sizing: border-box;
}
body {
font-family: sans-serif;
display: grid;
grid-template-rows: auto 1fr;
min-height: 100vh;
margin: 0;
padding: var(--half-spacing);
& > header {
padding: var(--spacing);
& h1 {
margin: 0;
}
}
}
header {
& #think-controls {
display: flex;
gap: var(--spacing);
margin: 0;
}
}
#editor-size-input + output {
width: 5em;
}
.file-path {
font-family: monospace;
}
.think-editor {
display: flex;
gap: var(--spacing);
height: 100%;
& > #main-nav > nav {
display: flex;
flex-direction: column;
gap: var(--spacing);
& #file-tree {
margin: 0;
overflow: auto;
flex-grow: 1;
& > li {
margin-top: var(--half-spacing);
& > a {
text-decoration: none;
}
}
& .dir {
font-weight: bold;
}
& .dir + .file {
margin-top: var(--spacing);
}
}
& form {
display: grid;
grid-template-columns: 1fr 6em;
align-content: start;
align-items: start;
}
& #make-log {
& > pre {
max-width: 20em;
overflow: auto;
}
}
}
& #log[open] {
width: 80ch;
overflow: auto;
}
& #editor {
overflow: hidden;
flex-grow: 1;
flex-basis: var(--editor-size);
max-height: 85vh;
& #editor-controls {
display: flex;
gap: var(--spacing);
justify-content: space-between;
& > details {
text-align: right;
& > summary {
user-select: none;
}
& button {
margin: var(--half-spacing) 0;
}
}
}
& #code-editor {
display: block;
max-width: 50vw;
padding-bottom: 10em;
}
}
& #preview {
display: flex;
flex-direction: column;
&[open] {
flex-grow: 1;
flex-shrink: 1;
flex-basis: calc(100% - var(--editor-size));
}
& > summary {
text-align: right;
}
& > iframe {
width: 100%;
height: 100%;
border: none;
}
&[closed] > iframe {
display: none;
}
}
overflow: hidden;
}
#file-form {
overflow: auto;
max-height: 100%;
max-width: 100%;
}
@media (max-width: 100ch) {
html {
font-size: min(3vw, 16px);
}
.think-editor {
flex-direction: column;
overflow: visible;
& > * ~ * {
border-top: medium solid #888;
margin-top: var(--spacing);
padding-top: var(--spacing);
}
& nav {
flex-direction: row;
flex-wrap: wrap;
& form {
flex-grow: 1;
}
& #file-tree {
max-height: 7em;
}
}
& #editor {
overflow: auto;
& #code-editor {
max-width: none;
}
}
& #preview {
height: 100vh;
}
}
:root {
--spacing: 1em;
--half-spacing: calc(0.5 * var(--spacing));
--double-spacing: calc(2 * var(--spacing));
--editor-size: 50%;
}
* {
box-sizing: border-box;
}
body {
color-scheme: light dark;
font-family: sans-serif;
display: grid;
grid-template-rows: auto 1fr;
min-height: 100vh;
margin: 0;
padding: var(--half-spacing);
& > header {
padding: var(--spacing);
& h1 {
margin: 0;
}
}
}
@media (prefers-color-scheme: dark) {
body {
background: black;
color: white;
}
}
header {
& #think-controls {
display: flex;
gap: var(--spacing);
margin: 0;
}
}
#editor-size-input + output {
width: 5em;
}
.file-path {
font-family: monospace;
}
.think-editor {
display: grid;
gap: var(--spacing);
height: 100%;
overflow: hidden;
--col-1-width: auto;
grid-template:
"nav editor preview" min-content
"log editor preview" 1fr
/ var(--col-1-width) var(--editor-size) var(--preview-size)
;
&:has(#main-nav[open], #log[open]) {
--col-1-width: 20em;
}
& > #main-nav {
grid-area: nav;
}
& > #log {
grid-area: log;
width: 100%;
overflow: auto;
}
& .dragging {
background: red;
}
& summary {
background: #eee;
}
& > #main-nav > nav {
display: flex;
flex-direction: column;
gap: var(--spacing);
& #file-tree {
margin: 0;
overflow: auto;
flex-grow: 1;
& > li {
margin-top: var(--half-spacing);
& > a {
text-decoration: none;
}
}
& .dir {
font-weight: bold;
}
& .dir + .file {
margin-top: var(--spacing);
}
}
& form {
display: grid;
grid-template-columns: 1fr 6em;
align-content: start;
align-items: start;
}
& #make-log {
& > pre {
max-width: 20em;
overflow: auto;
}
}
}
& #editor {
overflow: hidden;
flex-grow: 1;
flex-basis: var(--editor-size);
max-height: 85vh;
grid-area: editor;
& #editor-controls {
display: flex;
gap: var(--spacing);
justify-content: space-between;
& > details {
text-align: right;
& > summary {
user-select: none;
}
& button {
margin: var(--half-spacing) 0;
}
}
}
& #code-editor {
display: block;
max-width: 50vw;
padding-bottom: 10em;
}
}
& #preview {
display: flex;
flex-direction: column;
grid-area: preview;
&[open] {
flex-grow: 1;
flex-shrink: 1;
flex-basis: calc(100% - var(--editor-size));
}
& > summary {
text-align: right;
}
& > iframe {
width: 100%;
height: calc(100% - 3em);
border: none;
}
&[closed] > iframe {
display: none;
}
}
}
#file-form {
overflow: auto;
max-height: 100%;
max-width: 100%;
}
@media (max-width: 100ch) {
html {
font-size: min(3vw, 16px);
}
.think-editor {
overflow: visible;
grid-template:
"nav"
"log"
"editor"
"preview"
;
& > * ~ * {
border-top: medium solid #888;
margin-top: var(--spacing);
}
& nav {
flex-direction: row;
flex-wrap: wrap;
& form {
flex-grow: 1;
}
& #file-tree {
max-height: 7em;
}
}
& #editor {
overflow: auto;
& #code-editor {
max-width: none;
}
}
& #preview {
height: 100vh;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -18,6 +18,44 @@ body {
}
}
body.login {
display: grid;
align-content: center;
justify-content: center;
height: 100svh;
margin: 0;
padding: var(--spacing);
& header {
text-align: center;
}
& form {
display: grid;
gap: var(--spacing);
& div {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-flow: row;
gap: var(--spacing);
align-items: center;
& label {
grid-column: 1;
justify-self: end;
}
& input {
grid-column: 2;
}
}
grid-template-rows: 2em 2em 2em;
}
}
body.index {
font-size: 20px;
@ -32,7 +70,7 @@ body.index {
gap: var(--double-spacing);
}
& #thinks-list {
& .thinks-list {
display: flex;
flex-direction: column;
gap: var(--double-spacing);