feat: v0.0.10 (#23)

* feat: single SOT for themes + basic custom support

* fix: adjust colors for yuu theme

* feat: Allow loading of environment variables from file (#20)

* feat: allow loading of environment variables from file

* Panic if a file for an environment variable cannot be read

* Use log.Fatalf + os.Exit instead of panic

* fix: remove supurfluous call to os.Exit()

---------

Co-authored-by: adaexec <nixos-git.s1pht@simplelogin.com>
Co-authored-by: Gabe Farrell <90876006+gabehf@users.noreply.github.com>

* chore: add pr test workflow

* chore: changelog

* feat: make all activity grids configurable

* fix: adjust activity grid style

* fix: make background gradient consistent size

* revert: remove year from activity grid opts

* style: adjust top item list min size to 200px

* feat: add support for custom themes

* fix: stabilized the order of top items

* chore: update changelog

* feat: native import & export

* fix: use correct request body for alias requests

* fix: clear input when closing edit modal

* chore: changelog

* docs: make endpoint clearer for some apps

* feat: add ui and handler for export

* fix: fix pr test workflow

---------

Co-authored-by: adaexec <78047743+adaexec@users.noreply.github.com>
Co-authored-by: adaexec <nixos-git.s1pht@simplelogin.com>
This commit is contained in:
Gabe Farrell 2025-06-18 08:48:19 -04:00 committed by GitHub
parent 486f5d0269
commit c16b557c21
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
51 changed files with 1754 additions and 866 deletions

View file

@ -95,11 +95,15 @@ export default function EditModal({ open, setOpen, type, id }: Props) {
}
})
setLoading(false)
}
const handleClose = () => {
setOpen(false)
setInput('')
}
return (
<Modal maxW={1000} isOpen={open} onClose={() => setOpen(false)}>
<Modal maxW={1000} isOpen={open} onClose={handleClose}>
<div className="flex flex-col items-start gap-6 w-full">
<div className="w-full">
<h2>Alias Manager</h2>

View file

@ -0,0 +1,45 @@
import { useState } from "react";
import { AsyncButton } from "../AsyncButton";
import { getExport } from "api/api";
export default function ExportModal() {
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const handleExport = () => {
setLoading(true)
fetch(`/apis/web/v1/export`, {
method: "GET"
})
.then(res => {
if (res.ok) {
res.blob()
.then(blob => {
const url = window.URL.createObjectURL(blob)
const a = document.createElement("a")
a.href = url
a.download = "koito_export.json"
document.body.appendChild(a)
a.click()
a.remove()
window.URL.revokeObjectURL(url)
setLoading(false)
})
} else {
res.json().then(r => setError(r.error))
setLoading(false)
}
}).catch(err => {
setError(err)
setLoading(false)
})
}
return (
<div>
<h2>Export</h2>
<AsyncButton loading={loading} onClick={handleExport}>Export Data</AsyncButton>
{error && <p className="error">{error}</p>}
</div>
)
}

View file

@ -5,6 +5,8 @@ import { ThemeSwitcher } from "../themeSwitcher/ThemeSwitcher";
import ThemeHelper from "../../routes/ThemeHelper";
import { useAppContext } from "~/providers/AppProvider";
import ApiKeysModal from "./ApiKeysModal";
import { AsyncButton } from "../AsyncButton";
import ExportModal from "./ExportModal";
interface Props {
open: boolean
@ -19,7 +21,7 @@ export default function SettingsModal({ open, setOpen } : Props) {
const contentClasses = "w-full px-2 mt-8 sm:mt-0 sm:px-10 overflow-y-auto"
return (
<Modal h={600} isOpen={open} onClose={() => setOpen(false)} maxW={900}>
<Modal h={700} isOpen={open} onClose={() => setOpen(false)} maxW={900}>
<Tabs
defaultValue="Appearance"
orientation="vertical" // still vertical, but layout is responsive via Tailwind
@ -29,9 +31,12 @@ export default function SettingsModal({ open, setOpen } : Props) {
<TabsTrigger className={triggerClasses} value="Appearance">Appearance</TabsTrigger>
<TabsTrigger className={triggerClasses} value="Account">Account</TabsTrigger>
{user && (
<TabsTrigger className={triggerClasses} value="API Keys">
API Keys
</TabsTrigger>
<>
<TabsTrigger className={triggerClasses} value="API Keys">
API Keys
</TabsTrigger>
<TabsTrigger className={triggerClasses} value="Export">Export</TabsTrigger>
</>
)}
</TabsList>
@ -44,6 +49,9 @@ export default function SettingsModal({ open, setOpen } : Props) {
<TabsContent value="API Keys" className={contentClasses}>
<ApiKeysModal />
</TabsContent>
<TabsContent value="Export" className={contentClasses}>
<ExportModal />
</TabsContent>
</Tabs>
</Modal>
)