Created
September 5, 2021 03:31
-
-
Save nightire/b109ad2ee1173c18d5522e6a2f7d875c to your computer and use it in GitHub Desktop.
Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { registerDestructor } from '@ember/destroyable'; | |
import { action } from '@ember/object'; | |
import Component from '@glimmer/component'; | |
import { tracked } from '@glimmer/tracking'; | |
import { task, timeout } from 'ember-concurrency'; | |
import { taskFor } from 'ember-concurrency-ts'; | |
import type { Named, Positional } from 'ember-resources'; | |
import { Resource, useResource } from 'ember-resources'; | |
import { api } from 'os-dashboard'; | |
type TaskStatus = 'canceled' | 'completed' | 'pending'; | |
interface TaskSchema { | |
title: string; | |
status: TaskStatus; | |
dateCreated: string; | |
} | |
class Task { | |
constructor(params: TaskSchema) { | |
this.dateCreated = params.dateCreated; | |
this.status = params.status; | |
this.title = params.title; | |
} | |
dateCreated: string; | |
@tracked | |
status: TaskStatus; | |
@tracked | |
title: string; | |
@tracked | |
editable = false; | |
get isPending(): boolean { | |
return this.status === 'pending'; | |
} | |
@action | |
toggleCompleteness() { | |
this.status = this.status === 'pending' ? 'completed' : 'pending'; | |
} | |
@action | |
setTitle(title: string) { | |
this.title = title; | |
this.editable = false; | |
} | |
validateTitle({ value }: { value: string }) { | |
return /^aaa/.test(value) ? ['title is required'] : []; | |
} | |
@action | |
setValidations(event: InputEvent) { | |
const input = event.target as HTMLInputElement; | |
const isValid = input.validity.valid; | |
if (isValid) { | |
if (document.activeElement !== input) { | |
this.editable = false; | |
} | |
if (input.classList.contains('focus:ring-red-200')) { | |
input.classList.remove('focus:ring-red-200'); | |
} | |
} else { | |
input.classList.add('focus:ring-red-200'); | |
input.focus(); | |
} | |
} | |
} | |
type Args = Positional<[string]> & Named; | |
class TaskResource extends Resource<Args> { | |
keyword: string; | |
constructor(owner: unknown, args: Args, state?: TaskResource) { | |
super(owner, args, state); | |
this.keyword = args.positional[0]; | |
if (typeof state === 'undefined') { | |
taskFor(this.fetchTasks).perform(); | |
} else { | |
this._tasks = state._tasks; | |
} | |
registerDestructor(this, () => { | |
taskFor(this.fetchTasks).cancelAll(); | |
}); | |
} | |
@tracked | |
_tasks: Task[] = []; | |
@task({ drop: true, maxConcurrency: 1 }) | |
async fetchTasks(): Promise<void> { | |
const { data } = await api.get('/tasks', { | |
params: { sort: 'date_created' }, | |
}); | |
await timeout(1000); | |
this._tasks = data.map((task: TaskSchema) => new Task(task)); | |
} | |
get value(): unknown[] { | |
return this._tasks.filter((task) => { | |
return task.title.toLowerCase().includes(this.keyword.toLowerCase()); | |
}); | |
} | |
} | |
export default class TasksContainer extends Component { | |
tasks = useResource(this, TaskResource, () => [this.searchKeyword]); | |
@tracked | |
searchKeyword = ''; | |
@action | |
setSearchKeyword(keyword: string): void { | |
this.searchKeyword = keyword; | |
} | |
focusIn(element: HTMLElement): void { | |
element.focus(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment