Skip to content
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

Feat/do not use multiline descriptions #60

Merged
merged 3 commits into from
Jun 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ rules:
- "sibling"
- "type"
import/no-unresolved: off
ignorePatterns:
- '*.d.ts'
9 changes: 3 additions & 6 deletions src/delay.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
export const delay = (t = 0): Promise<number> =>
export const delay = (t = 0): PromiseLike<number> =>
({
then: (resolve: typeof Promise.resolve) => {
const timeout: ReturnType<typeof setTimeout> = setTimeout(
() => resolve(timeout),
t
)
const timeout = setTimeout(() => resolve(timeout), t)
},
} as Promise<number>)
} as PromiseLike<number>)
3 changes: 2 additions & 1 deletion src/examples/purity-todo/components/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ const headerStyle = (): string => render`
#header ul {
display: flex;
justify-content: space-around;
box-shadow: 0px 4px 10px -2px
user-select: none;
box-shadow: 0px 4px 10px -2px;
}

</style>
Expand Down
3 changes: 3 additions & 0 deletions src/examples/purity-todo/components/modal-style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@ export const modalStyle = (): string => render`

.modal {
border: 1px solid wheat;
box-shadow: 0px 4px 16px 0px;
}

.modal .modal-header {
background-color: lightgrey;
font-weight: bold;
position: relative;
box-shadow: 0px 8px 10px -10px;
${lineContainerCSS}
}

Expand Down
5 changes: 4 additions & 1 deletion src/examples/purity-todo/components/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ export const root = (): string => render`
}
</div>
${modalStyle()}
${theIntrospector({state, localStorage: window.localStorage})}
${theIntrospector({
task_1: state?.tasks?.[0],
localStorage: window.localStorage,
})}
</div>
`
15 changes: 6 additions & 9 deletions src/examples/purity-todo/components/task-details-style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ export const taskDetailsStyle = (): string => render`
}

.task-details--image .fullscreen-image {
height: 90vw;
max-height: 90vw;
height: min(90vw, 33vh);
max-height: min(90vw, 33vh);
transition: height .2s ease-in;

background-size: cover;
background-repeat: no-repeat;
background-position: center;
position: relative;
}
Expand All @@ -43,18 +44,14 @@ export const taskDetailsStyle = (): string => render`

.task-details--description {
flex-grow: 1;
background: pink;
}

.task-details--description textarea {
width: 100%;
height: 3rem;
padding: 4px 8px;
background: #f0f0f0;
}

.description-edit, .subtask-input {
width: 100%;
padding: 4px 8px;
border: none;
height: 2rem;
}

