make it easy to deploy yourself
This commit is contained in:
parent
5ebcbb0ced
commit
17a21a6947
7 changed files with 252 additions and 36 deletions
2
.env
2
.env
|
@ -1 +1,3 @@
|
||||||
|
VITE_APPWRITE_ENDPOINT=https://api.fnukapps.com/v1
|
||||||
|
VITE_APPWRITE_PROJECT_ID=6524683fc8d947fe9a07
|
||||||
VITE_APPWRITE_DB_ID=tehillim-split
|
VITE_APPWRITE_DB_ID=tehillim-split
|
20
README.md
20
README.md
|
@ -3,9 +3,19 @@ This is a web application to split Sefer Tehillim between a group of people. You
|
||||||
|
|
||||||
Currently live at https://tehillim-split.dovicowan.dev
|
Currently live at https://tehillim-split.dovicowan.dev
|
||||||
|
|
||||||
Tehillim Split is build on Appwrite BaaS. Config files and setting your own Appwrite endpoint coming soon, but for now you can set your endpoint in `src/lib/appwrite.js` and your project ID as env `VITE_APPWRITE_DB_ID`.
|
|
||||||
|
|
||||||
Frontend in Svelte, run `npm install` + `npm run dev` to run locally.
|
|
||||||
|
|
||||||
## Github
|
## Github
|
||||||
The Github repo is a mirror of the repo on my self-hosted Git server at https://git.fnukhosting.net/dcowan/tehillim-split.
|
The Github repo is a mirror of the repo on my self-hosted Git server at https://git.fnukhosting.net/dcowan/tehillim-split.
|
||||||
|
|
||||||
|
## Building it yourself
|
||||||
|
Tehillim Split is built on top of Appwrite BaaS and the frontend is Svelte+Vite. To host it yourself, you'll either need your own Appwrite self hosted instance, or you can use [Appwrite Cloud](cloud.appwrite.io).
|
||||||
|
|
||||||
|
### Deploy to Appwrite
|
||||||
|
1. Set up the Appwrite CLI, and connect it to your Appwrite instance with `$ appwrite login`
|
||||||
|
2. Create a new Project with `$ appwrite init project`.
|
||||||
|
3. Deploy the DB with `$ appwrite deploy collection`. Select all Collections.
|
||||||
|
4. Update `VITE_APPWRITE_ENDPOINT` and `VITE_APPWRITE_PROJECT_ID` in `.env`.
|
||||||
|
|
||||||
|
### Deploy frontend
|
||||||
|
`npm install` + `npm run dev` / `npm run build`.
|
||||||
|
|
||||||
|
**NOTICE:** You need to add a platform from the Appwrite Console when deploying to production, otherwise you'll get a CORS error. Wildcards are not supported in the Hostname field.
|
170
appwrite.json
Normal file
170
appwrite.json
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
{
|
||||||
|
"projectId": "6524683fc8d947fe9a07",
|
||||||
|
"projectName": "Tehillim Split",
|
||||||
|
"databases": [
|
||||||
|
{
|
||||||
|
"$id": "tehillim-split",
|
||||||
|
"name": "tehillim-split",
|
||||||
|
"$createdAt": "2023-10-11T14:08:05.106+00:00",
|
||||||
|
"$updatedAt": "2023-10-11T14:08:05.106+00:00",
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"collections": [
|
||||||
|
{
|
||||||
|
"$id": "lists",
|
||||||
|
"$permissions": [
|
||||||
|
"create(\"users\")"
|
||||||
|
],
|
||||||
|
"databaseId": "tehillim-split",
|
||||||
|
"name": "Lists",
|
||||||
|
"enabled": true,
|
||||||
|
"documentSecurity": true,
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"key": "title",
|
||||||
|
"type": "string",
|
||||||
|
"status": "available",
|
||||||
|
"error": "",
|
||||||
|
"required": true,
|
||||||
|
"array": false,
|
||||||
|
"size": 1000,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "require_logged_in",
|
||||||
|
"type": "boolean",
|
||||||
|
"status": "available",
|
||||||
|
"error": "",
|
||||||
|
"required": false,
|
||||||
|
"array": false,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "owner_id",
|
||||||
|
"type": "string",
|
||||||
|
"status": "available",
|
||||||
|
"error": "",
|
||||||
|
"required": true,
|
||||||
|
"array": false,
|
||||||
|
"size": 40,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "list_type",
|
||||||
|
"type": "string",
|
||||||
|
"status": "available",
|
||||||
|
"error": "",
|
||||||
|
"required": true,
|
||||||
|
"array": false,
|
||||||
|
"elements": [
|
||||||
|
"perakim",
|
||||||
|
"month"
|
||||||
|
],
|
||||||
|
"format": "enum",
|
||||||
|
"default": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
{
|
||||||
|
"key": "require_logged_in",
|
||||||
|
"type": "key",
|
||||||
|
"status": "available",
|
||||||
|
"error": "",
|
||||||
|
"attributes": [
|
||||||
|
"require_logged_in"
|
||||||
|
],
|
||||||
|
"orders": [
|
||||||
|
"ASC"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$id": "perakim",
|
||||||
|
"$permissions": [
|
||||||
|
"create(\"users\")",
|
||||||
|
"read(\"users\")"
|
||||||
|
],
|
||||||
|
"databaseId": "tehillim-split",
|
||||||
|
"name": "Perakim",
|
||||||
|
"enabled": true,
|
||||||
|
"documentSecurity": true,
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"key": "list_id",
|
||||||
|
"type": "string",
|
||||||
|
"status": "available",
|
||||||
|
"error": "",
|
||||||
|
"required": true,
|
||||||
|
"array": false,
|
||||||
|
"size": 50,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "perek",
|
||||||
|
"type": "integer",
|
||||||
|
"status": "available",
|
||||||
|
"error": "",
|
||||||
|
"required": true,
|
||||||
|
"array": false,
|
||||||
|
"min": 1,
|
||||||
|
"max": 150,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "taken",
|
||||||
|
"type": "boolean",
|
||||||
|
"status": "available",
|
||||||
|
"error": "",
|
||||||
|
"required": false,
|
||||||
|
"array": false,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "completed",
|
||||||
|
"type": "boolean",
|
||||||
|
"status": "available",
|
||||||
|
"error": "",
|
||||||
|
"required": false,
|
||||||
|
"array": false,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "taken_by",
|
||||||
|
"type": "string",
|
||||||
|
"status": "available",
|
||||||
|
"error": "",
|
||||||
|
"required": false,
|
||||||
|
"array": false,
|
||||||
|
"size": 50,
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "taken_by_name",
|
||||||
|
"type": "string",
|
||||||
|
"status": "available",
|
||||||
|
"error": "",
|
||||||
|
"required": false,
|
||||||
|
"array": false,
|
||||||
|
"size": 800,
|
||||||
|
"default": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
{
|
||||||
|
"key": "list_id",
|
||||||
|
"type": "key",
|
||||||
|
"status": "available",
|
||||||
|
"error": "",
|
||||||
|
"attributes": [
|
||||||
|
"list_id"
|
||||||
|
],
|
||||||
|
"orders": [
|
||||||
|
"ASC"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -4,8 +4,8 @@ import { navigate } from 'svelte-navigator';
|
||||||
const appwrite = new Client();
|
const appwrite = new Client();
|
||||||
|
|
||||||
appwrite
|
appwrite
|
||||||
.setEndpoint("https://api.fnukapps.com/v1")
|
.setEndpoint(import.meta.env.VITE_APPWRITE_ENDPOINT)
|
||||||
.setProject("6524683fc8d947fe9a07")
|
.setProject(import.meta.env.VITE_APPWRITE_PROJECT_ID)
|
||||||
|
|
||||||
|
|
||||||
export const account = new Account(appwrite);
|
export const account = new Account(appwrite);
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
database
|
database
|
||||||
.createDocument("tehillim-split", "lists", ID.unique(), {
|
.createDocument(import.meta.env.VITE_APPWRITE_DB_ID, "lists", ID.unique(), {
|
||||||
title: listname,
|
title: listname,
|
||||||
require_logged_in: !!requireLoggedIn,
|
require_logged_in: !!requireLoggedIn,
|
||||||
owner_id: loggedInUser["$id"],
|
owner_id: loggedInUser["$id"],
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
|
|
||||||
database
|
database
|
||||||
.updateDocument(
|
.updateDocument(
|
||||||
"tehillim-split",
|
import.meta.env.VITE_APPWRITE_DB_ID,
|
||||||
"lists",
|
"lists",
|
||||||
r["$id"],
|
r["$id"],
|
||||||
{},
|
{},
|
||||||
|
|
|
@ -12,7 +12,11 @@
|
||||||
|
|
||||||
export let id;
|
export let id;
|
||||||
|
|
||||||
let list = database.getDocument("tehillim-split", "lists", id);
|
let list = database.getDocument(
|
||||||
|
import.meta.env.VITE_APPWRITE_DB_ID,
|
||||||
|
"lists",
|
||||||
|
id,
|
||||||
|
);
|
||||||
let members = teams.listMemberships(id);
|
let members = teams.listMemberships(id);
|
||||||
|
|
||||||
const rolesIndex = (user, role) => {
|
const rolesIndex = (user, role) => {
|
||||||
|
@ -42,7 +46,10 @@
|
||||||
email,
|
email,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
window.location.protocol + "//" + window.location.host + "/accept_list_invitation",
|
window.location.protocol +
|
||||||
|
"//" +
|
||||||
|
window.location.host +
|
||||||
|
"/accept_list_invitation",
|
||||||
)
|
)
|
||||||
.then(() => getData());
|
.then(() => getData());
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,11 @@
|
||||||
|
|
||||||
let elementsNumbers = 0;
|
let elementsNumbers = 0;
|
||||||
|
|
||||||
let list = database.getDocument("tehillim-split", "lists", id);
|
let list = database.getDocument(
|
||||||
|
import.meta.env.VITE_APPWRITE_DB_ID,
|
||||||
|
"lists",
|
||||||
|
id,
|
||||||
|
);
|
||||||
|
|
||||||
list.then((r) => {
|
list.then((r) => {
|
||||||
if (r.list_type == "perakim") elementsNumbers = 151;
|
if (r.list_type == "perakim") elementsNumbers = 151;
|
||||||
|
@ -17,7 +21,9 @@
|
||||||
});
|
});
|
||||||
let perakim = [];
|
let perakim = [];
|
||||||
let perakimPromise = database
|
let perakimPromise = database
|
||||||
.listDocuments("tehillim-split", "perakim", [Query.equal("list_id", [id])])
|
.listDocuments(import.meta.env.VITE_APPWRITE_DB_ID, "perakim", [
|
||||||
|
Query.equal("list_id", [id]),
|
||||||
|
])
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
perakim = r.documents;
|
perakim = r.documents;
|
||||||
});
|
});
|
||||||
|
@ -43,7 +49,7 @@
|
||||||
console.log(perek);
|
console.log(perek);
|
||||||
database
|
database
|
||||||
.createDocument(
|
.createDocument(
|
||||||
"tehillim-split",
|
import.meta.env.VITE_APPWRITE_DB_ID,
|
||||||
"perakim",
|
"perakim",
|
||||||
ID.unique(),
|
ID.unique(),
|
||||||
{
|
{
|
||||||
|
@ -60,7 +66,7 @@
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
perakimPromise = database
|
perakimPromise = database
|
||||||
.listDocuments("tehillim-split", "perakim", [
|
.listDocuments(import.meta.env.VITE_APPWRITE_DB_ID, "perakim", [
|
||||||
Query.equal("list_id", [id]),
|
Query.equal("list_id", [id]),
|
||||||
])
|
])
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
|
@ -74,18 +80,23 @@
|
||||||
|
|
||||||
if (newTitle !== "") {
|
if (newTitle !== "") {
|
||||||
database
|
database
|
||||||
.updateDocument("tehillim-split", "lists", id, {
|
.updateDocument(import.meta.env.VITE_APPWRITE_DB_ID, "lists", id, {
|
||||||
title: newTitle,
|
title: newTitle,
|
||||||
})
|
})
|
||||||
.then(
|
.then(
|
||||||
() => (list = database.getDocument("tehillim-split", "lists", id)),
|
() =>
|
||||||
|
(list = database.getDocument(
|
||||||
|
import.meta.env.VITE_APPWRITE_DB_ID,
|
||||||
|
"lists",
|
||||||
|
id,
|
||||||
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteList() {
|
function deleteList() {
|
||||||
database
|
database
|
||||||
.deleteDocument("tehillim-split", "lists", id)
|
.deleteDocument(import.meta.env.VITE_APPWRITE_DB_ID, "lists", id)
|
||||||
.then(() => teams.delete(id).then(() => navigate("/", {})));
|
.then(() => teams.delete(id).then(() => navigate("/", {})));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,12 +104,17 @@
|
||||||
let perekDBId = perakim[perekIndex(perek)]["$id"];
|
let perekDBId = perakim[perekIndex(perek)]["$id"];
|
||||||
|
|
||||||
database
|
database
|
||||||
.updateDocument("tehillim-split", "perakim", perekDBId, {
|
.updateDocument(
|
||||||
completed: true,
|
import.meta.env.VITE_APPWRITE_DB_ID,
|
||||||
})
|
"perakim",
|
||||||
|
perekDBId,
|
||||||
|
{
|
||||||
|
completed: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
perakimPromise = database
|
perakimPromise = database
|
||||||
.listDocuments("tehillim-split", "perakim", [
|
.listDocuments(import.meta.env.VITE_APPWRITE_DB_ID, "perakim", [
|
||||||
Query.equal("list_id", [id]),
|
Query.equal("list_id", [id]),
|
||||||
])
|
])
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
|
@ -111,12 +127,17 @@
|
||||||
let perekDBId = perakim[perekIndex(perek)]["$id"];
|
let perekDBId = perakim[perekIndex(perek)]["$id"];
|
||||||
|
|
||||||
database
|
database
|
||||||
.updateDocument("tehillim-split", "perakim", perekDBId, {
|
.updateDocument(
|
||||||
completed: false,
|
import.meta.env.VITE_APPWRITE_DB_ID,
|
||||||
})
|
"perakim",
|
||||||
|
perekDBId,
|
||||||
|
{
|
||||||
|
completed: false,
|
||||||
|
},
|
||||||
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
perakimPromise = database
|
perakimPromise = database
|
||||||
.listDocuments("tehillim-split", "perakim", [
|
.listDocuments(import.meta.env.VITE_APPWRITE_DB_ID, "perakim", [
|
||||||
Query.equal("list_id", [id]),
|
Query.equal("list_id", [id]),
|
||||||
])
|
])
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
|
@ -128,15 +149,17 @@
|
||||||
function untakePerek(perek) {
|
function untakePerek(perek) {
|
||||||
let perekDBId = perakim[perekIndex(perek)]["$id"];
|
let perekDBId = perakim[perekIndex(perek)]["$id"];
|
||||||
|
|
||||||
database.deleteDocument("tehillim-split", "perakim", perekDBId).then(() => {
|
database
|
||||||
perakimPromise = database
|
.deleteDocument(import.meta.env.VITE_APPWRITE_DB_ID, "perakim", perekDBId)
|
||||||
.listDocuments("tehillim-split", "perakim", [
|
.then(() => {
|
||||||
Query.equal("list_id", [id]),
|
perakimPromise = database
|
||||||
])
|
.listDocuments(import.meta.env.VITE_APPWRITE_DB_ID, "perakim", [
|
||||||
.then((r) => {
|
Query.equal("list_id", [id]),
|
||||||
perakim = r.documents;
|
])
|
||||||
});
|
.then((r) => {
|
||||||
});
|
perakim = r.documents;
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -149,7 +172,11 @@
|
||||||
Loading...
|
Loading...
|
||||||
{:then list}
|
{:then list}
|
||||||
<h1 class="text-2xl">List {list.title}</h1>
|
<h1 class="text-2xl">List {list.title}</h1>
|
||||||
<p>List split by {list.list_type=="perakim"?"perek":""}{list.list_type=="month"?"days of month":""}</p>
|
<p>
|
||||||
|
List split by {list.list_type == "perakim"
|
||||||
|
? "perek"
|
||||||
|
: ""}{list.list_type == "month" ? "days of month" : ""}
|
||||||
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<Link class="text-blue-400" to="/list/{id}/members">Members</Link>
|
<Link class="text-blue-400" to="/list/{id}/members">Members</Link>
|
||||||
{#await teamDetails then team}
|
{#await teamDetails then team}
|
||||||
|
|
Loading…
Reference in a new issue