diff --git a/.parcelrc b/.parcelrc
new file mode 100644
index 0000000..1f3df89
--- /dev/null
+++ b/.parcelrc
@@ -0,0 +1,4 @@
+{
+ "extends": ["@parcel/config-default"],
+ "reporters": ["...", "parcel-reporter-static-files-copy"]
+}
diff --git a/README.md b/README.md
index a5131b2..50c55c1 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,13 @@ Crafted with love and care to provide the best experience possible.
## Self-host using Docker
```
-docker run --name chatpad -d -p 1234:80 ghcr.io/deiucanta/chatpad:latest
+docker run --name chatpad -d -p 8080:80 ghcr.io/deiucanta/chatpad:latest
+```
+
+## Self-host using Docker with custom config
+
+```
+docker run --name chatpad -d -v `pwd`/config.json:/usr/share/nginx/html/config.json -p 8080:80 ghcr.io/deiucanta/chatpad:latest
```
## One click Deployments
diff --git a/package-lock.json b/package-lock.json
index 8a3c8b8..742a0b1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -44,7 +44,7 @@
"@types/react-dom": "^18.0.11",
"buffer": "^5.7.1",
"parcel": "^2.8.3",
- "path-browserify": "^1.0.1",
+ "parcel-reporter-static-files-copy": "^1.5.0",
"process": "^0.11.10"
}
},
@@ -6776,6 +6776,18 @@
"url": "https://opencollective.com/parcel"
}
},
+ "node_modules/parcel-reporter-static-files-copy": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/parcel-reporter-static-files-copy/-/parcel-reporter-static-files-copy-1.5.0.tgz",
+ "integrity": "sha512-dsY3MQkbYSgEqS0/22vtD2mZtel8UC0ItH0ok8LmgFeCMTsdhyOtJgvt945ODIzu9lYc/sCIzksM8C77uSE3Fg==",
+ "dev": true,
+ "dependencies": {
+ "@parcel/plugin": "^2.0.0-beta.1"
+ },
+ "engines": {
+ "parcel": "^2.0.0-beta.1"
+ }
+ },
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -12924,6 +12936,15 @@
"v8-compile-cache": "^2.0.0"
}
},
+ "parcel-reporter-static-files-copy": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/parcel-reporter-static-files-copy/-/parcel-reporter-static-files-copy-1.5.0.tgz",
+ "integrity": "sha512-dsY3MQkbYSgEqS0/22vtD2mZtel8UC0ItH0ok8LmgFeCMTsdhyOtJgvt945ODIzu9lYc/sCIzksM8C77uSE3Fg==",
+ "dev": true,
+ "requires": {
+ "@parcel/plugin": "^2.0.0-beta.1"
+ }
+ },
"parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
diff --git a/package.json b/package.json
index c104ce8..93dd9e0 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,9 @@
"start": "parcel",
"build": "parcel build"
},
+ "staticFiles": {
+ "staticPath": "src/static"
+ },
"devDependencies": {
"@parcel/transformer-sass": "^2.8.3",
"@types/downloadjs": "^1.4.3",
@@ -16,6 +19,7 @@
"buffer": "^5.7.1",
"parcel": "^2.8.3",
"path-browserify": "^1.0.1",
+ "parcel-reporter-static-files-copy": "^1.5.0",
"process": "^0.11.10"
},
"dependencies": {
diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx
index beb7f61..3c39330 100644
--- a/src/components/Layout.tsx
+++ b/src/components/Layout.tsx
@@ -40,6 +40,7 @@ import { DatabaseModal } from "./DatabaseModal";
import { LogoText } from "./Logo";
import { Prompts } from "./Prompts";
import { SettingsModal } from "./SettingsModal";
+import { config } from "../utils/config";
declare global {
interface Window {
@@ -186,35 +187,41 @@ export function Layout() {
-
- toggleColorScheme()}
+ {config.allowDarkModeToggle && (
+
- {colorScheme === "dark" ? (
-
- ) : (
-
- )}
-
-
-
-
-
-
+ toggleColorScheme()}
+ >
+ {colorScheme === "dark" ? (
+
+ ) : (
+
+ )}
-
-
-
-
-
-
-
-
+ )}
+ {config.allowSettingsModal && (
+
+
+
+
+
+
+
+ )}
+ {config.allowDatabaseModal && (
+
+
+
+
+
+
+
+ )}
-
-
-
-
-
-
- {
- if (window.todesktop) {
- event.preventDefault();
- window.todesktop.contents.openUrlInBrowser(
- "https://feedback.chatpad.ai"
- );
- }
- }}
- target="_blank"
- sx={{ flex: 1 }}
- size="xl"
- >
-
-
-
+ {config.showTwitterLink && (
+
+
+
+
+
+ )}
+ {config.showFeedbackLink && (
+
+ {
+ if (window.todesktop) {
+ event.preventDefault();
+ window.todesktop.contents.openUrlInBrowser(
+ "https://feedback.chatpad.ai"
+ );
+ }
+ }}
+ target="_blank"
+ sx={{ flex: 1 }}
+ size="xl"
+ >
+
+
+
+ )}
diff --git a/src/components/SettingsModal.tsx b/src/components/SettingsModal.tsx
index 4a1fc0c..824263c 100644
--- a/src/components/SettingsModal.tsx
+++ b/src/components/SettingsModal.tsx
@@ -6,6 +6,7 @@ import {
List,
Modal,
PasswordInput,
+ TextInput,
Select,
Stack,
Text,
@@ -15,7 +16,7 @@ import { notifications } from "@mantine/notifications";
import { useLiveQuery } from "dexie-react-hooks";
import { cloneElement, ReactElement, useEffect, useState } from "react";
import { db } from "../db";
-import { availableModels, defaultModel } from "../utils/constants";
+import { config } from "../utils/config";
import { checkOpenAIKey } from "../utils/openai";
export function SettingsModal({ children }: { children: ReactElement }) {
@@ -23,7 +24,11 @@ export function SettingsModal({ children }: { children: ReactElement }) {
const [submitting, setSubmitting] = useState(false);
const [value, setValue] = useState("");
- const [model, setModel] = useState(defaultModel);
+ const [model, setModel] = useState(config.defaultModel);
+ const [type, setType] = useState(config.defaultType);
+ const [auth, setAuth] = useState(config.defaultAuth);
+ const [base, setBase] = useState("");
+ const [version, setVersion] = useState("");
const settings = useLiveQuery(async () => {
return db.settings.where({ id: "general" }).first();
@@ -36,6 +41,18 @@ export function SettingsModal({ children }: { children: ReactElement }) {
if (settings?.openAiModel) {
setModel(settings.openAiModel);
}
+ if (settings?.openAiApiType) {
+ setType(settings.openAiApiType);
+ }
+ if (settings?.openAiApiAuth) {
+ setAuth(settings.openAiApiAuth);
+ }
+ if (settings?.openAiApiBase) {
+ setBase(settings.openAiApiBase);
+ }
+ if (settings?.openAiApiVersion) {
+ setVersion(settings.openAiApiVersion);
+ }
}, [settings]);
return (
@@ -111,20 +128,213 @@ export function SettingsModal({ children }: { children: ReactElement }) {