.subtask {
Expand Down
17 changes: 11 additions & 6 deletions src/examples/purity-todo/components/task-details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const makeChangeImage =

const handleCaptureImage: EventHandler = async ({target}) => {
try {
const [file] = target.files!
const [file] = target.files as FileList
if (!file) {
return
}
Expand Down Expand Up @@ -71,6 +71,9 @@ const handleAddSubtask: EventHandler = () => {
id: task.id,
subtasks: [...(task.subtasks || []), {checked: false, description: ""}],
})
document
.querySelector<HTMLInputElement>(".subtask:last-child input.subtask-input")
?.focus()
}

export const taskDetails = (): string => {
Expand Down Expand Up @@ -126,12 +129,14 @@ export const taskDetails = (): string => {

<section class="task-details--description">
<!-- TODO: use debounce TODO: bound event handlers properly -->
<textarea
<input
id="task-description-edit"
::change=${handleEditTaskDescription}
>
${task?.description}
</textarea>
class="description-edit"
value="${task?.description ?? ""}"
placeholder="Task description"
autocomplete="off"
::input=${handleEditTaskDescription}
/>
<div id="subtasks-list">
${task.subtasks?.map(subtaskItem)}
</div>
Expand Down
109 changes: 109 additions & 0 deletions src/examples/purity-todo/components/task-item.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import {describe, it, expect, beforeEach, afterEach} from "vitest"
import {delay} from "../../../delay.js"
import {taskItem} from "./task-item.js"
import type {Task} from "../app.js"

const getTestTask = (): Task =>
structuredClone({
description: "test",
id: "test",
completed: false,
image: {
link: "image.png",
queries: {
request: {startIndex: 0},
},
},
createdAt: 0,
updatedAt: 0,
})

describe("task-item", () => {
afterEach(async () => {
// Cleanup for data-purity keys.
await delay()
})

it("should render correctly for a given task item", () => {
const item = getTestTask()
expect(taskItem(item)).toMatchInlineSnapshot(`
"<li id="test" class="task-item "><img
src="image.png"
onerror="this.onerror = null; this.src = './assets/images/icon-pack/forbidden.svg'"
loading="lazy"
/><div
class="item-description"
data-id="test"
data-purity_click_0 data-purity_flag
>test</div><button
id="delete-test"
class="action-button delete-button hidden"
data-id="test"
title="Delete"
>⊟</button><button
id="toggle-test"
class="action-button toggle-button"
data-id="test"
data-completed=""
title="Toggle"
>⊡</button></li>"
`)
})

it("should render correctly for a completed task item", () => {
const item = getTestTask()
item.completed = true
expect(taskItem(item)).toMatchInlineSnapshot(`
"<li id="test" class="task-item completed"><img
src="image.png"
onerror="this.onerror = null; this.src = './assets/images/icon-pack/forbidden.svg'"
loading="lazy"
/><div
class="item-description"
data-id="test"
data-purity_click_0 data-purity_flag
>test</div><button
id="delete-test"
class="action-button delete-button "
data-id="test"
title="Delete"
>⊟</button><button
id="toggle-test"
class="action-button toggle-button"
data-id="test"
data-completed="true"
title="Toggle"
>⊠</button></li>"
`)
})

it("should render correctly for a given task item with subtasks", () => {
const item = getTestTask()
item.subtasks = [
{description: "checked (should not be visible!)", checked: true},
{description: "not checked (should be visible!)", checked: false},
]
expect(taskItem(item)).toMatchInlineSnapshot(`
"<li id="test" class="task-item "><img
src="image.png"
onerror="this.onerror = null; this.src = './assets/images/icon-pack/forbidden.svg'"
loading="lazy"
/><div
class="item-description"
data-id="test"
data-purity_click_0 data-purity_flag
>test<span class="subtask-inline">not checked (should be visible!)</span></div><button
id="delete-test"
class="action-button delete-button hidden"
data-id="test"
title="Delete"
>⊟</button><button
id="toggle-test"
class="action-button toggle-button"
data-id="test"
data-completed=""
title="Toggle"
>⊡</button></li>"
`)
})
})
17 changes: 10 additions & 7 deletions src/examples/purity-todo/components/task-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {render} from "../../../index.js"
import {IMAGES} from "../config/images.js"
import {openTaskDetails} from "../services/task-details.js"
import {ACTION_BUTTON} from "./app-style.js"
import type {Task} from "../app.js"
import type {Subtask, Task} from "../app.js"

export const TOGGLE_BUTTON = "toggle-button"
export const withToggleButton =
Expand Down Expand Up @@ -31,17 +31,19 @@ export const withItemDescription =
}
}

const formatDescription = (description: string): string => {
const [first, ...rest] = description.trim().split("\n")
return `${first}${rest.map(item => render`<span> ⊡ ${item}</span>`).join("")}`
}
export const subtaskItem = (item: Subtask) => render`
<span class="subtask-inline">
${item.description}
</span>
`

export const taskItem = ({
description,
id,
completed,
image,
}: Task): string => render`
subtasks = [],
}: Task) => render`
<li id="${id}" class="task-item ${completed && "completed"}">
<img
src="${image.link}"
Expand All @@ -53,7 +55,8 @@ export const taskItem = ({
data-id="${id}"
::click=${openTaskDetails}
>
${formatDescription(description)}
${description.trim()}
${subtasks.filter(({checked}) => !checked).map(subtaskItem)}
</div>
<button
id="delete-${id}"
Expand Down
9 changes: 8 additions & 1 deletion src/examples/purity-todo/components/task-list-style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,14 @@ export const taskListStyle = (): string => render`
color: lightgrey;
}

.${ITEM_DESCRIPTION} span {
.${ITEM_DESCRIPTION} .subtask-inline {
color: lightgrey;
}

.${ITEM_DESCRIPTION} .subtask-inline::before {
content: "⊡";
margin-right: 0.5rem;
margin-left: 0.5rem;
color: lightgrey;
}

Expand Down
2 changes: 1 addition & 1 deletion src/examples/purity-todo/manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "Purity Todo 2.12",
"name": "Purity Todo 2.13",
"short_name": "ToDo",
"description": "Todo list written with purity.js",
"icons": [
Expand Down
3 changes: 1 addition & 2 deletions src/examples/purity-todo/purity-todo.sw.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
const appScope = self.registration.scope

const cacheName = `${appScope}@2.12`
const cacheName = `${appScope}@2.13`
const contentToCache = [
"./",
"./index.html",
"./index.js",

"./assets/images/todo-icon-48.png",
"./assets/images/todo-icon-192.png",
Expand Down
2 changes: 1 addition & 1 deletion src/examples/purity-todo/services/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const downloadUserData = async (): Promise<void> => {
}

export const uploadUserData: EventHandler = async ({target: {files}}) => {
const [file] = files!
const [file] = files as FileList
try {
const text = await textFileReader(file)
const tasks: BaseTask[] = JSON.parse(text)
Expand Down
2 changes: 1 addition & 1 deletion src/examples/purity-todo/services/task-details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ export const openTaskDetails: EventHandler = e => {
}

export const selectDetailedTask = (): Task =>
state.tasks.find(({id}) => id === state.taskDetailId)!
state.tasks.find(({id}) => id === state.taskDetailId) as Task
3 changes: 2 additions & 1 deletion src/playground/components/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {configureMonacoEditor} from "../services/monaco-editor-config.js"
import {createUpdate, defaultCode} from "../services/user-code.js"
import {editorStyle} from "./editor-style.js"

export const getEditor = (): HTMLElement => document.getElementById("editor")!
export const getEditor = (): HTMLElement =>
document.getElementById("editor") as HTMLElement

export const editor = (): string => {
once("configure-editor", () => {
Expand Down
2 changes: 1 addition & 1 deletion src/playground/components/playground.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {view} from "./view.js"
const initDrag = makeDrag(e => {
const startWidth = window.getComputedStyle(getEditor()).width
const fullWidth = window.getComputedStyle(
document.getElementById("playground-root")!
document.getElementById("playground-root") as HTMLElement
).width
console.log("drag:init", startWidth, "/", fullWidth)
setState(() => ({placeOverDisplay: "initial"}))
Expand Down
3 changes: 3 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@ export default defineConfig({
include: ["src/**/*.ts"],
exclude: ["src/**/index.ts", "src/**/*.test.ts", "src/**/*.d.ts"],
},
snapshotFormat: {
escapeString: false,
},
},
})