Skip to content
This repository was archived by the owner on Apr 17, 2023. It is now read-only.

Commit db71e2b

Browse files
authored
Merge pull request #1072 from Arenukvern/feat/vue3-hooks
2 parents f47ddec + 42f9c5d commit db71e2b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1604
-190
lines changed

examples/vue-datastore/README.md

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# vue-datastore
2+
3+
## Project setup
4+
5+
```
6+
yarn install
7+
```
8+
9+
### Compiles and hot-reloads for development
10+
11+
```
12+
yarn serve
13+
```
14+
15+
### Compiles and minifies for production
16+
17+
```
18+
yarn build
19+
```
20+
21+
### Lints and fixes files
22+
23+
```
24+
yarn lint
25+
```
26+
27+
### Customize configuration
28+
29+
See [Configuration Reference](https://cli.vuejs.org/config/).
30+
31+
# Offix - Vue3 Todo Example App
32+
33+
This example demonstrates how to get started using Offix in a Vue project. The app is a simple
34+
todo app making use of the `offix-client` and can be used as launch pad to getting started
35+
with Offix and make use of the features in the library.
36+
37+
## Getting started
38+
39+
To get started, run:
40+
41+
```
42+
yarn install
43+
```
44+
45+
### Setting up a server
46+
47+
For simplicity, a GraphQL Serve in-memory server has been provided. You can make changes to the GrapQL schema, by editing the `models/runtime.graphql` file. To start the server, run the following
48+
command:
49+
50+
```
51+
yarn startServer
52+
```
53+
54+
Alternatively, you can implement your own backend server.
55+
56+
### Starting the client
57+
58+
Next, configure the GraphQL server address in the `src/clientConfig.js` file:
59+
60+
```
61+
62+
...
63+
64+
const wsLink = new WebSocketLink({
65+
uri: 'ws://<YOUR-SERVER-ADDRESS-HERE>',
66+
...
67+
});
68+
69+
const httpLink = new HttpLink({
70+
uri: 'http://<YOUR-SERVER-ADDRESS-HERE>',
71+
});
72+
73+
...
74+
75+
```
76+
77+
### Starting the client
78+
79+
Lastly, run the following commands from the React example folder.
80+
81+
```
82+
yarn start
83+
```
84+
85+
## Adding more models
86+
87+
1. Edit runtime.graphql file in `src/model/runtime.graphql`
88+
2. Generate models yarn generate
89+
3. Review new models
90+
91+
## Running as native capacitor application
92+
93+
yarn build
94+
yarn cap add ios
95+
yarn cap copy ios
96+
yarn cap open ios
97+
98+
yarn build
99+
yarn cap add android
100+
// Swap main activity https://github.com/capacitor-community/sqlite
101+
yarn cap copy android
102+
yarn cap open android

examples/vue-datastore/index.html

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" href="/favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Vite App</title>
8+
</head>
9+
<body>
10+
<div id="app"></div>
11+
<script type="module" src="/src/main.ts"></script>
12+
</body>
13+
</html>

examples/vue-datastore/package.json

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"name": "vue-datastore",
3+
"version": "0.0.0",
4+
"scripts": {
5+
"dev": "vite",
6+
"build": "vite build",
7+
"serve": "vite preview",
8+
"upgrade-next": "yarn yarn-upgrade-all add vue@next ant-design-vue@next",
9+
"generate": "offix generate --schema ./src/model/runtime.graphql --outputPath ./src/datastore/generated",
10+
"startServer": "gqlserve serve --datasync --conflict=clientSideWins --port=5400 ./src/model/runtime.graphql",
11+
"linkdatastore": "cd ../../packages/datastore/datastore && yarn link && cd - && yarn link offix-datastore && rm -Rf ./node_modules/react && && rm -Rf ./node_modules/react-dom",
12+
"linkdatastorecli": "cd ../../packages/datastore/cli && yarn link && cd - && yarn link @offix/cli"
13+
},
14+
"browserslist": {
15+
"production": [
16+
">0.2%",
17+
"not dead",
18+
"not op_mini all"
19+
],
20+
"development": [
21+
"last 1 chrome version",
22+
"last 1 firefox version",
23+
"last 1 safari version"
24+
]
25+
},
26+
"dependencies": {
27+
"@ant-design/colors": "^6.0.0",
28+
"ant-design-vue": "^2.0.1",
29+
"offix-datastore": "^0.4.0",
30+
"vue": "^3.0.6",
31+
"@ant-design/icons-vue": "^6.0.1"
32+
},
33+
"devDependencies": {
34+
"@offix/cli": "^0.3.3",
35+
"@types/node": "^14.14.31",
36+
"@vitejs/plugin-vue": "^1.1.4",
37+
"@vitejs/plugin-vue-jsx": "^1.1.2",
38+
"@vue/compiler-sfc": "^3.0.5",
39+
"babel-plugin-import": "^1.13.3",
40+
"eslint": "^7.21.0",
41+
"eslint-plugin-vue": "^7.6.0",
42+
"graphback-cli": "^1.1.2",
43+
"graphql-serve": "1.1.2",
44+
"sass": "^1.32.8",
45+
"typescript": "^4.2.2",
46+
"vite": "^2.0.4",
47+
"yarn-upgrade-all": "^0.5.4"
48+
}
49+
}
4.19 KB
Binary file not shown.

