merge
This commit is contained in:
commit
d0eb8c38c5
30
README.md
30
README.md
|
@ -20,7 +20,7 @@
|
|||
|
||||
|
||||
<p align="center">
|
||||
<img src="https://i.imgur.com/tMCahK8.png">
|
||||
<img src="https://i.imgur.com/tPQHruf.png">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
@ -69,17 +69,10 @@ When other platforms chose the closed source route, we decided to go open source
|
|||
|
||||
- **Cloud hosting and self-hosting.** Users can self-host (see below), or host their apps with Budibase. Currently, our cloud hosting offering is limited to the free tier but we aim to change this in the future. For heavy usage, we advise users to self-host.
|
||||
|
||||
|
||||
## 🤖 Self-hosting
|
||||
|
||||
<p align="center">
|
||||
<img src="https://i.imgur.com/Z52cEvT.png?1" />
|
||||
<img alt="Budibase design ui" src="https://imgur.com/v8m6v3q.png">
|
||||
</p>
|
||||
|
||||
Budibase wants to make sure anyone can use the tools we develop and we know a lot of people need to be able to host the apps they make on their own systems - that is why we've decided to try and make self hosting as easy as possible!
|
||||
|
||||
Currently, you can host your apps using Docker. The documentation for self-hosting can be found [here](https://docs.budibase.com/self-hosting/introduction-to-self-hosting).
|
||||
|
||||
|
||||
## ⌛ Status
|
||||
- [x] Alpha: We are demoing Budibase to users and receiving feedback
|
||||
|
@ -95,10 +88,6 @@ Watch "releases" of this repo to get notified of major updates, and give the sta
|
|||
|
||||
If you are having issues between updates of the builder, please use the guide [here](https://github.com/Budibase/budibase/blob/master/CONTRIBUTING.md#troubleshooting) to clear down your environment.
|
||||
|
||||
## Roadmap
|
||||
|
||||
Checkout our [Public Roadmap](https://github.com/Budibase/budibase/projects/10). If you would like to discuss some of the items on the roadmap, please feel to reach out on [Discord](https://discord.gg/rCYayfe), or via [Github discussions](https://github.com/Budibase/budibase/discussions)
|
||||
|
||||
|
||||
## 🏁 Getting Started with Budibase
|
||||
|
||||
|
@ -111,10 +100,17 @@ The Budibase builder runs in Electron, on Mac, PC and Linux. Follow the steps be
|
|||
|
||||
[Here is a guided tutorial](https://docs.budibase.com/tutorial/tutorial-signing-up) if you need extra help.
|
||||
|
||||
|
||||
## 🤖 Self-hosting
|
||||
|
||||
<p align="center">
|
||||
<img alt="Budibase design ui" src="https://imgur.com/v8m6v3q.png">
|
||||
<img src="https://i.imgur.com/Z52cEvT.png?1" />
|
||||
</p>
|
||||
|
||||
Budibase wants to make sure anyone can use the tools we develop and we know a lot of people need to be able to host the apps they make on their own systems - that is why we've decided to try and make self hosting as easy as possible!
|
||||
|
||||
Currently, you can host your apps using Docker. The documentation for self-hosting can be found [here](https://docs.budibase.com/self-hosting/introduction-to-self-hosting).
|
||||
|
||||
|
||||
## 🎓 Learning Budibase
|
||||
|
||||
|
@ -122,6 +118,12 @@ The Budibase [documentation lives here](https://docs.budibase.com).
|
|||
|
||||
You can also follow a quick tutorial on [how to build a CRM with Budibase](https://docs.budibase.com/tutorial/tutorial-introduction)
|
||||
|
||||
|
||||
## Roadmap
|
||||
|
||||
Checkout our [Public Roadmap](https://github.com/Budibase/budibase/projects/10). If you would like to discuss some of the items on the roadmap, please feel to reach out on [Discord](https://discord.gg/rCYayfe), or via [Github discussions](https://github.com/Budibase/budibase/discussions)
|
||||
|
||||
|
||||
## ❗ Code of Conduct
|
||||
|
||||
Budibase is dedicated to providing a welcoming, diverse, and harrassment-free experience for everyone. We expect everyone in the Budibase community to abide by our [**Code of Conduct**](https://github.com/Budibase/budibase/blob/master/.github/CODE_OF_CONDUCT.md). Please read it.
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
GITHUB_BASE_URL=https://raw.githubusercontent.com/Budibase/budibase/master/hosting
|
||||
|
||||
if ! [ -x "$(command -v wget)" ]; then
|
||||
echo 'Error: wget is not installed. Please install it for your operating system.' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
fetch_config_files() {
|
||||
wget $GITHUB_BASE_URL/docker-compose.yaml
|
||||
wget $GITHUB_BASE_URL/envoy.yaml
|
||||
wget $GITHUB_BASE_URL/hosting.properties
|
||||
wget $GITHUB_BASE_URL/start.sh
|
||||
}
|
||||
|
||||
fetch_config_files
|
||||
|
||||
# Start budibase
|
||||
docker-compose --env-file hosting.properties up -d
|
|
@ -2,6 +2,7 @@ version: "3"
|
|||
|
||||
services:
|
||||
app-service:
|
||||
restart: always
|
||||
image: budibase/budibase-apps
|
||||
ports:
|
||||
- "${APP_PORT}:4002"
|
||||
|
@ -18,6 +19,7 @@ services:
|
|||
- worker-service
|
||||
|
||||
worker-service:
|
||||
restart: always
|
||||
image: budibase/budibase-worker
|
||||
ports:
|
||||
- "${WORKER_PORT}:4003"
|
||||
|
@ -36,6 +38,7 @@ services:
|
|||
- couch-init
|
||||
|
||||
minio-service:
|
||||
restart: always
|
||||
image: minio/minio
|
||||
volumes:
|
||||
- minio_data:/data
|
||||
|
@ -53,6 +56,7 @@ services:
|
|||
retries: 3
|
||||
|
||||
proxy-service:
|
||||
restart: always
|
||||
image: envoyproxy/envoy:v1.16-latest
|
||||
volumes:
|
||||
- ./envoy.yaml:/etc/envoy/envoy.yaml
|
||||
|
@ -66,6 +70,7 @@ services:
|
|||
- couchdb-service
|
||||
|
||||
couchdb-service:
|
||||
restart: always
|
||||
image: apache/couchdb:3.0
|
||||
environment:
|
||||
- COUCHDB_PASSWORD=${COUCH_DB_PASSWORD}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { notificationStore } from "builderStore/store/notifications"
|
||||
import { onMount, onDestroy } from "svelte"
|
||||
import { flip } from 'svelte/animate';
|
||||
import { fly } from "svelte/transition"
|
||||
|
||||
export let themes = {
|
||||
|
@ -27,6 +27,7 @@
|
|||
<div class="notifications">
|
||||
{#each $notificationStore.notifications as notification (notification.id)}
|
||||
<div
|
||||
animate:flip
|
||||
class="toast"
|
||||
style="background: {themes[notification.type]};"
|
||||
transition:fly={{ y: -30 }}>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
"@budibase/string-templates": "^0.5.3",
|
||||
"deep-equal": "^2.0.1",
|
||||
"regexparam": "^1.3.0",
|
||||
"shortid": "^2.2.15",
|
||||
"svelte-spa-router": "^3.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/**
|
||||
* API cache for cached request responses.
|
||||
*/
|
||||
import { notificationStore } from "../store/notification"
|
||||
let cache = {}
|
||||
|
||||
/**
|
||||
|
@ -35,10 +36,12 @@ const makeApiCall = async ({ method, url, body, json = true }) => {
|
|||
case 200:
|
||||
return response.json()
|
||||
case 404:
|
||||
notificationStore.danger("Not found")
|
||||
return handleError(`${url}: Not Found`)
|
||||
case 400:
|
||||
return handleError(`${url}: Bad Request`)
|
||||
case 403:
|
||||
notificationStore.danger("Forbidden")
|
||||
return handleError(`${url}: Forbidden`)
|
||||
default:
|
||||
if (response.status >= 200 && response.status < 400) {
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
import { notificationStore } from "../store/notification"
|
||||
import API from "./api"
|
||||
/**
|
||||
* Executes an automation. Must have "App Action" trigger.
|
||||
*/
|
||||
export const triggerAutomation = async (automationId, fields) => {
|
||||
return await API.post({
|
||||
const res = await API.post({
|
||||
url: `/api/automations/${automationId}/trigger`,
|
||||
body: { fields },
|
||||
})
|
||||
res.error
|
||||
? notificationStore.danger("An error has occurred")
|
||||
: notificationStore.success("Automation triggered")
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
import { notificationStore } from "../store/notification"
|
||||
import API from "./api"
|
||||
|
||||
/**
|
||||
* Executes a query against an external data connector.
|
||||
*/
|
||||
export const executeQuery = async ({ queryId, parameters }) => {
|
||||
const response = await API.post({
|
||||
const res = await API.post({
|
||||
url: `/api/queries/${queryId}`,
|
||||
body: {
|
||||
parameters,
|
||||
},
|
||||
})
|
||||
return response
|
||||
res.error
|
||||
? notificationStore.danger("An error has occurred")
|
||||
: notificationStore.success("Query successful")
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { notificationStore } from "../store/notification"
|
||||
import API from "./api"
|
||||
import { fetchTableDefinition } from "./tables"
|
||||
|
||||
|
@ -15,42 +16,58 @@ export const fetchRow = async ({ tableId, rowId }) => {
|
|||
* Creates a row in a table.
|
||||
*/
|
||||
export const saveRow = async row => {
|
||||
return await API.post({
|
||||
const res = await API.post({
|
||||
url: `/api/${row.tableId}/rows`,
|
||||
body: row,
|
||||
})
|
||||
res.error
|
||||
? notificationStore.danger("An error has occurred")
|
||||
: notificationStore.success("Row saved")
|
||||
return res
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a row in a table.
|
||||
*/
|
||||
export const updateRow = async row => {
|
||||
return await API.patch({
|
||||
const res = await API.patch({
|
||||
url: `/api/${row.tableId}/rows/${row._id}`,
|
||||
body: row,
|
||||
})
|
||||
res.error
|
||||
? notificationStore.danger("An error has occurred")
|
||||
: notificationStore.success("Row updated")
|
||||
return res
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a row from a table.
|
||||
*/
|
||||
export const deleteRow = async ({ tableId, rowId, revId }) => {
|
||||
return await API.del({
|
||||
const res = await API.del({
|
||||
url: `/api/${tableId}/rows/${rowId}/${revId}`,
|
||||
})
|
||||
res.error
|
||||
? notificationStore.danger("An error has occurred")
|
||||
: notificationStore.success("Row deleted")
|
||||
return res
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes many rows from a table.
|
||||
*/
|
||||
export const deleteRows = async ({ tableId, rows }) => {
|
||||
return await API.post({
|
||||
const res = await API.post({
|
||||
url: `/api/${tableId}/rows`,
|
||||
body: {
|
||||
rows,
|
||||
type: "delete",
|
||||
},
|
||||
})
|
||||
res.error
|
||||
? notificationStore.danger("An error has occurred")
|
||||
: notificationStore.success(`${rows.length} row(s) deleted`)
|
||||
return res
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
import { writable } from "svelte/store"
|
||||
import { setContext, onMount } from "svelte"
|
||||
import Component from "./Component.svelte"
|
||||
import NotificationDisplay from './NotificationDisplay.svelte'
|
||||
import SDK from "../sdk"
|
||||
import { createDataStore, initialise, screenStore } from "../store"
|
||||
import { createDataStore, initialise, screenStore, notificationStore } from "../store"
|
||||
|
||||
// Provide contexts
|
||||
setContext("sdk", SDK)
|
||||
|
@ -23,3 +24,4 @@
|
|||
{#if loaded && $screenStore.activeLayout}
|
||||
<Component definition={$screenStore.activeLayout.props} />
|
||||
{/if}
|
||||
<NotificationDisplay />
|
|
@ -0,0 +1,60 @@
|
|||
<script>
|
||||
import { flip } from 'svelte/animate';
|
||||
import { fly } from "svelte/transition"
|
||||
import { getContext } from "svelte"
|
||||
const { notifications } = getContext("sdk")
|
||||
|
||||
export let themes = {
|
||||
danger: "#E26D69",
|
||||
success: "#84C991",
|
||||
warning: "#f0ad4e",
|
||||
info: "#5bc0de",
|
||||
default: "#aaaaaa",
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="notifications">
|
||||
{#each $notifications as notification (notification.id)}
|
||||
<div
|
||||
animate:flip
|
||||
class="toast"
|
||||
style="background: {themes[notification.type]};"
|
||||
transition:fly={{ y: -30 }}>
|
||||
<div class="content">{notification.message}</div>
|
||||
{#if notification.icon}<i class={notification.icon} />{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.notifications {
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.toast {
|
||||
flex: 0 0 auto;
|
||||
margin-bottom: 10px;
|
||||
border-radius: var(--border-radius-s);
|
||||
/* The toasts now support being auto sized, so this static width could be removed */
|
||||
width: 40vw;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 10px;
|
||||
display: block;
|
||||
color: white;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,5 +1,11 @@
|
|||
import * as API from "./api"
|
||||
import { authStore, routeStore, screenStore, bindingStore } from "./store"
|
||||
import {
|
||||
authStore,
|
||||
notificationStore,
|
||||
routeStore,
|
||||
screenStore,
|
||||
bindingStore,
|
||||
} from "./store"
|
||||
import { styleable } from "./utils/styleable"
|
||||
import { linkable } from "./utils/linkable"
|
||||
import DataProvider from "./components/DataProvider.svelte"
|
||||
|
@ -7,6 +13,7 @@ import DataProvider from "./components/DataProvider.svelte"
|
|||
export default {
|
||||
API,
|
||||
authStore,
|
||||
notifications: notificationStore,
|
||||
routeStore,
|
||||
screenStore,
|
||||
styleable,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
export { authStore } from "./auth"
|
||||
export { notificationStore } from "./notification"
|
||||
export { routeStore } from "./routes"
|
||||
export { screenStore } from "./screens"
|
||||
export { builderStore } from "./builder"
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import { writable, derived } from "svelte/store"
|
||||
import { generate } from "shortid"
|
||||
|
||||
const NOTIFICATION_TIMEOUT = 3000
|
||||
|
||||
const createNotificationStore = () => {
|
||||
const _notifications = writable([])
|
||||
|
||||
const send = (message, type = "default") => {
|
||||
_notifications.update(state => {
|
||||
return [...state, { id: generate(), type, message }]
|
||||
})
|
||||
}
|
||||
|
||||
const notifications = derived(_notifications, ($_notifications, set) => {
|
||||
set($_notifications)
|
||||
if ($_notifications.length > 0) {
|
||||
const timeout = setTimeout(() => {
|
||||
_notifications.update(state => {
|
||||
state.shift()
|
||||
return state
|
||||
})
|
||||
set($_notifications)
|
||||
}, NOTIFICATION_TIMEOUT)
|
||||
return () => {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
}
|
||||
})
|
||||
const { subscribe } = notifications
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
send,
|
||||
danger: msg => send(msg, "danger"),
|
||||
warning: msg => send(msg, "warning"),
|
||||
info: msg => send(msg, "info"),
|
||||
success: msg => send(msg, "success"),
|
||||
}
|
||||
}
|
||||
|
||||
export const notificationStore = createNotificationStore()
|
|
@ -1362,6 +1362,11 @@ minimatch@^3.0.4:
|
|||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
nanoid@^2.1.0:
|
||||
version "2.1.11"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.1.11.tgz#ec24b8a758d591561531b4176a01e3ab4f0f0280"
|
||||
integrity sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==
|
||||
|
||||
nwsapi@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
|
||||
|
@ -1803,6 +1808,13 @@ sha.js@^2.4.0, sha.js@^2.4.8:
|
|||
inherits "^2.0.1"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
shortid@^2.2.15:
|
||||
version "2.2.16"
|
||||
resolved "https://registry.yarnpkg.com/shortid/-/shortid-2.2.16.tgz#b742b8f0cb96406fd391c76bfc18a67a57fe5608"
|
||||
integrity sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==
|
||||
dependencies:
|
||||
nanoid "^2.1.0"
|
||||
|
||||
side-channel@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.3.tgz#cdc46b057550bbab63706210838df5d4c19519c3"
|
||||
|
|
|
@ -6240,9 +6240,9 @@ mssql@^6.2.3:
|
|||
tedious "^6.6.2"
|
||||
|
||||
mustache@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.0.1.tgz#d99beb031701ad433338e7ea65e0489416c854a2"
|
||||
integrity sha512-yL5VE97+OXn4+Er3THSmTdCFCtx5hHWzrolvH+JObZnUYwuaG7XV+Ch4fR2cIrcYI0tFHxS7iyFYl14bW8y2sA==
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.1.0.tgz#8c1b042238a982d2eb2d30efc6c14296ae3f699d"
|
||||
integrity sha512-0FsgP/WVq4mKyjolIyX+Z9Bd+3WS8GOwoUTyKXT5cTYMGeauNTi2HPCwERqseC1IHAy0Z7MDZnJBfjabd4O8GQ==
|
||||
|
||||
mute-stream@0.0.8:
|
||||
version "0.0.8"
|
||||
|
|
Loading…
Reference in New Issue