<todo-create></todo-create>
<todo-list></todo-list>
import {realtimeRestModel, DefineMap, DefineList, Component, fixture} from "//unpkg.com/can@5/core.mjs";
const Todo = DefineMap.extend("Todo",{
id: { type: "number", identity: true },
complete: { type: "boolean", default: false },
dueDate: {type: "date", Default: Date},
name: "string",
preventSave(){
return !this.name || this.isSaving() || this.isDestroying();
}
});
Todo.List = DefineList.extend("TodoList",{
"#": Todo
});
const todoConnection = realtimeRestModel({
Map: Todo,
List: Todo.List,
url: "/api/todos/{id}"
});
mockService();
Component.extend({
tag: "todo-list",
view: `
Sort By: <select value:bind="sort">
<option value="">none</option>
<option value="name">name</option>
<option value="dueDate">dueDate</option>
</select>
Show: <select value:bind="completeFilter">
<option value="">All</option>
<option value="complete">Complete</option>
<option value="incomplete">Incomplete</option>
</select>
Due: <select value:bind="dueFilter">
<option value="">Anytime</option>
<option value="today">Today</option>
<option value="week">This Week</option>
</select>
Results <select value:bind="count">
<option value="">All</option>
<option value="10">10</option>
<option value="20">20</option>
</select>
<ul>
{{# if(todosPromise.isResolved) }}
{{# for(todo of todosPromise.value) }}
<li>
<input type='checkbox'
checked:bind='todo.complete'
on:change="todo.save()"
disabled:from="todo.preventSave()"/>
<label>{{ todo.name }}</label>
<input type='date'
valueAsDate:bind='todo.dueDate'
on:change="todo.save()"
disabled:from="todo.preventSave()"/>
<button on:click="todo.destroy()"
disabled:from="todo.preventSave()">delete</button>
</li>
{{/ for }}
{{/ if }}
{{# if(todosPromise.isPending) }}
<li>Loading</li>
{{/ if }}
</ul>
`,
ViewModel: {
sort: "string",
completeFilter: "string",
dueFilter: "string",
count: {type:"string", default: "10"},
todosPromise: {
get(){
var query = {filter: { }};
if(this.sort) {
query.sort = this.sort;
}
if(this.completeFilter) {
query.filter.complete = this.completeFilter === "complete";
}
if(this.dueFilter) {
var day = 24*60*60*1000;
var now = new Date();
var today = new Date(now.getFullYear(), now.getMonth(), now.getDate() );
if(this.dueFilter === "today") {
query.filter.dueDate = {
$gte: now.toString(),
$lt: new Date(now.getTime() + day).toString()
}
}
if(this.dueFilter === "week") {
var start = today.getTime() - (today.getDay() * day);
query.filter.dueDate = {
$gte: new Date(start).toString(),
$lt: new Date(start + 7*day).toString()
};
}
}
if(this.count) {
query.page = {
start: 0,
end: (+this.count)-1
};
}
return Todo.getList(query);
}
}
}
});
Component.extend({
tag: "todo-create",
view: `
<form on:submit="createTodo(scope.event)">
<p>
<label>Name</label>
<input on:input:value:bind='todo.name'/>
</p>
<p>
<label>Complete</label>
<input type='checkbox' checked:bind='todo.complete'/>
</p>
<p>
<label>Date</label>
<input type='date' valueAsDate:bind='todo.dueDate'/>
</p>
<button disabled:from="todo.preventSave()">Create Todo</button>
{{# if(todo.isSaving()) }}Creating ....{{/ if }}
</form>
`,
ViewModel: {
todo: {
Default: Todo
},
createTodo(event) {
event.preventDefault();
this.todo.save().then((createdTodo) => {
this.todo = new Todo();
})
}
}
});
function mockService(){
var terms = ["can you","please","","","",""],
verbs = ["clean","walk","do","vaccum","organize","fold","wash","dust","pay","cook","get","take out"],
subjects = ["dog","laundry","diapers","clothes","car","windows","carpet","taxes","food","gas","trash"];
var dayInMS = 24*60*60*1000;
var lastWeek = new Date() - (7*dayInMS);
var fourWeeks = new Date().getTime() + (4*7*dayInMS);
var todoStore = fixture.store(100, function(){
return {
complete: fixture.rand([true, false],1)[0],
dueDate: new Date( fixture.rand(lastWeek, fourWeeks) ).toString(),
name: (fixture.rand(terms,1)[0]+" "+fixture.rand(verbs,1)[0]+" "+fixture.rand(subjects,1)[0]).trim()
}
}, Todo);
fixture("/api/todos/{id}", todoStore);
fixture.delay = 500;
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.