Random tasks, more info
This commit is contained in:
parent
9187461ed4
commit
f93ad89194
7 changed files with 288 additions and 100 deletions
93
app/src/api/fetcher.ts
Normal file
93
app/src/api/fetcher.ts
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
import { pb } from "./pb";
|
||||||
|
import { ListsResponse, TasksResponse } from "./pocketbase-types";
|
||||||
|
|
||||||
|
export interface ListData {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
parentId: string | null;
|
||||||
|
lists: Array<{
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
listCount: number;
|
||||||
|
taskCount: number;
|
||||||
|
}>;
|
||||||
|
tasks: Array<TasksResponse>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function listFetcher(id: string): Promise<ListData> {
|
||||||
|
type Expand = { "lists(parent)": unknown[]; "tasks(list)": unknown[] };
|
||||||
|
type ListsResponseExpand = ListsResponse<Expand>;
|
||||||
|
if (id === "all") {
|
||||||
|
const lists = await pb
|
||||||
|
.collection<ListsResponseExpand>("lists")
|
||||||
|
.getList(0, 50, {
|
||||||
|
filter: pb.filter("parent = null"),
|
||||||
|
expand: "lists(parent),tasks(list)",
|
||||||
|
});
|
||||||
|
const tasks = await pb.collection("tasks").getList(0, 50, {
|
||||||
|
filter: pb.filter("list = null"),
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
name: "Lists",
|
||||||
|
parentId: null,
|
||||||
|
lists: lists.items.map((l) => ({
|
||||||
|
id: l.id,
|
||||||
|
name: l.name,
|
||||||
|
listCount: l.expand?.["lists(parent)"]?.length || 0,
|
||||||
|
taskCount: l.expand?.["tasks(list)"]?.length || 0,
|
||||||
|
})),
|
||||||
|
tasks: tasks.items,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const list = await pb.collection("lists").getOne(id);
|
||||||
|
const lists = await pb
|
||||||
|
.collection<ListsResponseExpand>("lists")
|
||||||
|
.getList(0, 50, {
|
||||||
|
filter: pb.filter("parent = {:id}", { id }),
|
||||||
|
expand: "lists(parent),tasks(list)",
|
||||||
|
});
|
||||||
|
const tasks = await pb.collection("tasks").getList(0, 50, {
|
||||||
|
filter: pb.filter("list = {:id}", { id }),
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
name: list.name,
|
||||||
|
parentId: list.parent,
|
||||||
|
lists: lists.items.map((l) => ({
|
||||||
|
id: l.id,
|
||||||
|
name: l.name,
|
||||||
|
listCount: l.expand?.["lists(parent)"]?.length || 0,
|
||||||
|
taskCount: l.expand?.["tasks(list)"]?.length || 0,
|
||||||
|
})),
|
||||||
|
tasks: tasks.items,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskData extends TasksResponse {
|
||||||
|
listId: string;
|
||||||
|
imageSource: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function taskFetcher(id: string): Promise<TaskData> {
|
||||||
|
const task = await pb.collection("tasks").getOne(id);
|
||||||
|
const icon = await pb.collection("icons").getOne(task.icon);
|
||||||
|
const imageSource = pb.getFileUrl(icon, icon.image, {
|
||||||
|
thumb: "300x300",
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...task,
|
||||||
|
listId: task.list,
|
||||||
|
imageSource,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RandomTaskData {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function randomTask(parent: string | null) {
|
||||||
|
return await pb.send<RandomTaskData>(`/api/extras/random/${parent}`, {});
|
||||||
|
}
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
import PocketBase from "pocketbase";
|
|
||||||
import type { TypedPocketBase } from "./pocketbase-types";
|
|
||||||
|
|
||||||
export const pb = new PocketBase("https://musclecat.pi.korz.tech") as TypedPocketBase;
|
|
||||||
5
app/src/api/pb.ts
Normal file
5
app/src/api/pb.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
import PocketBase from "pocketbase";
|
||||||
|
import type { TypedPocketBase } from "./pocketbase-types";
|
||||||
|
|
||||||
|
//export const pb = new PocketBase("https://musclecat.pi.korz.tech") as TypedPocketBase;
|
||||||
|
export const pb = new PocketBase("http://localhost:8090") as TypedPocketBase;
|
||||||
|
|
@ -5,27 +5,42 @@ import {
|
||||||
useWindowDimensions,
|
useWindowDimensions,
|
||||||
Image,
|
Image,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
import { Appbar, Text, Avatar, Card, List, useTheme } from "react-native-paper";
|
import { Appbar, Text, Avatar, Card, List, useTheme, Button } from "react-native-paper";
|
||||||
import {
|
import {
|
||||||
StackHeaderProps,
|
StackHeaderProps,
|
||||||
createStackNavigator,
|
createStackNavigator,
|
||||||
} from "@react-navigation/stack";
|
} from "@react-navigation/stack";
|
||||||
import RenderHtml from "react-native-render-html";
|
import RenderHtml from "react-native-render-html";
|
||||||
import { HomeScreenNavigationProp } from "./types";
|
import { HomeScreenNavigationProp } from "./types";
|
||||||
import useSWR from "swr";
|
import useSWR, { preload } from "swr";
|
||||||
import { pb } from "../api";
|
|
||||||
import { getHeaderTitle } from "@react-navigation/elements";
|
import { getHeaderTitle } from "@react-navigation/elements";
|
||||||
import { useEffect, useLayoutEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
import { ListData, listFetcher, randomTask, taskFetcher } from "../api/fetcher";
|
||||||
|
|
||||||
|
function ListItem(props: { data: ListData["lists"][0]; onPress(): void }) {
|
||||||
|
const { name, listCount, taskCount } = props.data;
|
||||||
|
let subtitle = "";
|
||||||
|
if (listCount) {
|
||||||
|
subtitle += `${listCount} lists`;
|
||||||
|
}
|
||||||
|
if (listCount && taskCount) {
|
||||||
|
subtitle += " • "
|
||||||
|
}
|
||||||
|
if (taskCount) {
|
||||||
|
subtitle += `${taskCount} tasks`;
|
||||||
|
}
|
||||||
|
if (!listCount && !taskCount) {
|
||||||
|
subtitle += "Empty";
|
||||||
|
}
|
||||||
|
|
||||||
function ListItem(props: { name: string; onPress(): void }) {
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
style={{ marginHorizontal: 8, marginBottom: 8 }}
|
style={{ marginHorizontal: 8, marginBottom: 8 }}
|
||||||
onPress={props.onPress}
|
onPress={props.onPress}
|
||||||
>
|
>
|
||||||
<Card.Title
|
<Card.Title
|
||||||
title={props.name}
|
title={name}
|
||||||
//subtitle="A list"
|
subtitle={subtitle}
|
||||||
left={(props) => <Avatar.Icon {...props} icon="clipboard-list" />}
|
left={(props) => <Avatar.Icon {...props} icon="clipboard-list" />}
|
||||||
/*right={(props) => (
|
/*right={(props) => (
|
||||||
<IconButton {...props} icon="dots-vertical" onPress={() => {}} />
|
<IconButton {...props} icon="dots-vertical" onPress={() => {}} />
|
||||||
|
|
@ -35,64 +50,23 @@ function ListItem(props: { name: string; onPress(): void }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TaskItem(props: { name: string; onPress(): void }) {
|
function TaskItem(props: { data: ListData["tasks"][0]; onPress(): void }) {
|
||||||
|
const { id, name, schedule } = props.data;
|
||||||
|
const date = new Date(schedule);
|
||||||
|
const now = new Date();
|
||||||
|
const ready = date <= now;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<List.Item
|
<List.Item
|
||||||
title={props.name}
|
title={name}
|
||||||
//description="A task"
|
description={ready ? "Ready" : "Not ready"}
|
||||||
left={(props) => <List.Icon {...props} icon="clipboard-check-outline" />}
|
left={(props) => <List.Icon {...props} icon="clipboard-check-outline" />}
|
||||||
onPress={props.onPress}
|
onPress={props.onPress}
|
||||||
|
onPressIn={() => preload(id, taskFetcher)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ListResponse {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
parentId: string | null;
|
|
||||||
lists: Array<{
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
}>;
|
|
||||||
tasks: Array<{
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function listFetcher(id: string): Promise<ListResponse> {
|
|
||||||
if (id === "all") {
|
|
||||||
const lists = await pb.collection("lists").getList(0, 50, {
|
|
||||||
filter: pb.filter("parent = null"),
|
|
||||||
});
|
|
||||||
const tasks = await pb.collection("tasks").getList(0, 50, {
|
|
||||||
filter: pb.filter("list = null"),
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
id,
|
|
||||||
name: "Lists",
|
|
||||||
parentId: null,
|
|
||||||
lists: lists.items.map((l) => ({ id: l.id, name: l.name })),
|
|
||||||
tasks: tasks.items.map((l) => ({ id: l.id, name: l.name })),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const list = await pb.collection("lists").getOne(id);
|
|
||||||
const lists = await pb.collection("lists").getList(0, 50, {
|
|
||||||
filter: pb.filter("parent = {:id}", { id }),
|
|
||||||
});
|
|
||||||
const tasks = await pb.collection("tasks").getList(0, 50, {
|
|
||||||
filter: pb.filter("list = {:id}", { id }),
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
id,
|
|
||||||
name: list.name,
|
|
||||||
parentId: list.parent,
|
|
||||||
lists: lists.items.map((l) => ({ id: l.id, name: l.name })),
|
|
||||||
tasks: tasks.items.map((l) => ({ id: l.id, name: l.name })),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function ListContent({ route, navigation }: HomeScreenNavigationProp<"List">) {
|
function ListContent({ route, navigation }: HomeScreenNavigationProp<"List">) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { listId, listName } = route.params ?? {};
|
const { listId, listName } = route.params ?? {};
|
||||||
|
|
@ -137,8 +111,10 @@ function ListContent({ route, navigation }: HomeScreenNavigationProp<"List">) {
|
||||||
{lists.map((l) => (
|
{lists.map((l) => (
|
||||||
<ListItem
|
<ListItem
|
||||||
key={l.id}
|
key={l.id}
|
||||||
name={l.name}
|
data={l}
|
||||||
onPress={() => navigation.push("List", { listId: l.id, listName: l.name })}
|
onPress={() =>
|
||||||
|
navigation.push("List", { listId: l.id, listName: l.name })
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{tasks.length > 0 && (
|
{tasks.length > 0 && (
|
||||||
|
|
@ -147,8 +123,10 @@ function ListContent({ route, navigation }: HomeScreenNavigationProp<"List">) {
|
||||||
{tasks.map((t) => (
|
{tasks.map((t) => (
|
||||||
<TaskItem
|
<TaskItem
|
||||||
key={t.id}
|
key={t.id}
|
||||||
name={t.name}
|
data={t}
|
||||||
onPress={() => navigation.push("Task", { taskId: t.id, taskName: t.name })}
|
onPress={() =>
|
||||||
|
navigation.push("Task", { taskId: t.id, taskName: t.name })
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</List.Section>
|
</List.Section>
|
||||||
|
|
@ -157,29 +135,6 @@ function ListContent({ route, navigation }: HomeScreenNavigationProp<"List">) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TaskResponse {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
listId: string;
|
|
||||||
imageSource: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function taskFetcher(id: string): Promise<TaskResponse> {
|
|
||||||
const task = await pb.collection("tasks").getOne(id);
|
|
||||||
const icon = await pb.collection("icons").getOne(task.icon);
|
|
||||||
const imageSource = pb.getFileUrl(icon, icon.image, {
|
|
||||||
thumb: "300x300",
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
id,
|
|
||||||
name: task.name,
|
|
||||||
description: task.description,
|
|
||||||
listId: task.list,
|
|
||||||
imageSource,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function TaskContent({ route, navigation }: HomeScreenNavigationProp<"Task">) {
|
function TaskContent({ route, navigation }: HomeScreenNavigationProp<"Task">) {
|
||||||
const dimensions = useWindowDimensions();
|
const dimensions = useWindowDimensions();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
@ -211,12 +166,15 @@ function TaskContent({ route, navigation }: HomeScreenNavigationProp<"Task">) {
|
||||||
<View
|
<View
|
||||||
style={[styles.padded, { backgroundColor: theme.colors.background }]}
|
style={[styles.padded, { backgroundColor: theme.colors.background }]}
|
||||||
>
|
>
|
||||||
<Text>Something went wrong: {error.toString()}</Text>
|
<Text>Something went wrong: {error?.toString()}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { name, description, imageSource } = data;
|
const { name, description, schedule, imageSource } = data;
|
||||||
|
const date = new Date(schedule);
|
||||||
|
const now = new Date();
|
||||||
|
const ready = date <= now;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
|
|
@ -235,6 +193,7 @@ function TaskContent({ route, navigation }: HomeScreenNavigationProp<"Task">) {
|
||||||
fontSize: "1.1em",
|
fontSize: "1.1em",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Button disabled={!ready} mode="contained">{ready ? "Start" : "Not ready"}</Button>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -245,14 +204,24 @@ function ListNavigationBar({
|
||||||
options,
|
options,
|
||||||
back,
|
back,
|
||||||
}: StackHeaderProps) {
|
}: StackHeaderProps) {
|
||||||
const title = getHeaderTitle(options, (route.params as any)?.listName || route.name);
|
const params = route.params as any | undefined;
|
||||||
|
const title = getHeaderTitle(options, params?.listName || route.name);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Appbar.Header elevated>
|
<Appbar.Header elevated>
|
||||||
{back ? <Appbar.BackAction onPress={() => navigation.pop()} /> : null}
|
{(back || params?.listId) ? <Appbar.BackAction
|
||||||
|
onPress={() => (back ? navigation.pop() : navigation.replace("List"))}
|
||||||
|
/> : null}
|
||||||
<Appbar.Content title={title} />
|
<Appbar.Content title={title} />
|
||||||
<Appbar.Action icon="dice-multiple-outline" onPress={() => {}} />
|
<Appbar.Action
|
||||||
<Appbar.Action icon="magnify" onPress={() => {}} />
|
icon="dice-multiple-outline"
|
||||||
|
onPress={() =>
|
||||||
|
randomTask(params?.listId || null).then((data) =>
|
||||||
|
navigation.push("Task", { taskId: data.id, taskName: data.name }),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{/*<Appbar.Action icon="magnify" onPress={() => {}} />*/}
|
||||||
</Appbar.Header>
|
</Appbar.Header>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -263,7 +232,10 @@ function TaskNavigationBar({
|
||||||
options,
|
options,
|
||||||
back,
|
back,
|
||||||
}: StackHeaderProps) {
|
}: StackHeaderProps) {
|
||||||
const title = getHeaderTitle(options, (route.params as any)?.taskName || route.name);
|
const title = getHeaderTitle(
|
||||||
|
options,
|
||||||
|
(route.params as any)?.taskName || route.name,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Appbar.Header elevated>
|
<Appbar.Header elevated>
|
||||||
|
|
@ -271,8 +243,8 @@ function TaskNavigationBar({
|
||||||
onPress={() => (back ? navigation.pop() : navigation.replace("List"))}
|
onPress={() => (back ? navigation.pop() : navigation.replace("List"))}
|
||||||
/>
|
/>
|
||||||
<Appbar.Content title={title} />
|
<Appbar.Content title={title} />
|
||||||
<Appbar.Action icon="run-fast" onPress={() => {}} />
|
{/*<Appbar.Action icon="run-fast" onPress={() => {}} />*/}
|
||||||
<Appbar.Action icon="square-edit-outline" onPress={() => {}} />
|
{/*<Appbar.Action icon="square-edit-outline" onPress={() => {}} />*/}
|
||||||
</Appbar.Header>
|
</Appbar.Header>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -281,9 +253,7 @@ const Stack = createStackNavigator();
|
||||||
|
|
||||||
export function ScreenList() {
|
export function ScreenList() {
|
||||||
return (
|
return (
|
||||||
<Stack.Navigator
|
<Stack.Navigator initialRouteName="List">
|
||||||
initialRouteName="List"
|
|
||||||
>
|
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="List"
|
name="List"
|
||||||
component={ListContent as any}
|
component={ListContent as any}
|
||||||
|
|
|
||||||
21
pb_hooks/main.pb.js
Normal file
21
pb_hooks/main.pb.js
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
routerAdd("GET", "/api/extras/random/:parent", (c) => {
|
||||||
|
const result = new DynamicModel({
|
||||||
|
"id": "",
|
||||||
|
"name": "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const query = `WITH RECURSIVE descendants(id) AS (
|
||||||
|
VALUES({:parent}) UNION ALL
|
||||||
|
SELECT l.id FROM lists l JOIN descendants d ON d.id = l.parent
|
||||||
|
) SELECT t.id, t.name FROM tasks t JOIN descendants d ON t.list = d.id WHERE t.schedule <= DATE('now') ORDER BY RANDOM() LIMIT 1`;
|
||||||
|
const queryNull = `SELECT id, name FROM tasks WHERE schedule <= DATE('now') ORDER BY RANDOM() LIMIT 1`;
|
||||||
|
const parent = c.pathParam("parent");
|
||||||
|
|
||||||
|
$app.dao().db()
|
||||||
|
.newQuery(parent === "null" ? queryNull : query)
|
||||||
|
.bind({ parent })
|
||||||
|
.one(result)
|
||||||
|
|
||||||
|
return c.json(200, result)
|
||||||
|
})
|
||||||
|
|
||||||
61
pb_migrations/1704322685_updated_tasks.js
Normal file
61
pb_migrations/1704322685_updated_tasks.js
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
/// <reference path="../pb_data/types.d.ts" />
|
||||||
|
migrate((db) => {
|
||||||
|
const dao = new Dao(db)
|
||||||
|
const collection = dao.findCollectionByNameOrId("pf13z4hs1iubw41")
|
||||||
|
|
||||||
|
// add
|
||||||
|
collection.schema.addField(new SchemaField({
|
||||||
|
"system": false,
|
||||||
|
"id": "mxuameue",
|
||||||
|
"name": "reward",
|
||||||
|
"type": "number",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": 0,
|
||||||
|
"max": 10,
|
||||||
|
"noDecimal": false
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
// update
|
||||||
|
collection.schema.addField(new SchemaField({
|
||||||
|
"system": false,
|
||||||
|
"id": "qjz9b0tm",
|
||||||
|
"name": "index4groupdefaultschedule",
|
||||||
|
"type": "date",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": "",
|
||||||
|
"max": ""
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
return dao.saveCollection(collection)
|
||||||
|
}, (db) => {
|
||||||
|
const dao = new Dao(db)
|
||||||
|
const collection = dao.findCollectionByNameOrId("pf13z4hs1iubw41")
|
||||||
|
|
||||||
|
// remove
|
||||||
|
collection.schema.removeField("mxuameue")
|
||||||
|
|
||||||
|
// update
|
||||||
|
collection.schema.addField(new SchemaField({
|
||||||
|
"system": false,
|
||||||
|
"id": "qjz9b0tm",
|
||||||
|
"name": "schedule",
|
||||||
|
"type": "date",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": "",
|
||||||
|
"max": ""
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
return dao.saveCollection(collection)
|
||||||
|
})
|
||||||
42
pb_migrations/1704322700_updated_tasks.js
Normal file
42
pb_migrations/1704322700_updated_tasks.js
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
/// <reference path="../pb_data/types.d.ts" />
|
||||||
|
migrate((db) => {
|
||||||
|
const dao = new Dao(db)
|
||||||
|
const collection = dao.findCollectionByNameOrId("pf13z4hs1iubw41")
|
||||||
|
|
||||||
|
// update
|
||||||
|
collection.schema.addField(new SchemaField({
|
||||||
|
"system": false,
|
||||||
|
"id": "qjz9b0tm",
|
||||||
|
"name": "schedule",
|
||||||
|
"type": "date",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": "",
|
||||||
|
"max": ""
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
return dao.saveCollection(collection)
|
||||||
|
}, (db) => {
|
||||||
|
const dao = new Dao(db)
|
||||||
|
const collection = dao.findCollectionByNameOrId("pf13z4hs1iubw41")
|
||||||
|
|
||||||
|
// update
|
||||||
|
collection.schema.addField(new SchemaField({
|
||||||
|
"system": false,
|
||||||
|
"id": "qjz9b0tm",
|
||||||
|
"name": "index4groupdefaultschedule",
|
||||||
|
"type": "date",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": "",
|
||||||
|
"max": ""
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
return dao.saveCollection(collection)
|
||||||
|
})
|
||||||
Loading…
Add table
Add a link
Reference in a new issue