examples/vue-datastore/src/App.vue

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<template>
2+
<Loading v-if="loading" />
3+
<Error v-else-if="error" :message="error.message" />
4+
<div :style="containerStyle" v-else>
5+
<div style="width: 60%">
6+
<a-page-header
7+
:title="isNotToAddView ? 'Offix Todo' : 'Add Todo'"
8+
@back="isNotToAddView ? null : (isToAddView = false)"
9+
>
10+
<template v-slot:extra v-if="isNotToAddView">
11+
<a-button type="primary" @click="isToAddView = true" ghost>
12+
Add Todo
13+
</a-button>
14+
<a-button type="primary" danger ghost>
15+
{{ replicating ? "Online" : "Offline" }}
16+
</a-button>
17+
</template>
18+
<TodoList v-if="isNotToAddView" :todos="data" />
19+
<AddTodo v-else :cancel="cancelAddTodo" />
20+
</a-page-header>
21+
</div>
22+
</div>
23+
</template>
24+
<script lang="ts">
25+
import { NetworkStatusEvent } from "offix-datastore/types/replication/network/NetworkStatus";
26+
import { computed, defineComponent, onMounted, ref, toRefs, watch } from "vue";
27+
import { Error, TodoList } from "./components";
28+
import { datastore } from "./datastore/config";
29+
import { useFindTodos } from "./datastore/hooks";
30+
import Loading from "./components/UI/Loading.vue";
31+
import AddTodo from "./components/forms/AddTodo.vue";
32+
export default defineComponent({
33+
name: "App",
34+
components: {
35+
AddTodo,
36+
Error,
37+
Loading,
38+
TodoList,
39+
},
40+
setup() {
41+
const containerStyle = {
42+
display: "flex",
43+
alignItems: "start",
44+
justifyContent: "center",
45+
minHeight: "100vh",
46+
width: "100vw",
47+
padding: "2em 0",
48+
};
49+
const replicating = ref(false);
50+
const isToAddView = ref(false);
51+
const isNotToAddView = computed(() => !isToAddView.value);
52+
const { state, subscribeToUpdates } = useFindTodos();
53+
const { loading, data, error } = toRefs(state.value);
54+
console.log({ loading, data, error, state });
55+
const startReplication = () => {
56+
datastore.startReplication();
57+
replicating.value = true;
58+
};
59+
onMounted(() => {
60+
startReplication();
61+
datastore.getNetworkIndicator()?.subscribe({
62+
next: (event: NetworkStatusEvent) => {
63+
if (event.isOnline) {
64+
startReplication();
65+
} else {
66+
datastore.stopReplication();
67+
replicating.value = false;
68+
}
69+
},
70+
});
71+
});
72+
watch(
73+
data,
74+
() => {
75+
const subscription = subscribeToUpdates();
76+
return () => subscription.unsubscribe();
77+
},
78+
{ deep: true, immediate: true }
79+
);
80+
const cancelAddTodo = () => (isToAddView.value = false);
81+
return {
82+
containerStyle,
83+
isToAddView,
84+
isNotToAddView,
85+
loading,
86+
replicating,
87+
error,
88+
data,
89+
cancelAddTodo,
90+
};
91+
},
92+
});
93+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { DeleteOutlined, EditOutlined } from "@ant-design/icons-vue";
2+
import { defineComponent, h, ref } from "@vue/runtime-core";
3+
import { PropType } from "vue";
4+
import { useDeleteTodo } from "../../datastore/hooks";
5+
import EditTodo from "../forms/EditTodo.vue";
6+
import ToggleTodo from "../forms/ToggleTodo.vue";
7+
import { Todo } from "/@/datastore/generated";
8+
export const TodoItem = defineComponent({
9+
props: {
10+
todo: {
11+
type: Object as PropType<Todo>,
12+
required: true,
13+
},
14+
},
15+
components: {
16+
ToggleTodo,
17+
EditTodo,
18+
},
19+
setup(props) {
20+
const { remove: deleteTodo } = useDeleteTodo();
21+
const edit = ref(false);
22+
const handleDelete = () => {
23+
deleteTodo({ _id: props.todo._id })
24+
.then((res) => console.log("response", res))
25+
.catch((error: any) => console.log(error));
26+
};
27+
28+
return () =>
29+
h(
30+
edit.value ? (
31+
<edit-todo
32+
todo={props.todo}
33+
toggleEdit={() => (edit.value = !edit.value)}
34+
/>
35+
) : (
36+
<a-row justify="space-between">
37+
<a-col>
38+
<toggle-todo todo={props.todo} />
39+
<p>
40+
<b>Description: </b>
41+
<br />
42+
{props.todo.description}
43+
</p>
44+
</a-col>
45+
<a-col>
46+
<a-button type="primary" onClick={() => (edit.value = true)}>
47+
<EditOutlined />
48+
</a-button>
49+
<a-button type="primary" onClick={handleDelete} danger>
50+
<DeleteOutlined />
51+
</a-button>
52+
</a-col>
53+
</a-row>
54+
)
55+
);
56+
},
57+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { computed, defineComponent, h, PropType } from "vue";
2+
import { Todo } from "../../datastore/generated";
3+
import { Empty } from "../UI";
4+
import { TodoItem } from "./TodoItem";
5+
6+
export const TodoList = defineComponent({
7+
props: {
8+
todos: {
9+
type: Array as PropType<Todo[]>,
10+
required: true,
11+
default: () => [],
12+
},
13+
},
14+
components: {
15+
TodoItem,
16+
Empty,
17+
},
18+
setup(props) {
19+
const noTodos = computed(() => !props.todos || props.todos.length === 0);
20+
return () =>
21+
h("div", {}, [
22+
noTodos.value ? h(<empty />) : null,
23+
...props.todos.map((todo) =>
24+
h(
25+
<a-card key={todo._id} style='margin: "0.5em 0"'>
26+
<todo-item todo={todo} />
27+
</a-card>
28+
)
29+
),
30+
]);
31+
},
32+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from "./TodoItem";
2+
export * from "./TodoList";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//@ts-nocheck //FIXME: remove ignore
2+
import { defineComponent, h } from "@vue/runtime-core";
3+
4+
export const Empty = defineComponent({
5+
setup() {
6+
return () =>
7+
h(
8+
<div class="empty" style={{ background: "#fff" }}>
9+
<div class="empty-icon">
10+
<i class="icon icon-3x icon-flag" />
11+
</div>
12+
<p class="empty-title h5">You have no todo items</p>
13+
<p class="empty-subtitle">Click the button to create a new task</p>
14+
</div>
15+
);
16+
}
17+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { defineComponent, h } from "vue";
2+
3+
export const Error = defineComponent({
4+
name: "Error",
5+
props: {
6+
message: {
7+
type: String,
8+
required: false,
9+
default: "",
10+
},
11+
},
12+
setup(props) {
13+
return () =>
14+
h(
15+
<a-result
16+
status="error"
17+
title="Oops, it looks like there was an error!"
18+
subTitle={props.message}
19+
/>
20+
);
21+
},
22+
});

0 commit comments

Comments
 (0)