Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dab394d3c4 |
@@ -1,10 +0,0 @@
|
|||||||
version = 1
|
|
||||||
|
|
||||||
[[analyzers]]
|
|
||||||
name = "javascript"
|
|
||||||
|
|
||||||
[analyzers.meta]
|
|
||||||
plugins = ["react"]
|
|
||||||
|
|
||||||
[[transformers]]
|
|
||||||
name = "prettier"
|
|
||||||
@@ -2,12 +2,5 @@ Dockerfile
|
|||||||
.dockerignore
|
.dockerignore
|
||||||
node_modules
|
node_modules
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
*.md
|
README.md
|
||||||
.git
|
.git
|
||||||
.github
|
|
||||||
LICENSE
|
|
||||||
docs/
|
|
||||||
*.sqlite
|
|
||||||
*.env
|
|
||||||
.env
|
|
||||||
.next/standalone/.env
|
|
||||||
19
.env.example
@@ -1,19 +0,0 @@
|
|||||||
DATABASE_URL="file:./database/db.sqlite"
|
|
||||||
|
|
||||||
# Next Auth
|
|
||||||
# You can generate a new secret on the command line with:
|
|
||||||
# openssl rand -base64 32
|
|
||||||
# https://next-auth.js.org/configuration/options#secret
|
|
||||||
AUTH_TRUST_HOST="true"
|
|
||||||
NEXTAUTH_SECRET="anything"
|
|
||||||
|
|
||||||
# Disable analytics
|
|
||||||
NEXT_PUBLIC_DISABLE_ANALYTICS="true"
|
|
||||||
|
|
||||||
DEFAULT_COLOR_SCHEME="light"
|
|
||||||
|
|
||||||
# Unraid API Configuration
|
|
||||||
UNRAID_HOST=192.168.10.20
|
|
||||||
UNRAID_API_KEY=your-api-key-here
|
|
||||||
UNRAID_USE_SSL=false
|
|
||||||
UNRAID_PORT=80
|
|
||||||
2
.eslintignore
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*.js
|
||||||
|
nodes_modules/
|
||||||
32
.eslintrc.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: [
|
||||||
|
'mantine',
|
||||||
|
'plugin:@next/next/recommended',
|
||||||
|
'plugin:jest/recommended',
|
||||||
|
'plugin:storybook/recommended',
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:@typescript-eslint/eslint-recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended"
|
||||||
|
],
|
||||||
|
plugins: ['testing-library', 'jest', 'react-hooks', 'react', 'unused-imports'],
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['**/?(*.)+(spec|test).[jt]s?(x)'],
|
||||||
|
extends: ['plugin:testing-library/react'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
parserOptions: {
|
||||||
|
project: './tsconfig.json',
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'react/react-in-jsx-scope': 'off',
|
||||||
|
'react/no-children-prop': 'off',
|
||||||
|
"unused-imports/no-unused-imports": "warn",
|
||||||
|
"@typescript-eslint/no-unused-vars": "off",
|
||||||
|
"@typescript-eslint/no-unused-imports": "off",
|
||||||
|
"@typescript-eslint/no-unused-expressions": "off",
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/no-shadow": "off",
|
||||||
|
"@typescript-eslint/no-use-before-define": "off",
|
||||||
|
},
|
||||||
|
};
|
||||||
13
.github/FUNDING.yml
vendored
@@ -1,13 +0,0 @@
|
|||||||
# These are supported funding model platforms
|
|
||||||
|
|
||||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
|
||||||
patreon: # Replace with a single Patreon username
|
|
||||||
open_collective: homarr
|
|
||||||
ko_fi: ajnart
|
|
||||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
|
||||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
||||||
liberapay: # Replace with a single Liberapay username
|
|
||||||
issuehunt: # Replace with a single IssueHunt username
|
|
||||||
otechie: # Replace with a single Otechie username
|
|
||||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
|
||||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
||||||
24
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -3,11 +3,6 @@ description: Report something that's broken, or not working like intented!
|
|||||||
title: '<title>'
|
title: '<title>'
|
||||||
labels: ['🐛 Bug']
|
labels: ['🐛 Bug']
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
> [!WARNING]
|
|
||||||
> If you want to report a bug for 1.0, please open it on the new [repository](https://github.com/homarr-labs/homarr/issues/new/choose).
|
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
id: environment
|
id: environment
|
||||||
attributes:
|
attributes:
|
||||||
@@ -37,15 +32,8 @@ body:
|
|||||||
- type: textarea
|
- type: textarea
|
||||||
id: logs
|
id: logs
|
||||||
attributes:
|
attributes:
|
||||||
label: Logs
|
label: Additional info
|
||||||
description: Provide your Homarr logs so we can investigate what's going on
|
description: Logs? Screenshots? More info?
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: context
|
|
||||||
attributes:
|
|
||||||
label: Context
|
|
||||||
description: Screenshots? More info?
|
|
||||||
validations:
|
validations:
|
||||||
required: false
|
required: false
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
@@ -54,11 +42,9 @@ body:
|
|||||||
label: Please tick the boxes
|
label: Please tick the boxes
|
||||||
description: Before submitting, please ensure that
|
description: Before submitting, please ensure that
|
||||||
options:
|
options:
|
||||||
- label: I confirm that I attached the proper logs
|
- label: You've read the [docs](https://github.com/ajnart/homarr#readme)
|
||||||
required: true
|
required: true
|
||||||
- label: I've read the [docs](https://github.com/ajnart/homarr#readme)
|
- label: You've checked for [duplicate issues](https://github.com/ajnart/homarr/issues)
|
||||||
required: true
|
required: true
|
||||||
- label: I've checked for [duplicate issues](https://github.com/ajnart/homarr/issues)
|
- label: You've tried to debug yourself
|
||||||
required: true
|
|
||||||
- label: I've tried to debug myself
|
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
9
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
@@ -3,11 +3,6 @@ description: Request a feature to help improve Homarr!
|
|||||||
title: '<title>'
|
title: '<title>'
|
||||||
labels: ['✨ Feature']
|
labels: ['✨ Feature']
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
> [!WARNING]
|
|
||||||
> If you want to request a feature for 1.0, please open it on the new [repository](https://github.com/homarr-labs/homarr/issues/new/choose).
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: feature
|
id: feature
|
||||||
attributes:
|
attributes:
|
||||||
@@ -33,5 +28,7 @@ body:
|
|||||||
label: Please tick the boxes
|
label: Please tick the boxes
|
||||||
description: Before submitting, please ensure that
|
description: Before submitting, please ensure that
|
||||||
options:
|
options:
|
||||||
- label: You are **NOT** using a version superior to v1. if that is the case, please fill this issue on the new repository.
|
- label: You've read the [docs](https://github.com/ajnart/homarr#readme)
|
||||||
|
required: true
|
||||||
|
- label: You've checked for [duplicate issues](https://github.com/ajnart/homarr/issues)
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
5
.github/ISSUE_TEMPLATE/idea.yml
vendored
@@ -3,11 +3,6 @@ description: Tell us your idea! We may implement it.
|
|||||||
title: '<title>'
|
title: '<title>'
|
||||||
labels: ['🤔 Idea']
|
labels: ['🤔 Idea']
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
> [!WARNING]
|
|
||||||
> If you have an idea for 1.0, please open it on the new [repository](https://github.com/homarr-labs/homarr/issues/new/choose).
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: feature
|
id: feature
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
5
.github/ISSUE_TEMPLATE/module.yml
vendored
@@ -2,11 +2,6 @@ name: 🏗️ Module request
|
|||||||
description: Request for a module to be added / an integration with you favourite service !
|
description: Request for a module to be added / an integration with you favourite service !
|
||||||
title: '<title>'
|
title: '<title>'
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
> [!WARNING]
|
|
||||||
> If you want to request a new integration for 1.0, please open it on the new [repository](https://github.com/homarr-labs/homarr/issues/new/choose).
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: name
|
id: name
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
21
.github/renovate.json
vendored
@@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
||||||
"extends": [
|
|
||||||
"config:base"
|
|
||||||
],
|
|
||||||
"commitMessagePrefix": "⬆️",
|
|
||||||
"dependencyDashboard": true,
|
|
||||||
"prCreation": "approval",
|
|
||||||
"lockFileMaintenance": {
|
|
||||||
"automerge": false
|
|
||||||
},
|
|
||||||
"minor": {
|
|
||||||
"automerge": false
|
|
||||||
},
|
|
||||||
"patch": {
|
|
||||||
"automerge": false
|
|
||||||
},
|
|
||||||
"pin": {
|
|
||||||
"automerge": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
112
.github/workflows/docker.yml
vendored
@@ -1,11 +1,12 @@
|
|||||||
name: Master CI
|
name: Master docker CI
|
||||||
# This workflow uses actions that are not certified by GitHub.
|
# Workflow to build and publish docker image
|
||||||
# They are provided by a third-party and are governed by
|
|
||||||
# separate terms of service, privacy policy, and support
|
|
||||||
# documentation.
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [master]
|
branches: [master]
|
||||||
|
paths-ignore:
|
||||||
|
- '.github/**'
|
||||||
|
- '**.md'
|
||||||
tags:
|
tags:
|
||||||
- v*
|
- v*
|
||||||
|
|
||||||
@@ -16,54 +17,77 @@ env:
|
|||||||
REGISTRY: ghcr.io
|
REGISTRY: ghcr.io
|
||||||
# github.repository as <account>/<repo>
|
# github.repository as <account>/<repo>
|
||||||
IMAGE_NAME: ${{ github.repository }}
|
IMAGE_NAME: ${{ github.repository }}
|
||||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
|
||||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Push image to GitHub Packages.
|
# Push image to GitHub Packages.
|
||||||
# See also https://docs.docker.com/docker-hub/builds/
|
# See also https://docs.docker.com/docker-hub/builds/
|
||||||
yarn_install_and_build:
|
yarn_install_and_build:
|
||||||
|
# Will run yarn install && yarn build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Setup
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Get yarn cache directory path
|
||||||
|
# to help speed up build times
|
||||||
|
id: yarn-cache-dir-path
|
||||||
|
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||||
|
- name: Yarn cache
|
||||||
|
# to help speed up build times
|
||||||
|
uses: actions/cache@v3
|
||||||
|
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
||||||
|
with:
|
||||||
|
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||||
|
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
restore-keys: ${{ runner.os }}-yarn-
|
||||||
|
- name: Nextjs cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
# See here for caching with `yarn` https://github.com/actions/cache/blob/main/examples.md#node---yarn or you can leverage caching with actions/setup-node https://github.com/actions/setup-node
|
||||||
|
path: |
|
||||||
|
~/.npm
|
||||||
|
${{ github.workspace }}/.next/cache
|
||||||
|
# Generate a new cache whenever packages or source files change.
|
||||||
|
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
|
||||||
|
# If source files changed but packages didn't, rebuild from a prior cache.
|
||||||
|
restore-keys: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
|
||||||
|
- run: yarn install --immutable
|
||||||
|
- run: yarn build
|
||||||
|
- name: Cache build output
|
||||||
|
# to copy needed files to docker build job
|
||||||
|
uses: actions/cache@v2
|
||||||
|
id: restore-build
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
./next.config.js
|
||||||
|
./pages/
|
||||||
|
./public/
|
||||||
|
./.next/static/
|
||||||
|
./.next/standalone/
|
||||||
|
./packages.json
|
||||||
|
key: ${{ github.sha }}
|
||||||
|
|
||||||
|
docker_image_build_and_push:
|
||||||
|
needs: [yarn_install_and_build]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
packages: write
|
packages: write
|
||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Setup
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v2
|
||||||
|
- uses: actions/cache@v2
|
||||||
- name: Get yarn cache directory path
|
id: restore-build
|
||||||
id: yarn-cache-dir-path
|
|
||||||
run: echo "::set-output name=dir::$(yarn config get cacheFolder)"
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
id: yarn-cache
|
|
||||||
with:
|
with:
|
||||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
|
||||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-yarn-
|
|
||||||
|
|
||||||
- name: Restore NextJS cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
# See here for caching with `yarn` https://github.com/actions/cache/blob/main/examples.md#node---yarn or you can leverage caching with actions/setup-node https://github.com/actions/setup-node
|
|
||||||
path: |
|
path: |
|
||||||
${{ github.workspace }}/.next/cache
|
./next.config.js
|
||||||
# Generate a new cache whenever packages or source files change.
|
./pages/
|
||||||
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
|
./public/
|
||||||
# If source files changed but packages didn't, rebuild from a prior cache.
|
./.next/static/
|
||||||
restore-keys: |
|
./.next/standalone/
|
||||||
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
|
./packages.json
|
||||||
|
key: ${{ github.sha }}
|
||||||
- run: yarn install
|
|
||||||
|
|
||||||
- run: yarn turbo build
|
|
||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@v4
|
||||||
@@ -74,13 +98,10 @@ jobs:
|
|||||||
tags: |
|
tags: |
|
||||||
type=raw,value=latest
|
type=raw,value=latest
|
||||||
type=pep440,pattern={{version}}
|
type=pep440,pattern={{version}}
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
- name: Login to GHCR
|
- name: Login to GHCR
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
@@ -89,13 +110,10 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v4
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
network: host
|
|
||||||
|
|||||||
106
.github/workflows/docker_dev.yml
vendored
@@ -1,5 +1,8 @@
|
|||||||
name: Development CI
|
name: Development CI
|
||||||
|
# This workflow uses actions that are not certified by GitHub.
|
||||||
|
# They are provided by a third-party and are governed by
|
||||||
|
# separate terms of service, privacy policy, and support
|
||||||
|
# documentation.
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [dev]
|
branches: [dev]
|
||||||
@@ -12,36 +15,21 @@ on:
|
|||||||
- '**.md'
|
- '**.md'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
tag:
|
tags:
|
||||||
required: true
|
required: true
|
||||||
description: 'Tag to deploy to'
|
description: 'Tags to deploy to'
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: ./
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# Use docker.io for Docker Hub if empty
|
# Use docker.io for Docker Hub if empty
|
||||||
REGISTRY: ghcr.io
|
REGISTRY: ghcr.io
|
||||||
# github.repository as <account>/<repo>
|
# github.repository as <account>/<repo>
|
||||||
IMAGE_NAME: ${{ github.repository }}
|
IMAGE_NAME: ${{ github.repository }}
|
||||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
|
||||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read # for checkout repository
|
|
||||||
actions: read # for fetching base branch bundle stats
|
|
||||||
pull-requests: write # for comments
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Push image to GitHub Packages.
|
# Push image to GitHub Packages.
|
||||||
# See also https://docs.docker.com/docker-hub/builds/
|
# See also https://docs.docker.com/docker-hub/builds/
|
||||||
yarn_install_and_build_dev:
|
yarn_install_and_build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
|
||||||
packages: write
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Setup
|
- name: Setup
|
||||||
@@ -52,37 +40,68 @@ jobs:
|
|||||||
|
|
||||||
- name: Get yarn cache directory path
|
- name: Get yarn cache directory path
|
||||||
id: yarn-cache-dir-path
|
id: yarn-cache-dir-path
|
||||||
run: echo "::set-output name=dir::$(yarn config get cacheFolder)"
|
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
- name: Yarn cache
|
||||||
id: yarn-cache
|
uses: actions/cache@v3
|
||||||
|
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
||||||
with:
|
with:
|
||||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||||
restore-keys: |
|
restore-keys: ${{ runner.os }}-yarn-
|
||||||
${{ runner.os }}-yarn-
|
|
||||||
|
|
||||||
- name: Restore next build
|
- name: Nextjs cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v2
|
||||||
id: restore-build-cache
|
|
||||||
env:
|
|
||||||
cache-name: cache-next-build
|
|
||||||
with:
|
with:
|
||||||
path: .next/cache
|
# See here for caching with `yarn` https://github.com/actions/cache/blob/main/examples.md#node---yarn or you can leverage caching with actions/setup-node https://github.com/actions/setup-node
|
||||||
key: ${{ runner.os }}-build-${{ env.cache-name }}
|
path: |
|
||||||
|
~/.npm
|
||||||
|
${{ github.workspace }}/.next/cache
|
||||||
|
# Generate a new cache whenever packages or source files change.
|
||||||
|
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
|
||||||
|
# If source files changed but packages didn't, rebuild from a prior cache.
|
||||||
|
restore-keys: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
|
||||||
|
|
||||||
- run: yarn install
|
- run: yarn install --immutable
|
||||||
|
- run: yarn build
|
||||||
|
|
||||||
- run: yarn turbo build
|
- name: Cache build output
|
||||||
|
uses: actions/cache@v2
|
||||||
|
id: restore-build
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
./next.config.js
|
||||||
|
./pages/
|
||||||
|
./public/
|
||||||
|
./.next/static/
|
||||||
|
./.next/standalone/
|
||||||
|
./packages.json
|
||||||
|
key: ${{ github.sha }}
|
||||||
|
|
||||||
- run: yarn test:coverage
|
docker_image_build_and_push:
|
||||||
|
needs: [yarn_install_and_build]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
|
||||||
- name: Report coverage
|
- name: Checkout
|
||||||
if: always()
|
uses: actions/checkout@v2
|
||||||
uses: davelosert/vitest-coverage-report-action@v2
|
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
id: restore-build
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
./next.config.js
|
||||||
|
./pages/
|
||||||
|
./public/
|
||||||
|
./.next/static/
|
||||||
|
./.next/standalone/
|
||||||
|
./packages.json
|
||||||
|
key: ${{ github.sha }}
|
||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@v4
|
||||||
with:
|
with:
|
||||||
@@ -91,8 +110,7 @@ jobs:
|
|||||||
# generate Docker tags based on the following events/attributes
|
# generate Docker tags based on the following events/attributes
|
||||||
tags: |
|
tags: |
|
||||||
type=ref,event=pr
|
type=ref,event=pr
|
||||||
type=raw,value=${{ github.event.inputs.tag }},enable=${{ github.event.inputs.tag != '' }}
|
tpye=raw,value=dev,priority=1
|
||||||
tpye=raw,value=dev,priority=1,enable=${{ github.event.inputs.tag == '' }}
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v2
|
||||||
@@ -109,14 +127,10 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
if: github.event_name != 'pull_request'
|
uses: docker/build-push-action@v3
|
||||||
uses: docker/build-push-action@v4
|
|
||||||
with:
|
with:
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
context: .
|
context: .
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
network: host
|
|
||||||
|
|||||||
16
.github/workflows/greetings.yml
vendored
@@ -1,16 +0,0 @@
|
|||||||
name: Greetings
|
|
||||||
|
|
||||||
on: [pull_request_target, issues]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
greeting:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/first-interaction@v1
|
|
||||||
with:
|
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
issue-message: "Hi 👋. Thank you for submitting your first issue to Homarr. Please ensure that you've opened this issue on the correct repository. Homarr v1 has been moved to github.com/homarr-labs/homarr "
|
|
||||||
pr-message: "Hi 👋. Thank you for making your first contribution to Homarr. Please ensure that you've completed all the points in the TODO checklist. We'll review your changes shortly."
|
|
||||||
28
.github/workflows/stale.yml
vendored
@@ -1,28 +0,0 @@
|
|||||||
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
|
|
||||||
#
|
|
||||||
# You can adjust the behavior by modifying this file.
|
|
||||||
# For more information, see:
|
|
||||||
# https://github.com/actions/stale
|
|
||||||
name: Mark stale issues and pull requests
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '18 17 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/stale@v5
|
|
||||||
with:
|
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
stale-issue-message: "Hello 👋, this issue has been open for 60 days without activity. We mark issues to help prioritise and close dead issues. Can you confirm that this issue is still relevant on the latest version? I'll remove the stale label as soon as there is further activity on this issue. Thank you 🙏"
|
|
||||||
stale-pr-message: 'Hello 👋, this PR has gone stale. Please reply to mark it as active.'
|
|
||||||
stale-issue-label: 'Stale'
|
|
||||||
stale-pr-label: 'Stale'
|
|
||||||
days-before-close: -1
|
|
||||||
19
.gitignore
vendored
@@ -4,7 +4,6 @@
|
|||||||
/node_modules
|
/node_modules
|
||||||
/.pnp
|
/.pnp
|
||||||
.pnp.js
|
.pnp.js
|
||||||
/cli/node_modules/
|
|
||||||
|
|
||||||
# testing
|
# testing
|
||||||
/coverage
|
/coverage
|
||||||
@@ -26,7 +25,6 @@ yarn-debug.log*
|
|||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
# local env files
|
# local env files
|
||||||
.env
|
|
||||||
.env.local
|
.env.local
|
||||||
.env.development.local
|
.env.development.local
|
||||||
.env.test.local
|
.env.test.local
|
||||||
@@ -34,7 +32,6 @@ yarn-error.log*
|
|||||||
|
|
||||||
# vercel
|
# vercel
|
||||||
.vercel
|
.vercel
|
||||||
.turbo
|
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
|
|
||||||
# storybook
|
# storybook
|
||||||
@@ -50,19 +47,3 @@ data/configs
|
|||||||
!.yarn/releases
|
!.yarn/releases
|
||||||
!.yarn/sdks
|
!.yarn/sdks
|
||||||
!.yarn/versions
|
!.yarn/versions
|
||||||
/cli/.yarn/
|
|
||||||
|
|
||||||
#envfiles
|
|
||||||
.env
|
|
||||||
|
|
||||||
#Languages other than 'en'
|
|
||||||
public/locales/*
|
|
||||||
!public/locales/en
|
|
||||||
|
|
||||||
#database
|
|
||||||
sqlite.db
|
|
||||||
database/*.sqlite
|
|
||||||
WILL_BE_OVERWRITTEN.sqlite
|
|
||||||
|
|
||||||
# IDE
|
|
||||||
.idea/*
|
|
||||||
9
.prettierrc
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 100,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"parser": "typescript",
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"useTabs": false,
|
||||||
|
"endOfLine": "lf"
|
||||||
|
}
|
||||||
30
.storybook/main.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
module.exports = {
|
||||||
|
stories: ['../src/components/**/*.story.mdx', '../src/components/**/*.story.*'],
|
||||||
|
addons: [
|
||||||
|
'@storybook/addon-links',
|
||||||
|
'storybook-addon-mock/register',
|
||||||
|
'@storybook/addon-essentials',
|
||||||
|
],
|
||||||
|
typescript: {
|
||||||
|
check: false,
|
||||||
|
reactDocgen: false,
|
||||||
|
},
|
||||||
|
framework: '@storybook/react',
|
||||||
|
features: { emotionAlias: false },
|
||||||
|
webpackFinal: async (config, { configType }) => {
|
||||||
|
// `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
|
||||||
|
// You can change the configuration based on that.
|
||||||
|
// 'PRODUCTION' is used when building the static version of storybook.
|
||||||
|
|
||||||
|
// https://github.com/polkadot-js/extension/issues/621#issuecomment-759341776
|
||||||
|
// framer-motion uses the .mjs notation and we need to include it so that webpack will
|
||||||
|
// transpile it for us correctly (enables using a CJS module inside an ESM).
|
||||||
|
config.module.rules.push({
|
||||||
|
test: /\.mjs$/,
|
||||||
|
include: /node_modules/,
|
||||||
|
type: 'javascript/auto',
|
||||||
|
});
|
||||||
|
// Return the altered config
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
};
|
||||||
16
.storybook/preview.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { MantineProvider, ColorSchemeProvider } from '@mantine/core';
|
||||||
|
import { NotificationsProvider } from '@mantine/notifications';
|
||||||
|
|
||||||
|
export const parameters = { layout: 'fullscreen' };
|
||||||
|
|
||||||
|
function ThemeWrapper(props: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<ColorSchemeProvider colorScheme="light" toggleColorScheme={() => {}}>
|
||||||
|
<MantineProvider withGlobalStyles withNormalizeCSS>
|
||||||
|
<NotificationsProvider>{props.children}</NotificationsProvider>
|
||||||
|
</MantineProvider>
|
||||||
|
</ColorSchemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const decorators = [(renderStory: Function) => <ThemeWrapper>{renderStory()}</ThemeWrapper>];
|
||||||
28
.vscode/launch.json
vendored
@@ -1,28 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "Next.js: debug server-side",
|
|
||||||
"type": "node-terminal",
|
|
||||||
"request": "launch",
|
|
||||||
"command": "yarn dev"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Next.js: debug client-side",
|
|
||||||
"type": "chrome",
|
|
||||||
"request": "launch",
|
|
||||||
"url": "http://localhost:3000"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Next.js: debug full stack",
|
|
||||||
"type": "node-terminal",
|
|
||||||
"request": "launch",
|
|
||||||
"command": "yarn dev",
|
|
||||||
"serverReadyAction": {
|
|
||||||
"pattern": "started server on .+, url: (https?://.+)",
|
|
||||||
"uriFormat": "%s",
|
|
||||||
"action": "debugWithChrome"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
21
.vscode/settings.json
vendored
@@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"i18n-ally.localesPaths": "public/locales",
|
|
||||||
"i18n-ally.enabledFrameworks": [
|
|
||||||
"react-i18next"
|
|
||||||
],
|
|
||||||
"i18n-ally.namespace": true,
|
|
||||||
"i18n-ally.pathMatcher": "{locale}/{namespaces}.json",
|
|
||||||
"i18n-ally.keystyle": "nested",
|
|
||||||
"i18n-ally.keysInUse": [
|
|
||||||
"modules.**",
|
|
||||||
"layout.manage.navigation.**",
|
|
||||||
],
|
|
||||||
"editor.codeActionsOnSave": {
|
|
||||||
"source.organizeImports": "explicit"
|
|
||||||
},
|
|
||||||
"typescript.tsdk": "node_modules/typescript/lib",
|
|
||||||
"explorer.fileNesting.patterns": {
|
|
||||||
"package.json": "pnpm-lock.yaml, yarn.lock, package-lock.json",
|
|
||||||
"*.tsx": "${capture}.module.css"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
786
.yarn/releases/yarn-3.2.1.cjs
vendored
Normal file
874
.yarn/releases/yarn-3.6.0.cjs
vendored
5
.yarnrc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
yarn-path ".yarn/releases/yarn-1.22.19.cjs"
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
nodeLinker: node-modules
|
nodeLinker: node-modules
|
||||||
|
|
||||||
yarnPath: .yarn/releases/yarn-3.6.0.cjs
|
yarnPath: .yarn/releases/yarn-3.2.1.cjs
|
||||||
|
|||||||
@@ -104,11 +104,3 @@ Enhancement suggestions are tracked as [GitHub issues](https://github.com/ajnart
|
|||||||
Homarr uses [GitMoji](https://gitmoji.dev/).
|
Homarr uses [GitMoji](https://gitmoji.dev/).
|
||||||
We would appreciate it if everyone keeps their commit messages withing these rulings.
|
We would appreciate it if everyone keeps their commit messages withing these rulings.
|
||||||
|
|
||||||
### Tests
|
|
||||||
|
|
||||||
> Components should be tested using unit tests. A unit is the smallest isolated part of the component. Unit tests must not have any dependencies and must be isolated.
|
|
||||||
|
|
||||||
- Place testfiles directly at the root of the unit
|
|
||||||
- Only test a single unit of work inside a unit test
|
|
||||||
- You may test multiple units inside one test file
|
|
||||||
- Testnames do not begin with ``should`` or the unit name
|
|
||||||
72
Dockerfile
@@ -1,64 +1,14 @@
|
|||||||
FROM node:20.2.0-slim
|
FROM node:16-alpine
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Define node.js environment variables
|
|
||||||
ARG PORT=7575
|
|
||||||
|
|
||||||
ENV NEXT_TELEMETRY_DISABLED 1
|
|
||||||
ENV NODE_ENV production
|
ENV NODE_ENV production
|
||||||
ENV NODE_OPTIONS '--no-experimental-fetch'
|
COPY /next.config.js ./
|
||||||
|
COPY /public ./public
|
||||||
COPY next.config.js ./
|
COPY /package.json ./package.json
|
||||||
COPY public ./public
|
# Automatically leverage output traces to reduce image size. https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||||
COPY package.json ./temp_package.json
|
COPY /.next/standalone ./
|
||||||
COPY yarn.lock ./temp_yarn.lock
|
COPY /.next/static ./.next/static
|
||||||
# Automatically leverage output traces to reduce image size
|
EXPOSE 7575
|
||||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
|
||||||
COPY .next/standalone ./
|
|
||||||
COPY .next/static ./.next/static
|
|
||||||
COPY ./scripts/run.sh ./scripts/run.sh
|
|
||||||
RUN chmod +x ./scripts/run.sh
|
|
||||||
COPY ./drizzle ./drizzle
|
|
||||||
|
|
||||||
COPY ./drizzle/migrate ./migrate
|
|
||||||
COPY ./tsconfig.json ./migrate/tsconfig.json
|
|
||||||
COPY ./cli ./cli
|
|
||||||
|
|
||||||
RUN mkdir /data
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
RUN apt update && apt install -y openssl wget
|
|
||||||
|
|
||||||
# Move node_modules to temp location to avoid overwriting
|
|
||||||
RUN mv node_modules _node_modules
|
|
||||||
RUN rm package.json
|
|
||||||
# Install dependencies for migration
|
|
||||||
RUN cp ./migrate/package.json ./package.json
|
|
||||||
RUN yarn
|
|
||||||
# Copy better_sqlite3 build for current platform
|
|
||||||
RUN cp /app/node_modules/better-sqlite3/build/Release/better_sqlite3.node /app/_node_modules/better-sqlite3/build/Release/better_sqlite3.node
|
|
||||||
# Copy node_modules for migration to migrate folder for migration script
|
|
||||||
RUN mv node_modules ./migrate/node_modules
|
|
||||||
|
|
||||||
# Copy temp node_modules of app to app folder
|
|
||||||
RUN mv _node_modules node_modules
|
|
||||||
|
|
||||||
RUN echo '#!/bin/bash\nnode /app/cli/cli.js "$@"' > /usr/bin/homarr
|
|
||||||
RUN chmod +x /usr/bin/homarr
|
|
||||||
RUN cd /app/cli && yarn --immutable
|
|
||||||
|
|
||||||
# Expose the default application port
|
|
||||||
EXPOSE $PORT
|
|
||||||
ENV PORT=${PORT}
|
|
||||||
|
|
||||||
ENV DATABASE_URL "file:/data/db.sqlite"
|
|
||||||
ENV AUTH_TRUST_HOST="true"
|
|
||||||
ENV PORT 7575
|
ENV PORT 7575
|
||||||
ENV NEXTAUTH_SECRET NOT_IN_USE_BECAUSE_JWTS_ARE_UNUSED
|
RUN apk add tzdata
|
||||||
|
VOLUME /app/data/configs
|
||||||
HEALTHCHECK --interval=10s --timeout=5s --start-period=5s --retries=3 \
|
CMD ["node", "server.js"]
|
||||||
CMD wget --no-verbose --tries=1 --spider http://localhost:${PORT} || exit 1
|
|
||||||
|
|
||||||
VOLUME [ "/app/data/configs" ]
|
|
||||||
VOLUME [ "/data" ]
|
|
||||||
ENTRYPOINT ["sh", "./scripts/run.sh"]
|
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
# Multi-stage Dockerfile for Homarr Unraid UI
|
|
||||||
# Builds entirely inside Docker to avoid native module issues
|
|
||||||
|
|
||||||
# Build stage
|
|
||||||
FROM node:20.2.0-slim AS builder
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Install build dependencies
|
|
||||||
RUN apt-get update && apt-get install -y \
|
|
||||||
python3 \
|
|
||||||
make \
|
|
||||||
g++ \
|
|
||||||
git \
|
|
||||||
openssl \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Copy package files
|
|
||||||
COPY package.json yarn.lock ./
|
|
||||||
COPY .yarnrc.yml ./
|
|
||||||
COPY .yarn ./.yarn
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
RUN yarn install --immutable
|
|
||||||
|
|
||||||
# Copy source code
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Build the application
|
|
||||||
ENV SKIP_ENV_VALIDATION=1
|
|
||||||
ENV NEXTAUTH_SECRET=build-time-secret
|
|
||||||
ENV DATABASE_URL=file:build.sqlite
|
|
||||||
RUN yarn build
|
|
||||||
|
|
||||||
# Production stage
|
|
||||||
FROM node:20.2.0-slim
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Define node.js environment variables
|
|
||||||
ARG PORT=7575
|
|
||||||
|
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
|
||||||
ENV NODE_ENV=production
|
|
||||||
ENV NODE_OPTIONS='--no-experimental-fetch'
|
|
||||||
|
|
||||||
# Copy built application from builder
|
|
||||||
COPY --from=builder /app/next.config.js ./
|
|
||||||
COPY --from=builder /app/public ./public
|
|
||||||
COPY --from=builder /app/package.json ./temp_package.json
|
|
||||||
COPY --from=builder /app/yarn.lock ./temp_yarn.lock
|
|
||||||
COPY --from=builder /app/.next/standalone ./
|
|
||||||
COPY --from=builder /app/.next/static ./.next/static
|
|
||||||
COPY --from=builder /app/scripts/run.sh ./scripts/run.sh
|
|
||||||
COPY --from=builder /app/drizzle ./drizzle
|
|
||||||
COPY --from=builder /app/drizzle/migrate ./migrate
|
|
||||||
COPY --from=builder /app/tsconfig.json ./migrate/tsconfig.json
|
|
||||||
COPY --from=builder /app/cli ./cli
|
|
||||||
|
|
||||||
RUN chmod +x ./scripts/run.sh
|
|
||||||
RUN mkdir -p /data
|
|
||||||
|
|
||||||
# Install runtime dependencies
|
|
||||||
RUN apt-get update && apt-get install -y openssl wget && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Move node_modules to temp location to avoid overwriting
|
|
||||||
RUN mv node_modules _node_modules
|
|
||||||
RUN rm package.json
|
|
||||||
|
|
||||||
# Install dependencies for migration
|
|
||||||
RUN cp ./migrate/package.json ./package.json
|
|
||||||
RUN yarn install --production=false
|
|
||||||
|
|
||||||
# Copy better_sqlite3 build for current platform
|
|
||||||
RUN cp /app/node_modules/better-sqlite3/build/Release/better_sqlite3.node /app/_node_modules/better-sqlite3/build/Release/better_sqlite3.node || true
|
|
||||||
|
|
||||||
# Copy node_modules for migration to migrate folder
|
|
||||||
RUN mv node_modules ./migrate/node_modules
|
|
||||||
|
|
||||||
# Restore app node_modules
|
|
||||||
RUN mv _node_modules node_modules
|
|
||||||
|
|
||||||
# Setup CLI
|
|
||||||
RUN echo '#!/bin/bash\nnode /app/cli/cli.js "$@"' > /usr/bin/homarr
|
|
||||||
RUN chmod +x /usr/bin/homarr
|
|
||||||
RUN cd /app/cli && yarn install --production || true
|
|
||||||
|
|
||||||
# Expose the default application port
|
|
||||||
EXPOSE $PORT
|
|
||||||
ENV PORT=${PORT}
|
|
||||||
|
|
||||||
# Environment defaults
|
|
||||||
ENV DATABASE_URL="file:/data/db.sqlite"
|
|
||||||
ENV AUTH_TRUST_HOST="true"
|
|
||||||
ENV PORT=7575
|
|
||||||
ENV NEXTAUTH_SECRET=NOT_IN_USE_BECAUSE_JWTS_ARE_UNUSED
|
|
||||||
|
|
||||||
# Health check
|
|
||||||
HEALTHCHECK --interval=10s --timeout=5s --start-period=5s --retries=3 \
|
|
||||||
CMD wget --no-verbose --tries=1 --spider http://localhost:${PORT} || exit 1
|
|
||||||
|
|
||||||
VOLUME [ "/app/data/configs" ]
|
|
||||||
VOLUME [ "/data" ]
|
|
||||||
|
|
||||||
ENTRYPOINT ["sh", "./scripts/run.sh"]
|
|
||||||
248
README.md
@@ -1,144 +1,204 @@
|
|||||||
|
|
||||||
<!-- Project Title -->
|
<!-- Project Title -->
|
||||||
[](https://homarr.dev/)
|
<h1 align="center">Homarr</h1>
|
||||||
|
|
||||||
<!-- Badges -->
|
<!-- Badges -->
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://img.shields.io/github/stars/ajnart/homarr?label=%E2%AD%90%20Stars&style=flat-square?branch=master&kill_cache=1%22">
|
<img src="https://img.shields.io/github/stars/ajnart/homarr?label=%E2%AD%90%20Stars&style=flat-square?branch=master&kill_cache=1%22">
|
||||||
<a href="https://github.com/ajnart/homarr/releases/latest">
|
<a href="https://github.com/ajnart/homarr/releases/latest">
|
||||||
<img alt="Latest Release (Semver)" src="https://img.shields.io/github/v/release/ajnart/homarr?label=%F0%9F%9A%80%20Release">
|
<img alt="Latest Release (Semver)" src="https://img.shields.io/github/v/release/ajnart/homarr?label=%F0%9F%9A%80%20Release">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/ajnart/homarr/actions/workflows/docker.yml">
|
<a href="https://github.com/ajnart/homarr/actions/workflows/docker.yml">
|
||||||
<img title="Docker CI Status" src="https://github.com/ajnart/homarr/actions/workflows/docker.yml/badge.svg" alt="CI Status">
|
<img title="Docker CI Status" src="https://github.com/ajnart/homarr/actions/workflows/docker.yml/badge.svg" alt="CI Status">
|
||||||
</a>
|
|
||||||
<a href=https://translate.homarr.dev/>
|
|
||||||
<img title="Translations" src="https://badges.crowdin.net/homarr/localized.svg" />
|
|
||||||
</a>
|
</a>
|
||||||
<a href="https://discord.gg/aCsmEV5RgA">
|
<a href="https://discord.gg/aCsmEV5RgA">
|
||||||
<img title="Discord" src="https://discordapp.com/api/guilds/972958686051962910/widget.png?style=shield">
|
<img title="Discord" src="https://discordapp.com/api/guilds/972958686051962910/widget.png?style=shield">
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<!-- Links -->
|
<!-- Links -->
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://demo.homarr.dev/">
|
<i>Join the discord! — Don't forget to star the repo if you are enjoying the project!</i>
|
||||||
<strong>Demo ✨</strong>
|
</p>
|
||||||
</a>
|
<p align="center">
|
||||||
•
|
<a href="https://homarr.ajnart.fr/"><strong> Demo ↗️ </strong></a> • <a href="#-installation"><strong> Install ➡️ </strong></a> • <a href="https://github.com/ajnart/homarr/wiki"><strong> Read the Wiki 📄 </strong></a>
|
||||||
<a href="https://homarr.dev/docs/getting-started/">
|
|
||||||
<strong>Install 💻</strong>
|
|
||||||
</a> •
|
|
||||||
<a href="https://translate.homarr.dev/">
|
|
||||||
<strong>Translations 🈺</strong>
|
|
||||||
</a> •
|
|
||||||
<a href="https://discord.com/invite/aCsmEV5RgA">
|
|
||||||
<strong>Discord 👋</strong>
|
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
Simplify the management of your server with Homarr - a sleek, modern dashboard that puts all of your apps and services at your fingertips. With Homarr, you can access and control everything in one convenient location. Homarr seamlessly integrates with the apps you've added, providing you with valuable information and giving you complete control. Installation is a breeze, and Homarr supports a wide range of deployment methods.
|
---
|
||||||
|
|
||||||
<br/>
|
<!-- Homarr Description -->
|
||||||
<br/>
|
<img align="right" width=250 src="public/imgs/logo-color.svg" />
|
||||||
|
|
||||||
|
Homarr is a simple and lightweight homepage for your server, that helps you easily access all of your services in one place.
|
||||||
|
|
||||||
> [!IMPORTANT]
|
It integrates with the services you use to display information on the homepage (E.g. Show upcoming Sonarr/Radarr releases).
|
||||||
> # The Homarr repository has been moved to [HomarrLabs](https://github.com/homarr-labs/homarr)
|
|
||||||
> # Please create issues related to 1.0 there. This repository will be archived once the 1.0 is fully polished.
|
|
||||||
> # 1.0 is a complete rewrite and to migrate you have to change your compose file. Please follow the [Migration Guide](https://homarr.dev/blog/2025/01/19/migration-guide-1.0) and read the [Breaking Changes](https://homarr.dev/blog/2024/09/23/version-1.0#breaking-changes)
|
|
||||||
|
|
||||||
|
For a full list of integrations look at: [wiki/integrations](#).
|
||||||
|
|
||||||
[](https://homarr.dev/)
|
If you have any questions about Homarr or want to share information with us, please go to one of the following places:
|
||||||
|
|
||||||
- 🖌️ Highly customizable with an extensive drag and drop grid system
|
- [Github Discussions](https://github.com/ajnart/homarr/discussions)
|
||||||
- ✨ Integrates seamlessly with your favorite self-hosted applications
|
- [Discord Server](https://discord.gg/aCsmEV5RgA)
|
||||||
- 📌 Easy and fast app management - no YAML involved
|
|
||||||
- 🙊 Advanced secrets' management system for enhanced security
|
|
||||||
- 📄 Detailed documentation and active community
|
|
||||||
- 🔍 Search through the web or supported integrations in an instant
|
|
||||||
- 🏴 Monitor your application with a built-in status system
|
|
||||||
- 🦞 Comprehensive built-in icon picker with over 7000 icons
|
|
||||||
- 🐳 Easy deployment with Docker, unRAID, and Synology
|
|
||||||
- 🚀 Compatible with any major consumer hardware (x86, Raspberry Pi, old laptops, ...)
|
|
||||||
|
|
||||||
<br/>
|
*Before you file an [issue](https://github.com/ajnart/homarr/issues/new/choose), make sure you have the read [known issues](#-known-issues) section.*
|
||||||
<br/>
|
|
||||||
|
|
||||||
[](https://homarr.dev/docs/category/widgets)
|
**For more information, [read the wiki!](https://github.com/ajnart/homarr/wiki)**
|
||||||
|
|
||||||
Homarr has a [built-in collection of widgets and integrations](https://homarr.dev/docs/category/integrations), that connect to your applications and enable you to control them directly from the dashboard.
|
<details>
|
||||||
Each widget and integration has a comprehensive documentation
|
<summary><b>Table of Contents</b></summary>
|
||||||
Homarr will integrate with the following applications:
|
<p>
|
||||||
|
|
||||||
📥 Torrent clients
|
- [✨ Features](#-features)
|
||||||
- [Deluge](https://homarr.dev/docs/integrations/torrent#deluge)
|
- [👀 Preview](#-preview)
|
||||||
- [Transmission](https://homarr.dev/docs/integrations/torrent#transmission)
|
- [💥 Known Issues](#-known-issues)
|
||||||
- [qBittorent](https://homarr.dev/docs/integrations/torrent#qbittorrent-integration)
|
- [🚀 Installation](#-installation)
|
||||||
|
- [🐳 Deploying from Docker Image](#-deploying-from-docker-image)
|
||||||
|
- [🛠️ Building from Source](#️-building-from-source)
|
||||||
|
- [💖 Contributing](#-contributing)
|
||||||
|
- [📜 License](#-license)
|
||||||
|
|
||||||
📥 Usenet clients
|
</p>
|
||||||
- [SABnzbd](https://homarr.dev/docs/integrations/usenet#sabnzbd)
|
</details>
|
||||||
- [NZBGet](https://homarr.dev/docs/integrations/usenet#nzbget)
|
|
||||||
|
|
||||||
📺 Media servers
|
---
|
||||||
- [Plex](https://homarr.dev/docs/integrations/media-server/#plex)
|
|
||||||
- [Jellyfin](https://homarr.dev/docs/integrations/media-server#jellyfin-and-emby)
|
|
||||||
|
|
||||||
📚 Media collection managers
|
## ✨ Features
|
||||||
- [Sonarr](https://homarr.dev/docs/integrations/servarr#sonarr)
|
- Integrates with services you use.
|
||||||
- [Radarr](https://homarr.dev/docs/integrations/servarr#radarr)
|
- Search the web direcetly from your homepage.
|
||||||
- [Lidarr](https://homarr.dev/docs/integrations/servarr#lidarr)
|
- Real-time status indicator for every service.
|
||||||
- [Readarr](https://homarr.dev/docs/integrations/servarr#readarr)
|
- Automatically finds icons while you type the name of a serivce.
|
||||||
|
- Widgets that can display all types of information.
|
||||||
|
- Easy deployment with Docker.
|
||||||
|
- Very light-weight and fast.
|
||||||
|
- Free and Open-Source.
|
||||||
|
- And more...
|
||||||
|
|
||||||
🎞️ Media request managers
|
**[⤴️ Back to Top](#homarr)**
|
||||||
- [Overseerr](https://homarr.dev/docs/integrations/media-requester)
|
|
||||||
- [Jellyseerr](https://homarr.dev/docs/integrations/media-requester)
|
|
||||||
|
|
||||||
🚫 DNS ad-blockers
|
---
|
||||||
- [Pihole](https://homarr.dev/docs/integrations/dns#pihole)
|
|
||||||
- [AdGuard Home](https://homarr.dev/docs/integrations/dns#adguard-home)
|
|
||||||
|
|
||||||
Other integrations
|
## 👀 Preview
|
||||||
- [🔌 Dash.](https://homarr.dev/docs/integrations/hardware)
|
<img alt="Homarr Preview" align="center" width="100%" src="https://user-images.githubusercontent.com/71191962/169860380-856634fb-4f41-47cb-ba54-6a9e7b3b9c81.gif" />
|
||||||
- [🐳 Docker](https://homarr.dev/docs/integrations/containers)
|
|
||||||
|
|
||||||
We're constantly adding new integrations and widgets, which will enhance your experience even further.
|
**[⤴️ Back to Top](#homarr)**
|
||||||
|
|
||||||
<br/>
|
---
|
||||||
<br/>
|
|
||||||
|
|
||||||
[](https://demo.homarr.dev/)
|
## 💥 Known Issues
|
||||||
|
- Posters on the Calendar get blocked by adblockers. (IMDb posters)
|
||||||
|
|
||||||
https://user-images.githubusercontent.com/30572287/217098893-5880e7de-13d0-42c5-b505-f7921593396f.mp4
|
**[⤴️ Back to Top](#homarr)**
|
||||||
|
|
||||||
<br/>
|
---
|
||||||
<br/>
|
|
||||||
|
|
||||||
[](https://homarr.dev/docs/category/installation-1)
|
## 🚀 Installation
|
||||||
|
### 🐳 Deploying from Docker Image
|
||||||
|
> Supported architectures: x86-64, ARM, ARM64
|
||||||
|
|
||||||
Since we are updating Homarr very frequently, we recommend reading our official installation guides:
|
_Requirements_:
|
||||||
|
- [Docker](https://docs.docker.com/get-docker/)
|
||||||
|
|
||||||
<a href="https://homarr.dev/docs/category/installation-1">
|
**Standard Docker Install**
|
||||||
<img src="docs/installation-button.png" width="200" />
|
```bash
|
||||||
</a>
|
docker run \
|
||||||
|
--name homarr \
|
||||||
|
--restart unless-stopped \
|
||||||
|
-p 7575:7575 \
|
||||||
|
-v ./homarr/configs:/app/data/configs \
|
||||||
|
-v ./homarr/icons:/app/public/icons \
|
||||||
|
-d ghcr.io/ajnart/homarr:latest
|
||||||
|
```
|
||||||
|
|
||||||
<br/>
|
**Docker Compose**
|
||||||
<br/>
|
```yml
|
||||||
|
---
|
||||||
|
version: '3'
|
||||||
|
#---------------------------------------------------------------------#
|
||||||
|
# Homarr - A homepage for your server. #
|
||||||
|
#---------------------------------------------------------------------#
|
||||||
|
services:
|
||||||
|
homarr:
|
||||||
|
container_name: homarr
|
||||||
|
image: ghcr.io/ajnart/homarr:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./homarr/configs:/app/data/configs
|
||||||
|
- ./homarr/icons:/app/public/icons
|
||||||
|
ports:
|
||||||
|
- '7575:7575'
|
||||||
|
```
|
||||||
|
|
||||||
[](https://github.com/ajnart/homarr/blob/dev/CONTRIBUTING.md)
|
```sh
|
||||||
Homarr is maintained by motivated developers in their free-time.
|
docker compose up -d
|
||||||
We work for fun and learning on this project.
|
```
|
||||||
|
|
||||||
Hence, we're glad for all the help and support we can get.
|
*Getting EACCESS errors in the logs? Try running `sudo chmod 777 /directory-you-mounted-to`!*
|
||||||
Although a donation is appreciated, there are other ways you can support us.
|
|
||||||
|
|
||||||
<a href="https://ko-fi.com/ajnart">
|
**[⤴️ Back to Top](#homarr)**
|
||||||
<img src="https://cdn.ko-fi.com/cdn/kofi3.png?v=3" width="200" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
You can also support us by helping with [translating the entire project](https://homarr.dev/docs/community/translations) to as many language as possible or contributing directly to the code or documentation.
|
### 🛠️ Building from Source
|
||||||
|
|
||||||
|
_Requirements_:
|
||||||
|
- [Git](https://git-scm.com/downloads)
|
||||||
|
- [NodeJS](https://nodejs.org/en/) _(Latest or LTS)_
|
||||||
|
- [Yarn](https://yarnpkg.com/)
|
||||||
|
|
||||||
|
**Installing**
|
||||||
|
|
||||||
|
- Clone the GitHub repo: `git clone https://github.com/ajnart/homarr.git` & `cd homarr`
|
||||||
|
- Install all dependencies: `yarn install`
|
||||||
|
- Build the source: `yarn build`
|
||||||
|
- Start the NextJS web server: ``yarn start``
|
||||||
|
- *Note: If you want to update the code in real time, launch with ``yarn dev``*
|
||||||
|
|
||||||
|
**[⤴️ Back to Top](#homarr)**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💖 Contributing
|
||||||
**Please read our [Contribution Guidelines](/CONTRIBUTING.md)**
|
**Please read our [Contribution Guidelines](/CONTRIBUTING.md)**
|
||||||
|
|
||||||
All contributions, regardless of their size or scope, are welcome and highly appreciated! Thank you ❤️
|
All contributions are highly appreciated.
|
||||||
|
|
||||||

|
**[⤴️ Back to Top](#homarr)**
|
||||||
[](https://argos-ci.com?utm_source=%5Bhomarr%5D&utm_campaign=oss)
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## 📜 License
|
||||||
|
Homarr is Licensed under [MIT](https://en.wikipedia.org/wiki/MIT_License)
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Copyright © 2022 Thomas "ajnart" Camlong
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
```
|
||||||
|
|
||||||
|
**[⤴️ Back to Top](#homarr)**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<i>Thank you for visiting! <b>For more information <a href="https://github.com/ajnart/homarr/wiki">read the wiki!</a></b></i>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<a href="https://trackgit.com">
|
||||||
|
<img src="https://us-central1-trackgit-analytics.cloudfunctions.net/token/ping/l3khzc3a3pexzw5w5whl" alt="trackgit-views" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|||||||
18
SECURITY.md
@@ -1,18 +0,0 @@
|
|||||||
# Security Policy
|
|
||||||
|
|
||||||
## Supported Versions
|
|
||||||
Only the following versions will receive updates, that include improvements to the security:
|
|
||||||
|
|
||||||
| Version | Supported |
|
|
||||||
| ------- | ------------------ |
|
|
||||||
| 0.13 | :white_check_mark: |
|
|
||||||
| <=0.12 | :x: |
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
|
||||||
We take security issues very seriously.
|
|
||||||
When you found a security issue, please ask yourself the following question:
|
|
||||||
|
|
||||||
**Would this be publicly disclosed, could it cause any problems or harm to any Homarr instances or individuals?**
|
|
||||||
|
|
||||||
If the answer to that question is yes, please contact us immideatly using [this link](https://homarr.dev/docs/community/get-in-touch). E-Mail is preferred, but you can write ``manicraft1001`` or ``ajnart`` on Discord as well.
|
|
||||||
If the answer is no, please create a public visible issue: [Vulnerability](https://github.com/ajnart/homarr/issues/new?assignees=&labels=%F0%9F%90%9B+Bug&projects=&template=bug.yml&title=)
|
|
||||||
30
cli/cli.js
@@ -1,30 +0,0 @@
|
|||||||
import yargs from 'yargs';
|
|
||||||
|
|
||||||
import { resetPasswordForOwner } from './commands/reset-owner-password.js';
|
|
||||||
import { resetPasswordForUsername } from './commands/reset-password.js';
|
|
||||||
|
|
||||||
yargs(process.argv.slice(2))
|
|
||||||
.scriptName('homarr')
|
|
||||||
.usage('$0 <cmd> [args]')
|
|
||||||
.command('reset-owner-password', 'Resets the current owner password without UI access', async () => {
|
|
||||||
await resetPasswordForOwner();
|
|
||||||
})
|
|
||||||
.command(
|
|
||||||
'reset-password',
|
|
||||||
'Reset the password of a specific user without UI access',
|
|
||||||
(yargs) => {
|
|
||||||
yargs.option('username', {
|
|
||||||
type: 'string',
|
|
||||||
describe: 'Username of user',
|
|
||||||
demandOption: true
|
|
||||||
});
|
|
||||||
},
|
|
||||||
async (argv) => {
|
|
||||||
await resetPasswordForUsername(argv.username);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.version(false)
|
|
||||||
.showHelpOnFail(true)
|
|
||||||
.alias('h', 'help')
|
|
||||||
.demandCommand()
|
|
||||||
.help().argv;
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
import bcrypt from 'bcryptjs';
|
|
||||||
|
|
||||||
import Database from 'better-sqlite3';
|
|
||||||
|
|
||||||
import boxen from 'boxen';
|
|
||||||
|
|
||||||
import chalk from 'chalk';
|
|
||||||
|
|
||||||
import Consola from 'consola';
|
|
||||||
|
|
||||||
import crypto from 'crypto';
|
|
||||||
|
|
||||||
import { sql } from 'drizzle-orm';
|
|
||||||
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
||||||
|
|
||||||
export async function resetPasswordForOwner() {
|
|
||||||
if (!process.env.DATABASE_URL) {
|
|
||||||
Consola.error('Unable to connect to database due to missing database URL environment variable');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Consola.info('Connecting to the database...');
|
|
||||||
const sqlite = new Database(process.env.DATABASE_URL.replace('file:', ''));
|
|
||||||
const db = drizzle(sqlite);
|
|
||||||
|
|
||||||
Consola.info('Connected to the database ' + chalk.green('✓'));
|
|
||||||
Consola.info('Generating new random password...');
|
|
||||||
|
|
||||||
const newPassword = crypto.randomUUID();
|
|
||||||
const salt = bcrypt.genSaltSync(10);
|
|
||||||
const hashedPassword = bcrypt.hashSync(newPassword, salt);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await db.transaction((tx) => {
|
|
||||||
tx.run(
|
|
||||||
sql`DELETE FROM session WHERE userId = (SELECT id FROM user WHERE is_owner = 1 LIMIT 1)`
|
|
||||||
);
|
|
||||||
tx.run(sql`UPDATE user SET password = ${hashedPassword} WHERE is_owner = 1 LIMIT 1;`);
|
|
||||||
});
|
|
||||||
console.log(
|
|
||||||
boxen(`New owner password is '${chalk.red(newPassword)}'. You can now log in with this password.\nExising sessions have been destroyed and need to login again with the new passowrd.`, {
|
|
||||||
dimBorder: true,
|
|
||||||
borderStyle: 'round',
|
|
||||||
padding: {
|
|
||||||
left: 1,
|
|
||||||
right: 1
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
Consola.error('Failed to update password', err);
|
|
||||||
} finally {
|
|
||||||
Consola.info('Command has completed');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
import bcrypt from 'bcryptjs';
|
|
||||||
|
|
||||||
import Database from 'better-sqlite3';
|
|
||||||
|
|
||||||
import Consola from 'consola';
|
|
||||||
|
|
||||||
import crypto from 'crypto';
|
|
||||||
|
|
||||||
import boxen from 'boxen';
|
|
||||||
|
|
||||||
import chalk from 'chalk';
|
|
||||||
|
|
||||||
import { sql } from 'drizzle-orm';
|
|
||||||
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
||||||
|
|
||||||
export async function resetPasswordForUsername(username) {
|
|
||||||
if (!process.env.DATABASE_URL) {
|
|
||||||
Consola.error('Unable to connect to database due to missing database URL environment variable');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Consola.info('Connecting to the database...');
|
|
||||||
const sqlite = new Database(process.env.DATABASE_URL.replace('file:', ''));
|
|
||||||
const db = drizzle(sqlite);
|
|
||||||
|
|
||||||
Consola.info('Generating new random password...');
|
|
||||||
|
|
||||||
const newPassword = crypto.randomUUID();
|
|
||||||
const salt = bcrypt.genSaltSync(10);
|
|
||||||
const hashedPassword = bcrypt.hashSync(newPassword, salt);
|
|
||||||
|
|
||||||
Consola.info(`Updating password for user '${username}'`);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await db.transaction((tx) => {
|
|
||||||
tx.run(
|
|
||||||
sql`DELETE FROM session WHERE userId = (SELECT id FROM user WHERE name = ${username} LIMIT 1)`
|
|
||||||
);
|
|
||||||
tx.run(sql`UPDATE user SET password = ${hashedPassword} WHERE id = (SELECT id FROM user WHERE name = ${username} LIMIT 1) LIMIT 1`);
|
|
||||||
});
|
|
||||||
console.log(
|
|
||||||
boxen(`New password for '${username}' is '${chalk.red(newPassword)}'. You can now log in with this password.\nExising sessions have been destroyed and need to login again with the new passowrd.`, {
|
|
||||||
dimBorder: true,
|
|
||||||
borderStyle: 'round',
|
|
||||||
padding: {
|
|
||||||
left: 1,
|
|
||||||
right: 1
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
Consola.error('Failed to update password', err);
|
|
||||||
} finally {
|
|
||||||
Consola.info('Command has completed');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"dependencies": {
|
|
||||||
"bcryptjs": "^2.4.3",
|
|
||||||
"better-sqlite3": "^8.6.0",
|
|
||||||
"boxen": "^7.1.1",
|
|
||||||
"chalk": "^5.3.0",
|
|
||||||
"consola": "^3.0.0",
|
|
||||||
"drizzle-orm": "^0.28.6",
|
|
||||||
"yargs": "^17.7.2"
|
|
||||||
},
|
|
||||||
"type": "module"
|
|
||||||
}
|
|
||||||
1371
cli/yarn.lock
@@ -1,5 +1,3 @@
|
|||||||
project_id: "534422"
|
|
||||||
api_token_env: "CROWDIN_PERSONAL_TOKEN"
|
|
||||||
files:
|
files:
|
||||||
- source: /public/locales/en/**/*.json
|
- source: /public/locales/en/*.json
|
||||||
translation: /public/locales/%two_letters_code%/**/%original_file_name%
|
translation: /public/locales/%two_letters_code%/%original_file_name%.json
|
||||||
|
|||||||
@@ -1,513 +1,23 @@
|
|||||||
{
|
{
|
||||||
"schemaVersion": 1,
|
"name": "default",
|
||||||
"configProperties": {
|
"services": [
|
||||||
"name": "default"
|
|
||||||
},
|
|
||||||
"categories": [],
|
|
||||||
"wrappers": [
|
|
||||||
{
|
{
|
||||||
"id": "default",
|
"name": "example",
|
||||||
"position": 0
|
"id": "09c45847-8afc-4c1a-9697-f03192de948a",
|
||||||
}
|
"type": "Other",
|
||||||
],
|
"icon": "https://c.tenor.com/o656qFKDzeUAAAAC/rick-astley-never-gonna-give-you-up.gif",
|
||||||
"apps": [
|
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
||||||
{
|
|
||||||
"id": "5df743d9-5cb1-457c-85d2-64ff86855652",
|
|
||||||
"name": "Documentation",
|
|
||||||
"url": "https://homarr.dev",
|
|
||||||
"behaviour": {
|
|
||||||
"onClickUrl": "https://homarr.dev",
|
|
||||||
"externalUrl": "https://homarr.dev",
|
|
||||||
"isOpeningNewTab": true
|
|
||||||
},
|
|
||||||
"network": {
|
|
||||||
"enabledStatusChecker": false,
|
|
||||||
"statusCodes": [
|
|
||||||
"200"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"appearance": {
|
|
||||||
"iconUrl": "/imgs/logo/logo.png",
|
|
||||||
"appNameStatus": "normal",
|
|
||||||
"positionAppName": "column",
|
|
||||||
"lineClampAppName": 1
|
|
||||||
},
|
|
||||||
"integration": {
|
|
||||||
"type": null,
|
|
||||||
"properties": []
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 5,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 6,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a337",
|
|
||||||
"name": "Discord",
|
|
||||||
"url": "https://discord.com/invite/aCsmEV5RgA",
|
|
||||||
"behaviour": {
|
|
||||||
"onClickUrl": "https://discord.com/invite/aCsmEV5RgA",
|
|
||||||
"isOpeningNewTab": true,
|
|
||||||
"externalUrl": "https://discord.com/invite/aCsmEV5RgA",
|
|
||||||
"tooltipDescription": "Join our Discord server! We're waiting for your ideas and feedback. "
|
|
||||||
},
|
|
||||||
"network": {
|
|
||||||
"enabledStatusChecker": false,
|
|
||||||
"statusCodes": [
|
|
||||||
"200"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"appearance": {
|
|
||||||
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/discord.png",
|
|
||||||
"appNameStatus": "normal",
|
|
||||||
"positionAppName": "row-reverse",
|
|
||||||
"lineClampAppName": 1
|
|
||||||
},
|
|
||||||
"integration": {
|
|
||||||
"type": null,
|
|
||||||
"properties": []
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 4
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 4,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a330",
|
|
||||||
"name": "Contribute",
|
|
||||||
"url": "https://github.com/ajnart/homarr",
|
|
||||||
"behaviour": {
|
|
||||||
"onClickUrl": "https://github.com/ajnart/homarr",
|
|
||||||
"externalUrl": "https://github.com/ajnart/homarr",
|
|
||||||
"isOpeningNewTab": true,
|
|
||||||
"tooltipDescription": ""
|
|
||||||
},
|
|
||||||
"network": {
|
|
||||||
"enabledStatusChecker": false,
|
|
||||||
"statusCodes": []
|
|
||||||
},
|
|
||||||
"appearance": {
|
|
||||||
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/github.png",
|
|
||||||
"appNameStatus": "normal",
|
|
||||||
"positionAppName": "row-reverse",
|
|
||||||
"lineClampAppName": 2
|
|
||||||
},
|
|
||||||
"integration": {
|
|
||||||
"type": null,
|
|
||||||
"properties": []
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 2
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 3
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a990",
|
|
||||||
"name": "Donate",
|
|
||||||
"url": "https://ko-fi.com/ajnart",
|
|
||||||
"behaviour": {
|
|
||||||
"onClickUrl": "https://ko-fi.com/ajnart",
|
|
||||||
"externalUrl": "https://ko-fi.com/ajnart",
|
|
||||||
"isOpeningNewTab": true,
|
|
||||||
"tooltipDescription": "Please consider making a donation"
|
|
||||||
},
|
|
||||||
"network": {
|
|
||||||
"enabledStatusChecker": false,
|
|
||||||
"statusCodes": [
|
|
||||||
"200"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"appearance": {
|
|
||||||
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/ko-fi.png",
|
|
||||||
"appNameStatus": "normal",
|
|
||||||
"positionAppName": "row-reverse",
|
|
||||||
"lineClampAppName": 1
|
|
||||||
},
|
|
||||||
"integration": {
|
|
||||||
"type": null,
|
|
||||||
"properties": []
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 4,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 4
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 6,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"widgets": [
|
|
||||||
{
|
|
||||||
"id": "e3004052-6b83-480e-b458-56e8ccdca5f0",
|
|
||||||
"type": "weather",
|
|
||||||
"properties": {
|
|
||||||
"displayInFahrenheit": false,
|
|
||||||
"location": {
|
|
||||||
"name": "Paris",
|
|
||||||
"latitude": 48.85341,
|
|
||||||
"longitude": 2.3488
|
|
||||||
},
|
|
||||||
"displayCityName": true
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 5,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "971aa859-8570-49a1-8d34-dd5c7b3638d1",
|
|
||||||
"type": "date",
|
|
||||||
"properties": {
|
|
||||||
"display24HourFormat": true,
|
|
||||||
"dateFormat": "hide",
|
|
||||||
"enableTimezone": false,
|
|
||||||
"timezoneLocation": {
|
|
||||||
"name": "Paris",
|
|
||||||
"latitude": 48.85341,
|
|
||||||
"longitude": 2.3488
|
|
||||||
},
|
|
||||||
"titleState": "city"
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 4,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 8,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "f252768d-9e69-491b-b6b4-8cad04fa30e8",
|
|
||||||
"type": "date",
|
|
||||||
"properties": {
|
|
||||||
"display24HourFormat": true,
|
|
||||||
"dateFormat": "hide",
|
|
||||||
"enableTimezone": true,
|
|
||||||
"timezoneLocation": {
|
|
||||||
"name": "Tokyo",
|
|
||||||
"latitude": 35.6895,
|
|
||||||
"longitude": 139.69171
|
|
||||||
},
|
|
||||||
"titleState": "city"
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 8,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "86b1921f-efa7-410f-92dd-79553bf3264d",
|
|
||||||
"type": "notebook",
|
|
||||||
"properties": {
|
|
||||||
"showToolbar": true,
|
|
||||||
"content": "<h2><strong>Welcome to Homarr 🚀👋</strong></h2><p>We're glad that you're here! Homarr is a <em>modern </em>and <em>easy to use</em> dashboard that helps you to <strong>organize and manage</strong> your home network from one place. Control is <strong>at your fingertips</strong>.</p><p>We recommend you to read the <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://homarr.dev/docs/getting-started/after-the-installation\">getting started guide</a> first. To edit this board you must enter the edit mode - only administrators can do this. Adding an app is the first step you should take. You can do this by clicking the <code>Add tile</code> button at the top right and select <code>App</code>. After you provided an internal URL, external URL and selected an icon you can drag it around when holding down the left mouse button. Make it bigger or smaller using the drag icon at the bottom right. When you're happy with it's position, you <strong>must exit edit mode to save your board</strong>. Adding widgets works the same way but may require additional configuration - read the documentation for more information.</p><p>To remove this widget, you must log in to your administrator account and click on the menu to delete it.</p><p><strong><u>Your TODO list:</u></strong></p><ul data-type=\"taskList\"><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Read the <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://homarr.dev\">documentation</a></p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Add your <em>first app</em></p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p><em>Resize </em>and <em>drag</em> your app to a different position</p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Add the <em>clock widget</em> to your dashboard</p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Create a <em>new user</em></p></div></li></ul>"
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 3,
|
|
||||||
"height": 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 3,
|
|
||||||
"height": 4
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 6,
|
|
||||||
"height": 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
"common": {
|
"searchUrl": "https://google.com/search?q="
|
||||||
"searchEngine": {
|
},
|
||||||
"type": "google",
|
"modules": {
|
||||||
"properties": {}
|
"Search Bar": {
|
||||||
}
|
"enabled": true
|
||||||
},
|
},
|
||||||
"customization": {
|
"Date": {
|
||||||
"layout": {
|
"enabled": false
|
||||||
"enabledLeftSidebar": false,
|
|
||||||
"enabledRightSidebar": false,
|
|
||||||
"enabledDocker": false,
|
|
||||||
"enabledPing": false,
|
|
||||||
"enabledSearchbar": true
|
|
||||||
},
|
|
||||||
"pageTitle": "Homarr ⭐️",
|
|
||||||
"logoImageUrl": "/imgs/logo/logo.png",
|
|
||||||
"faviconUrl": "/imgs/favicon/favicon-squared.png",
|
|
||||||
"backgroundImageUrl": "",
|
|
||||||
"customCss": "",
|
|
||||||
"colors": {
|
|
||||||
"primary": "red",
|
|
||||||
"secondary": "yellow",
|
|
||||||
"shade": 7
|
|
||||||
},
|
|
||||||
"appOpacity": 100,
|
|
||||||
"gridstack": {
|
|
||||||
"columnCountSmall": 3,
|
|
||||||
"columnCountMedium": 6,
|
|
||||||
"columnCountLarge": 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"access": {
|
|
||||||
"allowGuests": false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,2 @@
|
|||||||
export const REPO_URL = 'ajnart/homarr';
|
export const REPO_URL = 'ajnart/homarr';
|
||||||
export const ICON_PICKER_SLICE_LIMIT = 36;
|
export const CURRENT_VERSION = 'v0.7.0';
|
||||||
export const COOKIE_LOCALE_KEY = 'config-locale';
|
|
||||||
export const COOKIE_COLOR_SCHEME_KEY = 'color-scheme';
|
|
||||||
|
|||||||
@@ -1,513 +0,0 @@
|
|||||||
{
|
|
||||||
"schemaVersion": 2,
|
|
||||||
"configProperties": {
|
|
||||||
"name": "default"
|
|
||||||
},
|
|
||||||
"categories": [],
|
|
||||||
"wrappers": [
|
|
||||||
{
|
|
||||||
"id": "default",
|
|
||||||
"position": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"apps": [
|
|
||||||
{
|
|
||||||
"id": "5df743d9-5cb1-457c-85d2-64ff86855652",
|
|
||||||
"name": "Documentation",
|
|
||||||
"url": "https://homarr.dev",
|
|
||||||
"behaviour": {
|
|
||||||
"onClickUrl": "https://homarr.dev",
|
|
||||||
"externalUrl": "https://homarr.dev",
|
|
||||||
"isOpeningNewTab": true
|
|
||||||
},
|
|
||||||
"network": {
|
|
||||||
"enabledStatusChecker": false,
|
|
||||||
"statusCodes": [
|
|
||||||
"200"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"appearance": {
|
|
||||||
"iconUrl": "/imgs/logo/logo.png",
|
|
||||||
"appNameStatus": "normal",
|
|
||||||
"positionAppName": "column",
|
|
||||||
"lineClampAppName": 1
|
|
||||||
},
|
|
||||||
"integration": {
|
|
||||||
"type": null,
|
|
||||||
"properties": []
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 5,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 6,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a337",
|
|
||||||
"name": "Discord",
|
|
||||||
"url": "https://discord.com/invite/aCsmEV5RgA",
|
|
||||||
"behaviour": {
|
|
||||||
"onClickUrl": "https://discord.com/invite/aCsmEV5RgA",
|
|
||||||
"isOpeningNewTab": true,
|
|
||||||
"externalUrl": "https://discord.com/invite/aCsmEV5RgA",
|
|
||||||
"tooltipDescription": "Join our Discord server! We're waiting for your ideas and feedback. "
|
|
||||||
},
|
|
||||||
"network": {
|
|
||||||
"enabledStatusChecker": false,
|
|
||||||
"statusCodes": [
|
|
||||||
"200"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"appearance": {
|
|
||||||
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/discord.png",
|
|
||||||
"appNameStatus": "normal",
|
|
||||||
"positionAppName": "row-reverse",
|
|
||||||
"lineClampAppName": 1
|
|
||||||
},
|
|
||||||
"integration": {
|
|
||||||
"type": null,
|
|
||||||
"properties": []
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 4
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 4,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a330",
|
|
||||||
"name": "Contribute",
|
|
||||||
"url": "https://github.com/ajnart/homarr",
|
|
||||||
"behaviour": {
|
|
||||||
"onClickUrl": "https://github.com/ajnart/homarr",
|
|
||||||
"externalUrl": "https://github.com/ajnart/homarr",
|
|
||||||
"isOpeningNewTab": true,
|
|
||||||
"tooltipDescription": ""
|
|
||||||
},
|
|
||||||
"network": {
|
|
||||||
"enabledStatusChecker": false,
|
|
||||||
"statusCodes": []
|
|
||||||
},
|
|
||||||
"appearance": {
|
|
||||||
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/github.png",
|
|
||||||
"appNameStatus": "normal",
|
|
||||||
"positionAppName": "row-reverse",
|
|
||||||
"lineClampAppName": 2
|
|
||||||
},
|
|
||||||
"integration": {
|
|
||||||
"type": null,
|
|
||||||
"properties": []
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 2
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 3
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a990",
|
|
||||||
"name": "Donate",
|
|
||||||
"url": "https://ko-fi.com/ajnart",
|
|
||||||
"behaviour": {
|
|
||||||
"onClickUrl": "https://ko-fi.com/ajnart",
|
|
||||||
"externalUrl": "https://ko-fi.com/ajnart",
|
|
||||||
"isOpeningNewTab": true,
|
|
||||||
"tooltipDescription": "Please consider making a donation"
|
|
||||||
},
|
|
||||||
"network": {
|
|
||||||
"enabledStatusChecker": false,
|
|
||||||
"statusCodes": [
|
|
||||||
"200"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"appearance": {
|
|
||||||
"iconUrl": "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/ko-fi.png",
|
|
||||||
"appNameStatus": "normal",
|
|
||||||
"positionAppName": "row-reverse",
|
|
||||||
"lineClampAppName": 1
|
|
||||||
},
|
|
||||||
"integration": {
|
|
||||||
"type": null,
|
|
||||||
"properties": []
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 4,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 4
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 6,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"widgets": [
|
|
||||||
{
|
|
||||||
"id": "e3004052-6b83-480e-b458-56e8ccdca5f0",
|
|
||||||
"type": "weather",
|
|
||||||
"properties": {
|
|
||||||
"displayInFahrenheit": false,
|
|
||||||
"location": {
|
|
||||||
"name": "Paris",
|
|
||||||
"latitude": 48.85341,
|
|
||||||
"longitude": 2.3488
|
|
||||||
},
|
|
||||||
"displayCityName": true
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 5,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 2,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "971aa859-8570-49a1-8d34-dd5c7b3638d1",
|
|
||||||
"type": "date",
|
|
||||||
"properties": {
|
|
||||||
"display24HourFormat": true,
|
|
||||||
"dateFormat": "hide",
|
|
||||||
"enableTimezone": false,
|
|
||||||
"timezoneLocation": {
|
|
||||||
"name": "Paris",
|
|
||||||
"latitude": 48.85341,
|
|
||||||
"longitude": 2.3488
|
|
||||||
},
|
|
||||||
"titleState": "city"
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 4,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 8,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "f252768d-9e69-491b-b6b4-8cad04fa30e8",
|
|
||||||
"type": "date",
|
|
||||||
"properties": {
|
|
||||||
"display24HourFormat": true,
|
|
||||||
"dateFormat": "hide",
|
|
||||||
"enableTimezone": true,
|
|
||||||
"timezoneLocation": {
|
|
||||||
"name": "Tokyo",
|
|
||||||
"latitude": 35.6895,
|
|
||||||
"longitude": 139.69171
|
|
||||||
},
|
|
||||||
"titleState": "city"
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 3,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 1,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 8,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 2,
|
|
||||||
"height": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "86b1921f-efa7-410f-92dd-79553bf3264d",
|
|
||||||
"type": "notebook",
|
|
||||||
"properties": {
|
|
||||||
"showToolbar": true,
|
|
||||||
"content": "<h2><strong>Welcome to Homarr 🚀👋</strong></h2><p>We're glad that you're here! Homarr is a <em>modern </em>and <em>easy to use</em> dashboard that helps you to <strong>organize and manage</strong> your home network from one place. Control is <strong>at your fingertips</strong>.</p><p>We recommend you to read the <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://homarr.dev/docs/getting-started/after-the-installation\">getting started guide</a> first. To edit this board you must enter the edit mode - only administrators can do this. Adding an app is the first step you should take. You can do this by clicking the <code>Add tile</code> button at the top right and select <code>App</code>. After you provided an internal URL, external URL and selected an icon you can drag it around when holding down the left mouse button. Make it bigger or smaller using the drag icon at the bottom right. When you're happy with it's position, you <strong>must exit edit mode to save your board</strong>. Adding widgets works the same way but may require additional configuration - read the documentation for more information.</p><p>To remove this widget, you must log in to your administrator account and click on the menu to delete it.</p><p><strong><u>Your TODO list:</u></strong></p><ul data-type=\"taskList\"><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Read the <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://homarr.dev\">documentation</a></p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Add your <em>first app</em></p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p><em>Resize </em>and <em>drag</em> your app to a different position</p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Add the <em>clock widget</em> to your dashboard</p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Create a <em>new user</em></p></div></li></ul>"
|
|
||||||
},
|
|
||||||
"area": {
|
|
||||||
"type": "wrapper",
|
|
||||||
"properties": {
|
|
||||||
"id": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shape": {
|
|
||||||
"sm": {
|
|
||||||
"location": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 3,
|
|
||||||
"height": 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"md": {
|
|
||||||
"location": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 3,
|
|
||||||
"height": 4
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lg": {
|
|
||||||
"location": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 1
|
|
||||||
},
|
|
||||||
"size": {
|
|
||||||
"width": 6,
|
|
||||||
"height": 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"settings": {
|
|
||||||
"common": {
|
|
||||||
"searchEngine": {
|
|
||||||
"type": "google",
|
|
||||||
"properties": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"customization": {
|
|
||||||
"layout": {
|
|
||||||
"enabledLeftSidebar": false,
|
|
||||||
"enabledRightSidebar": false,
|
|
||||||
"enabledDocker": false,
|
|
||||||
"enabledPing": false,
|
|
||||||
"enabledSearchbar": true
|
|
||||||
},
|
|
||||||
"pageTitle": "Homarr ⭐️",
|
|
||||||
"logoImageUrl": "/imgs/logo/logo.png",
|
|
||||||
"faviconUrl": "/imgs/favicon/favicon-squared.png",
|
|
||||||
"backgroundImageUrl": "",
|
|
||||||
"customCss": "",
|
|
||||||
"colors": {
|
|
||||||
"primary": "red",
|
|
||||||
"secondary": "yellow",
|
|
||||||
"shade": 7
|
|
||||||
},
|
|
||||||
"appOpacity": 100,
|
|
||||||
"gridstack": {
|
|
||||||
"columnCountSmall": 3,
|
|
||||||
"columnCountMedium": 6,
|
|
||||||
"columnCountLarge": 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"access": {
|
|
||||||
"allowGuests": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
version: "3.8"
|
|
||||||
|
|
||||||
services:
|
|
||||||
unmarr:
|
|
||||||
image: git.xtrm-lab.org/jazzymc/homarr:latest
|
|
||||||
container_name: unmarr
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
# Unraid API Configuration
|
|
||||||
- UNRAID_HOST=192.168.10.20
|
|
||||||
- UNRAID_API_KEY=${UNRAID_API_KEY}
|
|
||||||
- UNRAID_USE_SSL=false
|
|
||||||
- UNRAID_PORT=80
|
|
||||||
# App Configuration
|
|
||||||
- TZ=Europe/Sofia
|
|
||||||
- DATABASE_URL=file:/data/db.sqlite
|
|
||||||
- AUTH_TRUST_HOST=true
|
|
||||||
- NEXTAUTH_URL=https://unmarr.xtrm-lab.org
|
|
||||||
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET:-changeme}
|
|
||||||
volumes:
|
|
||||||
- /mnt/user/appdata/unmarr/data:/data
|
|
||||||
- /mnt/user/appdata/unmarr/configs:/app/data/configs
|
|
||||||
networks:
|
|
||||||
dockerproxy:
|
|
||||||
ipv4_address: 172.18.0.5
|
|
||||||
labels:
|
|
||||||
# Traefik
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.constraint=valid"
|
|
||||||
- "traefik.http.routers.unmarr.rule=Host(`unmarr.xtrm-lab.org`)"
|
|
||||||
- "traefik.http.routers.unmarr.entrypoints=https"
|
|
||||||
- "traefik.http.routers.unmarr.tls=true"
|
|
||||||
- "traefik.http.routers.unmarr.tls.certresolver=cloudflare"
|
|
||||||
- "traefik.http.services.unmarr.loadbalancer.server.port=7575"
|
|
||||||
# Unraid
|
|
||||||
- "net.unraid.docker.managed=true"
|
|
||||||
- "net.unraid.docker.icon=https://homarr.dev/img/logo.png"
|
|
||||||
- "net.unraid.docker.webui=https://unmarr.xtrm-lab.org"
|
|
||||||
|
|
||||||
networks:
|
|
||||||
dockerproxy:
|
|
||||||
external: true
|
|
||||||
BIN
docs/banner.png
|
Before Width: | Height: | Size: 48 KiB |
BIN
docs/banner.xcf
|
Before Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 33 KiB |
@@ -1,148 +0,0 @@
|
|||||||
# Unraid Custom UI Project
|
|
||||||
|
|
||||||
This project transforms the Homarr fork into a custom Unraid management UI with an Orchis GTK theme.
|
|
||||||
|
|
||||||
## Project Goals
|
|
||||||
|
|
||||||
1. **Step 1**: Recreate all current Unraid WebGUI pages using Homarr as a base, with data from the Unraid GraphQL API
|
|
||||||
2. **Step 2**: Apply a custom theme based on the Orchis GTK theme
|
|
||||||
|
|
||||||
## Project Resources
|
|
||||||
|
|
||||||
| Document | Description |
|
|
||||||
|----------|-------------|
|
|
||||||
| [WEBGUI-COMPLETE-INVENTORY.md](./WEBGUI-COMPLETE-INVENTORY.md) | Complete inventory of ~100 Unraid WebGUI pages |
|
|
||||||
| [unraid-api-research.md](./unraid-api-research.md) | Unraid GraphQL API documentation |
|
|
||||||
| [homarr-architecture.md](./homarr-architecture.md) | Homarr codebase architecture |
|
|
||||||
| [orchis-design-system.ts](./orchis-design-system.ts) | Orchis theme design tokens (TypeScript) |
|
|
||||||
|
|
||||||
## Unraid Server Connection
|
|
||||||
|
|
||||||
- **GraphQL Endpoint**: `http://192.168.10.20/graphql`
|
|
||||||
- **Auth**: `x-api-key` header
|
|
||||||
- **Socket**: `/var/run/unraid-api.sock`
|
|
||||||
|
|
||||||
## Implementation Plan
|
|
||||||
|
|
||||||
### Phase 1: Foundation Setup
|
|
||||||
- [ ] Create Unraid GraphQL client integration
|
|
||||||
- [ ] Set up API authentication layer
|
|
||||||
- [ ] Configure environment variables for Unraid connection
|
|
||||||
- [ ] Create base types for Unraid data models
|
|
||||||
|
|
||||||
### Phase 2: Core Pages (Priority Order)
|
|
||||||
1. **Dashboard** - System overview with real-time metrics
|
|
||||||
- System info, CPU/RAM usage, array status
|
|
||||||
- Docker/VM summaries, network, UPS
|
|
||||||
|
|
||||||
2. **Array Management** (Main)
|
|
||||||
- Array devices, pool devices, boot device
|
|
||||||
- Parity check, array operations
|
|
||||||
|
|
||||||
3. **Docker Management**
|
|
||||||
- Container list, start/stop/restart
|
|
||||||
- Container details, logs
|
|
||||||
|
|
||||||
4. **VM Management**
|
|
||||||
- VM list, power controls
|
|
||||||
- VM details, console access
|
|
||||||
|
|
||||||
5. **Shares**
|
|
||||||
- User shares, disk shares
|
|
||||||
- Share settings, SMB/NFS security
|
|
||||||
|
|
||||||
### Phase 3: Orchis Theme Integration
|
|
||||||
- [ ] Copy design tokens to `src/styles/`
|
|
||||||
- [ ] Create Mantine theme override with Orchis values
|
|
||||||
- [ ] Implement light/dark mode with Orchis palettes
|
|
||||||
- [ ] Replace default components with Orchis-styled versions
|
|
||||||
|
|
||||||
### Phase 4: Settings & Tools
|
|
||||||
- Settings pages (identification, disk, network, etc.)
|
|
||||||
- Tools pages (syslog, diagnostics, system devices)
|
|
||||||
- User management
|
|
||||||
- Notifications system
|
|
||||||
|
|
||||||
### Phase 5: Real-time Features
|
|
||||||
- GraphQL subscriptions for CPU/memory metrics
|
|
||||||
- Nchan integration for legacy real-time features
|
|
||||||
- WebSocket connections for live updates
|
|
||||||
|
|
||||||
## Key Technical Decisions
|
|
||||||
|
|
||||||
### Homarr Stack
|
|
||||||
- Next.js 13 (Pages Router in this version)
|
|
||||||
- Mantine UI v6
|
|
||||||
- tRPC for type-safe API
|
|
||||||
- Zustand for state management
|
|
||||||
- React Query for server state
|
|
||||||
|
|
||||||
### Data Sources
|
|
||||||
| Feature | Source |
|
|
||||||
|---------|--------|
|
|
||||||
| System info, array, shares | Unraid GraphQL API |
|
|
||||||
| Docker containers | Unraid GraphQL API |
|
|
||||||
| VMs | Unraid GraphQL API |
|
|
||||||
| Real-time CPU/RAM | GraphQL Subscriptions |
|
|
||||||
| Real-time disk I/O | Nchan WebSocket (`/sub/diskload`) |
|
|
||||||
| Legacy features | PHP endpoints where needed |
|
|
||||||
|
|
||||||
### API Gaps (Require Legacy Endpoints)
|
|
||||||
- Docker create/delete/restart/logs
|
|
||||||
- VM create/delete
|
|
||||||
- Share CRUD, User CRUD
|
|
||||||
- System reboot/shutdown
|
|
||||||
- Mover operations
|
|
||||||
|
|
||||||
## Directory Structure (New Files)
|
|
||||||
|
|
||||||
```
|
|
||||||
src/
|
|
||||||
├── lib/
|
|
||||||
│ └── unraid/
|
|
||||||
│ ├── client.ts # GraphQL client
|
|
||||||
│ ├── types.ts # TypeScript types
|
|
||||||
│ └── queries/ # GraphQL queries
|
|
||||||
├── pages/
|
|
||||||
│ └── unraid/
|
|
||||||
│ ├── dashboard.tsx # Dashboard page
|
|
||||||
│ ├── array/ # Array pages
|
|
||||||
│ ├── docker/ # Docker pages
|
|
||||||
│ ├── vms/ # VM pages
|
|
||||||
│ ├── shares/ # Share pages
|
|
||||||
│ ├── settings/ # Settings pages
|
|
||||||
│ └── tools/ # Tools pages
|
|
||||||
├── components/
|
|
||||||
│ └── unraid/
|
|
||||||
│ ├── Dashboard/ # Dashboard components
|
|
||||||
│ ├── Array/ # Array components
|
|
||||||
│ ├── Docker/ # Docker components
|
|
||||||
│ └── ...
|
|
||||||
└── styles/
|
|
||||||
└── orchis/
|
|
||||||
├── theme.ts # Mantine theme config
|
|
||||||
├── variables.css # CSS custom properties
|
|
||||||
└── components.css # Component overrides
|
|
||||||
```
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install dependencies
|
|
||||||
yarn install
|
|
||||||
|
|
||||||
# Set up environment
|
|
||||||
cp .env.example .env.local
|
|
||||||
# Edit .env.local with your Unraid API key
|
|
||||||
|
|
||||||
# Run development server
|
|
||||||
yarn dev
|
|
||||||
```
|
|
||||||
|
|
||||||
## Environment Variables
|
|
||||||
|
|
||||||
```env
|
|
||||||
UNRAID_HOST=192.168.10.20
|
|
||||||
UNRAID_API_KEY=your-api-key-here
|
|
||||||
UNRAID_USE_SSL=false
|
|
||||||
```
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
# Homarr Architecture
|
|
||||||
|
|
||||||
## Tech Stack
|
|
||||||
- Next.js 13+ (App Router), React 18, TypeScript
|
|
||||||
- Mantine UI (component library)
|
|
||||||
- Zustand (client state), React Query (server state)
|
|
||||||
- Prisma ORM (SQLite default / PostgreSQL)
|
|
||||||
- Turbo monorepo, pnpm workspaces
|
|
||||||
|
|
||||||
## Project Structure
|
|
||||||
```
|
|
||||||
homarr/
|
|
||||||
├── apps/web/src/ # Main Next.js app
|
|
||||||
│ ├── app/ # App Router pages
|
|
||||||
│ ├── components/ # React components
|
|
||||||
│ ├── modules/ # Widgets & integrations
|
|
||||||
│ ├── stores/ # Zustand stores
|
|
||||||
│ └── styles/ # Themes & global CSS
|
|
||||||
├── packages/
|
|
||||||
│ ├── api-client/ # API client lib
|
|
||||||
│ ├── common/ # Shared types/utils
|
|
||||||
│ ├── definitions/ # Widget/integration defs
|
|
||||||
│ ├── auth/ # Auth logic
|
|
||||||
│ └── ui/ # Shared UI components
|
|
||||||
├── prisma/ # DB schema & migrations
|
|
||||||
└── turbo.json
|
|
||||||
```
|
|
||||||
|
|
||||||
## Widget System
|
|
||||||
Each widget in `apps/web/src/modules/`:
|
|
||||||
- `definition.ts` - Metadata + Zod config schema
|
|
||||||
- `component.tsx` - React component
|
|
||||||
- `settings.tsx` - Config panel
|
|
||||||
- `server-actions.ts` - Backend operations
|
|
||||||
- Registered in module index, auto-discovered
|
|
||||||
|
|
||||||
## Integration System
|
|
||||||
External service connectors with:
|
|
||||||
- API client abstraction, credential management
|
|
||||||
- URL/hostname config, SSL handling
|
|
||||||
- Error handling, retry, rate limiting, caching
|
|
||||||
|
|
||||||
## Theming
|
|
||||||
- CSS variables + Mantine theming + Tailwind
|
|
||||||
- Light/dark mode, custom color palettes, accent colors
|
|
||||||
- Wallpaper/background, font size, border radius customization
|
|
||||||
- Theme persisted in database
|
|
||||||
|
|
||||||
## Adding New Pages
|
|
||||||
1. Create in `apps/web/src/app/(group)/page-name/page.tsx`
|
|
||||||
2. Use Mantine UI components
|
|
||||||
3. Add API routes in `src/app/api/`
|
|
||||||
4. Create Zustand store or use React Query
|
|
||||||
5. Update navigation config
|
|
||||||
|
|
||||||
## Key Patterns
|
|
||||||
- Server Components by default, `'use client'` for interactive
|
|
||||||
- TRPC for type-safe RPC
|
|
||||||
- Zod schemas for validation
|
|
||||||
- Prisma for DB operations
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
# Unraid API Research (Live from XTRM-Unraid v7.2.3)
|
|
||||||
|
|
||||||
## API: unraid-api v4.29.2 (NestJS + Apollo GraphQL)
|
|
||||||
|
|
||||||
### Connection
|
|
||||||
- HTTP: `http://192.168.10.20/graphql`
|
|
||||||
- WebSocket: `ws://192.168.10.20/graphql` (graphql-ws protocol)
|
|
||||||
- Unix socket: `/var/run/unraid-api.sock`
|
|
||||||
- Auth: `x-api-key` header
|
|
||||||
|
|
||||||
### GraphQL Queries
|
|
||||||
| Query | Description |
|
|
||||||
|-------|-------------|
|
|
||||||
| `info` | System info (cpu, memory, os, baseboard, devices, display, versions) |
|
|
||||||
| `array` | Array state, capacity, disks, parities, caches, parity check status |
|
|
||||||
| `disks` / `disk(id)` | Physical disks with SMART status, temp, serial |
|
|
||||||
| `docker` | Containers (id, names, state, status, image, ports, autoStart) + networks |
|
|
||||||
| `vms` | VMs (id, name, state) |
|
|
||||||
| `shares` | Shares (name, free, used, size, include, exclude, cache, color) |
|
|
||||||
| `notifications` | Notifications (title, subject, description, importance, type, timestamp) |
|
|
||||||
| `vars` | Server variables (version, name, timezone, network, SMB/NFS settings) |
|
|
||||||
| `services` | Running services (name, online, uptime, version) |
|
|
||||||
| `flash` | Flash drive (guid, vendor, product) |
|
|
||||||
| `registration` | License (type, state, keyFile, expiration) |
|
|
||||||
| `network` | Network info (accessUrls) |
|
|
||||||
| `server` | Server details (owner, guid, wanip, lanip, localurl, remoteurl) |
|
|
||||||
| `connect` | Connect status (dynamicRemoteAccess, settings) |
|
|
||||||
| `plugins` | Installed plugins (name, version) |
|
|
||||||
| `logFiles` / `logFile(path)` | Log file listing and content |
|
|
||||||
| `upsDevices` / `upsConfiguration` | UPS monitoring |
|
|
||||||
| `apiKeys` | API key management |
|
|
||||||
| `customization` | Theme + activation code |
|
|
||||||
| `me` / `owner` | Current user / server owner |
|
|
||||||
|
|
||||||
### GraphQL Mutations
|
|
||||||
| Mutation | Description |
|
|
||||||
|----------|-------------|
|
|
||||||
| `array.setState` | Start/stop array |
|
|
||||||
| `array.addDiskToArray` / `removeDiskFromArray` | Disk management |
|
|
||||||
| `array.mountArrayDisk` / `unmountArrayDisk` | Mount/unmount |
|
|
||||||
| `docker.start(id)` / `docker.stop(id)` | Container start/stop |
|
|
||||||
| `vm.start/stop/pause/resume/forceStop/reboot/reset(id)` | VM power management |
|
|
||||||
| `parityCheck.start/pause/resume/cancel` | Parity check control |
|
|
||||||
| `notification.create/delete/archive/unread` | Notification CRUD |
|
|
||||||
| `apiKey.create/update/delete` | API key management |
|
|
||||||
| `customization.setTheme` | Theme switching |
|
|
||||||
| `connectSignIn/SignOut` | Unraid Connect |
|
|
||||||
| `setupRemoteAccess` | Remote access config |
|
|
||||||
|
|
||||||
### GraphQL Subscriptions (Real-time)
|
|
||||||
- `systemMetricsCpu` / `systemMetricsCpuTelemetry` / `systemMetricsMemory`
|
|
||||||
- `arraySubscription` / `parityHistorySubscription`
|
|
||||||
- `notificationAdded` / `notificationsOverview`
|
|
||||||
- `logFile` (live log streaming)
|
|
||||||
- `upsUpdates`
|
|
||||||
- `ownerSubscription` / `serversSubscription`
|
|
||||||
|
|
||||||
### Enums
|
|
||||||
- ArrayState: STARTED, STOPPED, NEW_ARRAY, RECON_DISK, DISABLE_DISK, etc.
|
|
||||||
- ArrayDiskStatus: DISK_NP, DISK_OK, DISK_INVALID, DISK_WRONG, DISK_DSBL, etc.
|
|
||||||
- ArrayDiskType: DATA, PARITY, FLASH, CACHE
|
|
||||||
- ContainerState: RUNNING, EXITED
|
|
||||||
- VmState: NOSTATE, RUNNING, IDLE, PAUSED, SHUTDOWN, SHUTOFF, CRASHED, PMSUSPENDED
|
|
||||||
- DiskFsType: XFS, BTRFS, VFAT, ZFS, EXT4, NTFS
|
|
||||||
- DiskInterfaceType: SAS, SATA, USB, PCIE, UNKNOWN
|
|
||||||
- ThemeName: azure, black, gray, white
|
|
||||||
|
|
||||||
### Legacy PHP/Nchan Endpoints
|
|
||||||
- Nchan WebSocket channels: `/sub/var`, `/sub/docker`, `/sub/update1-3`, `/sub/diskload`, etc.
|
|
||||||
- PHP includes: DashboardApps.php, Control.php, SmartInfo.php, Syslog.php, etc.
|
|
||||||
- State INI files at `/var/local/emhttp/`: var.ini, disks.ini, shares.ini, etc.
|
|
||||||
- Legacy control: POST to `/update.htm` for commands
|
|
||||||
|
|
||||||
### NOT Available via GraphQL
|
|
||||||
- Docker create/delete/restart/logs
|
|
||||||
- VM create/delete
|
|
||||||
- Share CRUD, User CRUD
|
|
||||||
- Detailed SMART attributes
|
|
||||||
- Disk format/clear, spin up/down
|
|
||||||
- System reboot/shutdown
|
|
||||||
- Mover operations
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import 'dotenv';
|
|
||||||
import { type Config } from 'drizzle-kit';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
schema: './src/server/db/schema.ts',
|
|
||||||
driver: 'better-sqlite',
|
|
||||||
out: './drizzle',
|
|
||||||
dbCredentials: {
|
|
||||||
url: process.env.DATABASE_URL!,
|
|
||||||
},
|
|
||||||
} satisfies Config;
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
CREATE TABLE `account` (
|
|
||||||
`userId` text NOT NULL,
|
|
||||||
`type` text NOT NULL,
|
|
||||||
`provider` text NOT NULL,
|
|
||||||
`providerAccountId` text NOT NULL,
|
|
||||||
`refresh_token` text,
|
|
||||||
`access_token` text,
|
|
||||||
`expires_at` integer,
|
|
||||||
`token_type` text,
|
|
||||||
`scope` text,
|
|
||||||
`id_token` text,
|
|
||||||
`session_state` text,
|
|
||||||
PRIMARY KEY(`provider`, `providerAccountId`),
|
|
||||||
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE TABLE `invite` (
|
|
||||||
`id` text PRIMARY KEY NOT NULL,
|
|
||||||
`token` text NOT NULL,
|
|
||||||
`expires` integer NOT NULL,
|
|
||||||
`created_by_id` text NOT NULL,
|
|
||||||
FOREIGN KEY (`created_by_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE TABLE `session` (
|
|
||||||
`sessionToken` text PRIMARY KEY NOT NULL,
|
|
||||||
`userId` text NOT NULL,
|
|
||||||
`expires` integer NOT NULL,
|
|
||||||
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE TABLE `user_setting` (
|
|
||||||
`id` text PRIMARY KEY NOT NULL,
|
|
||||||
`user_id` text NOT NULL,
|
|
||||||
`color_scheme` text DEFAULT 'environment' NOT NULL,
|
|
||||||
`language` text DEFAULT 'en' NOT NULL,
|
|
||||||
`default_board` text DEFAULT 'default' NOT NULL,
|
|
||||||
`first_day_of_week` text DEFAULT 'monday' NOT NULL,
|
|
||||||
`search_template` text DEFAULT 'https://google.com/search?q=%s' NOT NULL,
|
|
||||||
`open_search_in_new_tab` integer DEFAULT true NOT NULL,
|
|
||||||
`disable_ping_pulse` integer DEFAULT false NOT NULL,
|
|
||||||
`replace_ping_with_icons` integer DEFAULT false NOT NULL,
|
|
||||||
`use_debug_language` integer DEFAULT false NOT NULL,
|
|
||||||
`auto_focus_search` integer DEFAULT false NOT NULL,
|
|
||||||
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE TABLE `user` (
|
|
||||||
`id` text PRIMARY KEY NOT NULL,
|
|
||||||
`name` text,
|
|
||||||
`email` text,
|
|
||||||
`emailVerified` integer,
|
|
||||||
`image` text,
|
|
||||||
`password` text,
|
|
||||||
`salt` text,
|
|
||||||
`is_admin` integer DEFAULT false NOT NULL,
|
|
||||||
`is_owner` integer DEFAULT false NOT NULL
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE TABLE `verificationToken` (
|
|
||||||
`identifier` text NOT NULL,
|
|
||||||
`token` text NOT NULL,
|
|
||||||
`expires` integer NOT NULL,
|
|
||||||
PRIMARY KEY(`identifier`, `token`)
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE INDEX `userId_idx` ON `account` (`userId`);--> statement-breakpoint
|
|
||||||
CREATE UNIQUE INDEX `invite_token_unique` ON `invite` (`token`);--> statement-breakpoint
|
|
||||||
CREATE INDEX `user_id_idx` ON `session` (`userId`);
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
CREATE TABLE `migrate_token` (
|
|
||||||
`id` text PRIMARY KEY NOT NULL,
|
|
||||||
`token` text NOT NULL,
|
|
||||||
`boards` integer NOT NULL,
|
|
||||||
`users` integer NOT NULL,
|
|
||||||
`integrations` integer NOT NULL,
|
|
||||||
`expires` integer NOT NULL
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE UNIQUE INDEX `migrate_token_token_unique` ON `migrate_token` (`token`);
|
|
||||||
@@ -1,468 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "5",
|
|
||||||
"dialect": "sqlite",
|
|
||||||
"id": "32c1bc91-e69f-4e1d-b53c-9c43f2e6c9d3",
|
|
||||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
|
||||||
"tables": {
|
|
||||||
"account": {
|
|
||||||
"name": "account",
|
|
||||||
"columns": {
|
|
||||||
"userId": {
|
|
||||||
"name": "userId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"type": {
|
|
||||||
"name": "type",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"provider": {
|
|
||||||
"name": "provider",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"providerAccountId": {
|
|
||||||
"name": "providerAccountId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"refresh_token": {
|
|
||||||
"name": "refresh_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"access_token": {
|
|
||||||
"name": "access_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"expires_at": {
|
|
||||||
"name": "expires_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"token_type": {
|
|
||||||
"name": "token_type",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"scope": {
|
|
||||||
"name": "scope",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"id_token": {
|
|
||||||
"name": "id_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"session_state": {
|
|
||||||
"name": "session_state",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {
|
|
||||||
"userId_idx": {
|
|
||||||
"name": "userId_idx",
|
|
||||||
"columns": [
|
|
||||||
"userId"
|
|
||||||
],
|
|
||||||
"isUnique": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"foreignKeys": {
|
|
||||||
"account_userId_user_id_fk": {
|
|
||||||
"name": "account_userId_user_id_fk",
|
|
||||||
"tableFrom": "account",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"userId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {
|
|
||||||
"account_provider_providerAccountId_pk": {
|
|
||||||
"columns": [
|
|
||||||
"provider",
|
|
||||||
"providerAccountId"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"invite": {
|
|
||||||
"name": "invite",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"token": {
|
|
||||||
"name": "token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"expires": {
|
|
||||||
"name": "expires",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"created_by_id": {
|
|
||||||
"name": "created_by_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {
|
|
||||||
"invite_token_unique": {
|
|
||||||
"name": "invite_token_unique",
|
|
||||||
"columns": [
|
|
||||||
"token"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"foreignKeys": {
|
|
||||||
"invite_created_by_id_user_id_fk": {
|
|
||||||
"name": "invite_created_by_id_user_id_fk",
|
|
||||||
"tableFrom": "invite",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"created_by_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"session": {
|
|
||||||
"name": "session",
|
|
||||||
"columns": {
|
|
||||||
"sessionToken": {
|
|
||||||
"name": "sessionToken",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"userId": {
|
|
||||||
"name": "userId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"expires": {
|
|
||||||
"name": "expires",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {
|
|
||||||
"user_id_idx": {
|
|
||||||
"name": "user_id_idx",
|
|
||||||
"columns": [
|
|
||||||
"userId"
|
|
||||||
],
|
|
||||||
"isUnique": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"foreignKeys": {
|
|
||||||
"session_userId_user_id_fk": {
|
|
||||||
"name": "session_userId_user_id_fk",
|
|
||||||
"tableFrom": "session",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"userId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"user_setting": {
|
|
||||||
"name": "user_setting",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"color_scheme": {
|
|
||||||
"name": "color_scheme",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "'environment'"
|
|
||||||
},
|
|
||||||
"language": {
|
|
||||||
"name": "language",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "'en'"
|
|
||||||
},
|
|
||||||
"default_board": {
|
|
||||||
"name": "default_board",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "'default'"
|
|
||||||
},
|
|
||||||
"first_day_of_week": {
|
|
||||||
"name": "first_day_of_week",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "'monday'"
|
|
||||||
},
|
|
||||||
"search_template": {
|
|
||||||
"name": "search_template",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "'https://google.com/search?q=%s'"
|
|
||||||
},
|
|
||||||
"open_search_in_new_tab": {
|
|
||||||
"name": "open_search_in_new_tab",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": true
|
|
||||||
},
|
|
||||||
"disable_ping_pulse": {
|
|
||||||
"name": "disable_ping_pulse",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"replace_ping_with_icons": {
|
|
||||||
"name": "replace_ping_with_icons",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"use_debug_language": {
|
|
||||||
"name": "use_debug_language",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"auto_focus_search": {
|
|
||||||
"name": "auto_focus_search",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"user_setting_user_id_user_id_fk": {
|
|
||||||
"name": "user_setting_user_id_user_id_fk",
|
|
||||||
"tableFrom": "user_setting",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"user": {
|
|
||||||
"name": "user",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"name": "name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"email": {
|
|
||||||
"name": "email",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"emailVerified": {
|
|
||||||
"name": "emailVerified",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"image": {
|
|
||||||
"name": "image",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"password": {
|
|
||||||
"name": "password",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"salt": {
|
|
||||||
"name": "salt",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"is_admin": {
|
|
||||||
"name": "is_admin",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"is_owner": {
|
|
||||||
"name": "is_owner",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"verificationToken": {
|
|
||||||
"name": "verificationToken",
|
|
||||||
"columns": {
|
|
||||||
"identifier": {
|
|
||||||
"name": "identifier",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"token": {
|
|
||||||
"name": "token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"expires": {
|
|
||||||
"name": "expires",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {},
|
|
||||||
"compositePrimaryKeys": {
|
|
||||||
"verificationToken_identifier_token_pk": {
|
|
||||||
"columns": [
|
|
||||||
"identifier",
|
|
||||||
"token"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"enums": {},
|
|
||||||
"_meta": {
|
|
||||||
"schemas": {},
|
|
||||||
"tables": {},
|
|
||||||
"columns": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,527 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "5",
|
|
||||||
"dialect": "sqlite",
|
|
||||||
"id": "9c8971c9-6d33-4d14-b318-b19ff9fbb88f",
|
|
||||||
"prevId": "32c1bc91-e69f-4e1d-b53c-9c43f2e6c9d3",
|
|
||||||
"tables": {
|
|
||||||
"account": {
|
|
||||||
"name": "account",
|
|
||||||
"columns": {
|
|
||||||
"userId": {
|
|
||||||
"name": "userId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"type": {
|
|
||||||
"name": "type",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"provider": {
|
|
||||||
"name": "provider",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"providerAccountId": {
|
|
||||||
"name": "providerAccountId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"refresh_token": {
|
|
||||||
"name": "refresh_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"access_token": {
|
|
||||||
"name": "access_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"expires_at": {
|
|
||||||
"name": "expires_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"token_type": {
|
|
||||||
"name": "token_type",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"scope": {
|
|
||||||
"name": "scope",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"id_token": {
|
|
||||||
"name": "id_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"session_state": {
|
|
||||||
"name": "session_state",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {
|
|
||||||
"userId_idx": {
|
|
||||||
"name": "userId_idx",
|
|
||||||
"columns": [
|
|
||||||
"userId"
|
|
||||||
],
|
|
||||||
"isUnique": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"foreignKeys": {
|
|
||||||
"account_userId_user_id_fk": {
|
|
||||||
"name": "account_userId_user_id_fk",
|
|
||||||
"tableFrom": "account",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"userId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {
|
|
||||||
"account_provider_providerAccountId_pk": {
|
|
||||||
"columns": [
|
|
||||||
"provider",
|
|
||||||
"providerAccountId"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"invite": {
|
|
||||||
"name": "invite",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"token": {
|
|
||||||
"name": "token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"expires": {
|
|
||||||
"name": "expires",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"created_by_id": {
|
|
||||||
"name": "created_by_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {
|
|
||||||
"invite_token_unique": {
|
|
||||||
"name": "invite_token_unique",
|
|
||||||
"columns": [
|
|
||||||
"token"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"foreignKeys": {
|
|
||||||
"invite_created_by_id_user_id_fk": {
|
|
||||||
"name": "invite_created_by_id_user_id_fk",
|
|
||||||
"tableFrom": "invite",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"created_by_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"migrate_token": {
|
|
||||||
"name": "migrate_token",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"token": {
|
|
||||||
"name": "token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"boards": {
|
|
||||||
"name": "boards",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"users": {
|
|
||||||
"name": "users",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"integrations": {
|
|
||||||
"name": "integrations",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"expires": {
|
|
||||||
"name": "expires",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {
|
|
||||||
"migrate_token_token_unique": {
|
|
||||||
"name": "migrate_token_token_unique",
|
|
||||||
"columns": [
|
|
||||||
"token"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"foreignKeys": {},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"session": {
|
|
||||||
"name": "session",
|
|
||||||
"columns": {
|
|
||||||
"sessionToken": {
|
|
||||||
"name": "sessionToken",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"userId": {
|
|
||||||
"name": "userId",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"expires": {
|
|
||||||
"name": "expires",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {
|
|
||||||
"user_id_idx": {
|
|
||||||
"name": "user_id_idx",
|
|
||||||
"columns": [
|
|
||||||
"userId"
|
|
||||||
],
|
|
||||||
"isUnique": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"foreignKeys": {
|
|
||||||
"session_userId_user_id_fk": {
|
|
||||||
"name": "session_userId_user_id_fk",
|
|
||||||
"tableFrom": "session",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"userId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"user_setting": {
|
|
||||||
"name": "user_setting",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"color_scheme": {
|
|
||||||
"name": "color_scheme",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "'environment'"
|
|
||||||
},
|
|
||||||
"language": {
|
|
||||||
"name": "language",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "'en'"
|
|
||||||
},
|
|
||||||
"default_board": {
|
|
||||||
"name": "default_board",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "'default'"
|
|
||||||
},
|
|
||||||
"first_day_of_week": {
|
|
||||||
"name": "first_day_of_week",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "'monday'"
|
|
||||||
},
|
|
||||||
"search_template": {
|
|
||||||
"name": "search_template",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": "'https://google.com/search?q=%s'"
|
|
||||||
},
|
|
||||||
"open_search_in_new_tab": {
|
|
||||||
"name": "open_search_in_new_tab",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": true
|
|
||||||
},
|
|
||||||
"disable_ping_pulse": {
|
|
||||||
"name": "disable_ping_pulse",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"replace_ping_with_icons": {
|
|
||||||
"name": "replace_ping_with_icons",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"use_debug_language": {
|
|
||||||
"name": "use_debug_language",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"auto_focus_search": {
|
|
||||||
"name": "auto_focus_search",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"user_setting_user_id_user_id_fk": {
|
|
||||||
"name": "user_setting_user_id_user_id_fk",
|
|
||||||
"tableFrom": "user_setting",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"user": {
|
|
||||||
"name": "user",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"name": "name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"email": {
|
|
||||||
"name": "email",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"emailVerified": {
|
|
||||||
"name": "emailVerified",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"image": {
|
|
||||||
"name": "image",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"password": {
|
|
||||||
"name": "password",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"salt": {
|
|
||||||
"name": "salt",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"is_admin": {
|
|
||||||
"name": "is_admin",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"is_owner": {
|
|
||||||
"name": "is_owner",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false,
|
|
||||||
"default": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
},
|
|
||||||
"verificationToken": {
|
|
||||||
"name": "verificationToken",
|
|
||||||
"columns": {
|
|
||||||
"identifier": {
|
|
||||||
"name": "identifier",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"token": {
|
|
||||||
"name": "token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"expires": {
|
|
||||||
"name": "expires",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {},
|
|
||||||
"compositePrimaryKeys": {
|
|
||||||
"verificationToken_identifier_token_pk": {
|
|
||||||
"columns": [
|
|
||||||
"identifier",
|
|
||||||
"token"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"uniqueConstraints": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"enums": {},
|
|
||||||
"_meta": {
|
|
||||||
"schemas": {},
|
|
||||||
"tables": {},
|
|
||||||
"columns": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "5",
|
|
||||||
"dialect": "sqlite",
|
|
||||||
"entries": [
|
|
||||||
{
|
|
||||||
"idx": 0,
|
|
||||||
"version": "5",
|
|
||||||
"when": 1695874816934,
|
|
||||||
"tag": "0000_supreme_the_captain",
|
|
||||||
"breakpoints": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idx": 1,
|
|
||||||
"version": "5",
|
|
||||||
"when": 1730643218521,
|
|
||||||
"tag": "0001_brave_mimic",
|
|
||||||
"breakpoints": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
// This file is used to migrate the database to the current version
|
|
||||||
// It is run when the docker container starts
|
|
||||||
const Database = require('better-sqlite3');
|
|
||||||
const path = require('path');
|
|
||||||
const dotenv = require('dotenv');
|
|
||||||
const { drizzle } = require('drizzle-orm/better-sqlite3');
|
|
||||||
const { migrate } = require('drizzle-orm/better-sqlite3/migrator');
|
|
||||||
|
|
||||||
const migrationsFolder = process.argv[2] ?? '../drizzle';
|
|
||||||
|
|
||||||
dotenv.config({ path: path.join(__dirname, '/../.env') });
|
|
||||||
const sqlite = new Database(process.env.DATABASE_URL!.replace('file:', ''));
|
|
||||||
|
|
||||||
const db = drizzle(sqlite);
|
|
||||||
|
|
||||||
const migrateDatabase = async () => {
|
|
||||||
await migrate(db, { migrationsFolder });
|
|
||||||
};
|
|
||||||
|
|
||||||
migrateDatabase();
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"license": "MIT",
|
|
||||||
"description": "This package.json is used for the migration script the dependencies are only installed within the Dockerfile.",
|
|
||||||
"scripts": {
|
|
||||||
"db:migrate": "tsx ./migrate.ts"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@types/better-sqlite3": "^7.6.7",
|
|
||||||
"better-sqlite3": "8.6.0",
|
|
||||||
"drizzle-orm": "^0.28.6",
|
|
||||||
"dotenv": "^16.3.1",
|
|
||||||
"tsx": "4.19.1",
|
|
||||||
"typescript": "^5.2.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
const path = require('path');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
// https://www.i18next.com/overview/configuration-options#logging
|
|
||||||
i18n: {
|
|
||||||
defaultLocale: 'en',
|
|
||||||
locales: [
|
|
||||||
'ar',
|
|
||||||
'cn',
|
|
||||||
'cr',
|
|
||||||
'cs',
|
|
||||||
'da',
|
|
||||||
'de',
|
|
||||||
'el',
|
|
||||||
'en',
|
|
||||||
'es',
|
|
||||||
'fr',
|
|
||||||
'he',
|
|
||||||
'hr',
|
|
||||||
'hu',
|
|
||||||
'it',
|
|
||||||
'ja',
|
|
||||||
'ko',
|
|
||||||
'lv',
|
|
||||||
'nl',
|
|
||||||
'no',
|
|
||||||
'pl',
|
|
||||||
'pt',
|
|
||||||
'ru',
|
|
||||||
'sk',
|
|
||||||
'sl',
|
|
||||||
'sv',
|
|
||||||
'tr',
|
|
||||||
'tw',
|
|
||||||
'uk',
|
|
||||||
'vi',
|
|
||||||
'et',
|
|
||||||
'lt',
|
|
||||||
'ro'
|
|
||||||
],
|
|
||||||
|
|
||||||
localeDetection: false,
|
|
||||||
},
|
|
||||||
returnEmptyString: false,
|
|
||||||
appendNamespaceToCIMode: true,
|
|
||||||
reloadOnPrerender: process.env.NODE_ENV === 'development',
|
|
||||||
fallbackLng: 'en',
|
|
||||||
localePath: path.resolve('./public/locales'),
|
|
||||||
};
|
|
||||||
@@ -1,34 +1,16 @@
|
|||||||
require('./src/env');
|
const { env } = require('process');
|
||||||
const { i18n } = require('./next-i18next.config');
|
|
||||||
|
|
||||||
const withBundleAnalyzer = require('@next/bundle-analyzer')({
|
const withBundleAnalyzer = require('@next/bundle-analyzer')({
|
||||||
enabled: process.env.ANALYZE === 'true',
|
enabled: process.env.ANALYZE === 'true',
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = withBundleAnalyzer({
|
module.exports = withBundleAnalyzer({
|
||||||
|
reactStrictMode: false,
|
||||||
eslint: {
|
eslint: {
|
||||||
ignoreDuringBuilds: true,
|
ignoreDuringBuilds: true,
|
||||||
},
|
},
|
||||||
webpack: (config) => {
|
experimental: {
|
||||||
// for dynamic loading of auth providers
|
outputStandalone: true,
|
||||||
config.experiments = { ...config.experiments, topLevelAwait: true };
|
|
||||||
return config;
|
|
||||||
},
|
|
||||||
images: {
|
|
||||||
domains: ['cdn.jsdelivr.net'],
|
|
||||||
},
|
|
||||||
reactStrictMode: true,
|
|
||||||
output: 'standalone',
|
|
||||||
i18n,
|
|
||||||
transpilePackages: ['@jellyfin/sdk'],
|
|
||||||
redirects: async () => [
|
|
||||||
{
|
|
||||||
source: '/',
|
|
||||||
destination: '/unraid',
|
|
||||||
permanent: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
env: {
|
|
||||||
NEXTAUTH_URL_INTERNAL: process.env.NEXTAUTH_URL_INTERNAL || process.env.HOSTNAME || 'http://localhost:3000'
|
|
||||||
},
|
},
|
||||||
|
basePath: env.BASE_URL,
|
||||||
});
|
});
|
||||||
|
|||||||
331
package.json
@@ -1,247 +1,88 @@
|
|||||||
{
|
{
|
||||||
"name": "homarr",
|
"name": "homarr",
|
||||||
"version": "0.16.0",
|
"version": "0.7.0",
|
||||||
"description": "Homarr - A homepage for your server.",
|
"description": "Homarr - A homepage for your server.",
|
||||||
"license": "MIT",
|
"repository": {
|
||||||
"repository": {
|
"type": "git",
|
||||||
"type": "git",
|
"url": "https://github.com/ajnart/homarr"
|
||||||
"url": "https://github.com/ajnart/homarr"
|
},
|
||||||
},
|
"scripts": {
|
||||||
"scripts": {
|
"dev": "next dev",
|
||||||
"dev": "next dev",
|
"build": "next build",
|
||||||
"build": "NEXTAUTH_SECRET=WILL_BE_OVERWRITTEN next build",
|
"analyze": "ANALYZE=true next build",
|
||||||
"analyze": "ANALYZE=true next build",
|
"start": "next start",
|
||||||
"turbo": "DATABASE_URL=file:WILL_BE_OVERWRITTEN.sqlite turbo build",
|
"typecheck": "tsc --noEmit",
|
||||||
"start": "next start",
|
"export": "next build && next export",
|
||||||
"typecheck": "tsc --noEmit",
|
"lint": "next lint",
|
||||||
"export": "next build && next export",
|
"jest": "jest",
|
||||||
"lint": "next lint",
|
"jest:watch": "jest --watch",
|
||||||
"prettier:check": "prettier --check \"**/*.{ts,tsx}\"",
|
"prettier:check": "prettier --check \"**/*.{ts,tsx}\"",
|
||||||
"prettier:write": "prettier --write \"**/*.{ts,tsx}\"",
|
"prettier:write": "prettier --write \"**/*.{ts,tsx}\"",
|
||||||
"test": "SKIP_ENV_VALIDATION=1 vitest",
|
"test": "npm run prettier:check && npm run lint && npm run typecheck && npm run jest",
|
||||||
"test:docker": "yarn run turbo build && yarn test:run && docker build . -t homarr:local-dev && docker run -p 7575:7575 --name homarr-dev homarr:local-dev",
|
"storybook": "start-storybook -p 7001",
|
||||||
"test:ui": "SKIP_ENV_VALIDATION=1 vitest --ui",
|
"storybook:build": "build-storybook",
|
||||||
"test:run": "SKIP_ENV_VALIDATION=1 vitest run",
|
"ci": "yarn test && yarn lint --fix && yarn typecheck && yarn prettier:write"
|
||||||
"test:coverage": "SKIP_ENV_VALIDATION=1 vitest run --coverage",
|
},
|
||||||
"docker:build": "turbo build && docker build . -t homarr:local-dev",
|
"dependencies": {
|
||||||
"docker:start": "docker run -p 7575:7575 --name homarr-development homarr:local-dev",
|
"@ctrl/deluge": "^4.1.0",
|
||||||
"db:migrate": "dotenv tsx drizzle/migrate/migrate.ts ./drizzle",
|
"@ctrl/qbittorrent": "^4.0.0",
|
||||||
"db:add": "drizzle-kit generate:sqlite --config ./drizzle.config.ts"
|
"@ctrl/shared-torrent": "^4.1.0",
|
||||||
},
|
"@ctrl/transmission": "^4.1.1",
|
||||||
"dependencies": {
|
"@dnd-kit/core": "^6.0.1",
|
||||||
"@ctrl/deluge": "^4.1.0",
|
"@dnd-kit/sortable": "^7.0.0",
|
||||||
"@ctrl/qbittorrent": "^6.0.0",
|
"@dnd-kit/utilities": "^3.2.0",
|
||||||
"@ctrl/shared-torrent": "^4.1.1",
|
"@mantine/core": "^4.2.8",
|
||||||
"@ctrl/transmission": "^4.1.1",
|
"@mantine/dates": "^4.2.8",
|
||||||
"@emotion/react": "^11.10.6",
|
"@mantine/dropzone": "^4.2.8",
|
||||||
"@emotion/server": "^11.10.0",
|
"@mantine/form": "^4.2.8",
|
||||||
"@jellyfin/sdk": "^0.8.0",
|
"@mantine/hooks": "^4.2.8",
|
||||||
"@mantine/core": "^6.0.0",
|
"@mantine/next": "^4.2.8",
|
||||||
"@mantine/dates": "^6.0.0",
|
"@mantine/notifications": "^4.2.8",
|
||||||
"@mantine/form": "^6.0.0",
|
"@mantine/prism": "^4.2.8",
|
||||||
"@mantine/hooks": "^6.0.0",
|
"@nivo/core": "^0.79.0",
|
||||||
"@mantine/modals": "^6.0.0",
|
"@nivo/line": "^0.79.1",
|
||||||
"@mantine/next": "^6.0.0",
|
"@tabler/icons": "^1.68.0",
|
||||||
"@mantine/notifications": "^6.0.0",
|
"axios": "^0.27.2",
|
||||||
"@mantine/prism": "^6.0.19",
|
"cookies-next": "^2.0.4",
|
||||||
"@mantine/tiptap": "^6.0.17",
|
"dayjs": "^1.11.3",
|
||||||
"@nivo/core": "^0.83.0",
|
"framer-motion": "^6.3.1",
|
||||||
"@nivo/line": "^0.83.0",
|
"js-file-download": "^0.4.12",
|
||||||
"@t3-oss/env-nextjs": "^0.7.1",
|
"next": "12.1.6",
|
||||||
"@tabler/icons-react": "^2.20.0",
|
"prism-react-renderer": "^1.3.1",
|
||||||
"@tanstack/react-query": "^4.2.1",
|
"react": "^17.0.1",
|
||||||
"@tanstack/react-query-devtools": "^4.24.4",
|
"react-dom": "^17.0.1",
|
||||||
"@tiptap/extension-color": "^2.1.12",
|
"systeminformation": "^5.11.16",
|
||||||
"@tiptap/extension-highlight": "^2.1.12",
|
"uuid": "^8.3.2"
|
||||||
"@tiptap/extension-image": "^2.1.12",
|
},
|
||||||
"@tiptap/extension-link": "^2.1.12",
|
"devDependencies": {
|
||||||
"@tiptap/extension-table": "^2.1.12",
|
"@babel/core": "^7.17.8",
|
||||||
"@tiptap/extension-table-cell": "^2.1.12",
|
"@next/bundle-analyzer": "^12.1.4",
|
||||||
"@tiptap/extension-table-header": "^2.1.12",
|
"@next/eslint-plugin-next": "^12.1.4",
|
||||||
"@tiptap/extension-table-row": "^2.1.12",
|
"@storybook/react": "^6.5.4",
|
||||||
"@tiptap/extension-task-item": "^2.1.12",
|
"@types/node": "^17.0.23",
|
||||||
"@tiptap/extension-task-list": "^2.1.12",
|
"@types/react": "17.0.43",
|
||||||
"@tiptap/extension-text-align": "^2.1.12",
|
"@types/uuid": "^8.3.4",
|
||||||
"@tiptap/extension-text-style": "^2.1.12",
|
"@typescript-eslint/eslint-plugin": "^5.16.0",
|
||||||
"@tiptap/extension-underline": "^2.1.12",
|
"@typescript-eslint/parser": "^5.16.0",
|
||||||
"@tiptap/pm": "^2.1.12",
|
"eslint": "^8.11.0",
|
||||||
"@tiptap/react": "^2.1.12",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
"@tiptap/starter-kit": "^2.1.12",
|
"eslint-config-airbnb-typescript": "^16.1.0",
|
||||||
"@trpc/client": "^10.37.1",
|
"eslint-config-mantine": "1.1.0",
|
||||||
"@trpc/next": "^10.37.1",
|
"eslint-plugin-import": "^2.25.4",
|
||||||
"@trpc/react-query": "^10.37.1",
|
"eslint-plugin-jest": "^26.1.3",
|
||||||
"@trpc/server": "^10.37.1",
|
"eslint-plugin-jsx-a11y": "^6.5.1",
|
||||||
"@types/bcryptjs": "^2.4.2",
|
"eslint-plugin-react": "^7.29.4",
|
||||||
"@vitejs/plugin-react": "^4.0.0",
|
"eslint-plugin-react-hooks": "^4.3.0",
|
||||||
"adm-zip": "^0.5.15",
|
"eslint-plugin-storybook": "^0.5.11",
|
||||||
"axios": "^1.0.0",
|
"eslint-plugin-testing-library": "^5.2.0",
|
||||||
"bcryptjs": "^2.4.3",
|
"eslint-plugin-unused-imports": "^2.0.0",
|
||||||
"better-sqlite3": "^8.6.0",
|
"jest": "^28.1.0",
|
||||||
"consola": "^3.0.0",
|
"prettier": "^2.6.2",
|
||||||
"cookies": "^0.8.0",
|
"require-from-string": "^2.0.2",
|
||||||
"cookies-next": "^2.1.1",
|
"typescript": "4.6.4"
|
||||||
"dayjs": "^1.11.7",
|
},
|
||||||
"dockerode": "^3.3.2",
|
"resolutions": {
|
||||||
"dotenv": "^16.3.1",
|
"@types/react": "17.0.30"
|
||||||
"drizzle-kit": "^0.19.13",
|
},
|
||||||
"drizzle-orm": "^0.28.6",
|
"packageManager": "yarn@3.2.1"
|
||||||
"drizzle-zod": "^0.5.1",
|
|
||||||
"fily-publish-gridstack": "^0.0.13",
|
|
||||||
"flag-icons": "^6.9.2",
|
|
||||||
"framer-motion": "^10.0.0",
|
|
||||||
"generate-password": "^1.7.0",
|
|
||||||
"html-entities": "^2.3.3",
|
|
||||||
"i18next": "^22.5.1",
|
|
||||||
"immer": "^10.0.2",
|
|
||||||
"js-file-download": "^0.4.12",
|
|
||||||
"ldapjs": "^3.0.5",
|
|
||||||
"mantine-react-table": "^1.3.4",
|
|
||||||
"next": "13.4.12",
|
|
||||||
"next-auth": "^4.23.0",
|
|
||||||
"next-i18next": "^14.0.0",
|
|
||||||
"nextjs-cors": "^2.2.0",
|
|
||||||
"nzbget-api": "^0.0.3",
|
|
||||||
"prismjs": "^1.29.0",
|
|
||||||
"react": "^18.2.0",
|
|
||||||
"react-dom": "^18.2.0",
|
|
||||||
"react-i18next": "^12.3.1",
|
|
||||||
"react-simple-code-editor": "^0.13.1",
|
|
||||||
"rss-parser": "^3.12.0",
|
|
||||||
"sabnzbd-api": "^1.5.0",
|
|
||||||
"swagger-ui-react": "^5.11.0",
|
|
||||||
"tldts": "^6.1.18",
|
|
||||||
"trpc-openapi": "^1.2.0",
|
|
||||||
"uuid": "^9.0.0",
|
|
||||||
"xml-js": "^1.6.11",
|
|
||||||
"xss": "^1.0.14",
|
|
||||||
"zod": "^3.21.4",
|
|
||||||
"zustand": "^4.3.7"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@next/bundle-analyzer": "^13.0.0",
|
|
||||||
"@next/eslint-plugin-next": "^13.4.5",
|
|
||||||
"@testing-library/react": "^14.0.0",
|
|
||||||
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
|
|
||||||
"@types/adm-zip": "^0.5.5",
|
|
||||||
"@types/better-sqlite3": "^7.6.5",
|
|
||||||
"@types/cookies": "^0.7.7",
|
|
||||||
"@types/dockerode": "^3.3.9",
|
|
||||||
"@types/ldapjs": "^3.0.2",
|
|
||||||
"@types/node": "^20.6.0",
|
|
||||||
"@types/prismjs": "^1.26.0",
|
|
||||||
"@types/react": "^18.2.11",
|
|
||||||
"@types/swagger-ui-react": "^4.18.3",
|
|
||||||
"@types/umami": "^0.1.4",
|
|
||||||
"@types/uuid": "^9.0.0",
|
|
||||||
"@types/video.js": "^7.3.51",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
||||||
"@typescript-eslint/parser": "^6.0.0",
|
|
||||||
"@vitest/coverage-c8": "^0.33.0",
|
|
||||||
"@vitest/coverage-v8": "^0.34.5",
|
|
||||||
"@vitest/ui": "^0.34.4",
|
|
||||||
"dotenv-cli": "^7.3.0",
|
|
||||||
"eslint": "^8.0.1",
|
|
||||||
"eslint-config-next": "^13.4.5",
|
|
||||||
"eslint-plugin-promise": "^6.0.0",
|
|
||||||
"eslint-plugin-react": "latest",
|
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
|
||||||
"eslint-plugin-testing-library": "^5.5.1",
|
|
||||||
"eslint-plugin-unused-imports": "^3.0.0",
|
|
||||||
"eslint-plugin-vitest": "^0.2.0",
|
|
||||||
"happy-dom": "^10.0.0",
|
|
||||||
"node-mocks-http": "^1.12.2",
|
|
||||||
"prettier": "^3.0.0",
|
|
||||||
"sass": "^1.56.1",
|
|
||||||
"tsx": "4.19.1",
|
|
||||||
"turbo": "^1.10.12",
|
|
||||||
"typescript": "5.1.6",
|
|
||||||
"video.js": "^8.0.3",
|
|
||||||
"vite-tsconfig-paths": "^4.2.0",
|
|
||||||
"vitest": "^0.33.0",
|
|
||||||
"vitest-fetch-mock": "^0.2.2"
|
|
||||||
},
|
|
||||||
"nextBundleAnalysis": {
|
|
||||||
"budget": null,
|
|
||||||
"budgetPercentIncreaseRed": 20,
|
|
||||||
"minimumChangeThreshold": 0,
|
|
||||||
"showDetails": true
|
|
||||||
},
|
|
||||||
"prettier": {
|
|
||||||
"printWidth": 100,
|
|
||||||
"tabWidth": 2,
|
|
||||||
"parser": "typescript",
|
|
||||||
"singleQuote": true,
|
|
||||||
"trailingComma": "es5",
|
|
||||||
"useTabs": false,
|
|
||||||
"endOfLine": "lf",
|
|
||||||
"importOrder": [
|
|
||||||
"^@core/(.*)$",
|
|
||||||
"^@server/(.*)$",
|
|
||||||
"^@ui/(.*)$",
|
|
||||||
"^[./]"
|
|
||||||
],
|
|
||||||
"importOrderSeparation": true,
|
|
||||||
"plugins": [
|
|
||||||
"@trivago/prettier-plugin-sort-imports"
|
|
||||||
],
|
|
||||||
"importOrderSortSpecifiers": true
|
|
||||||
},
|
|
||||||
"eslintConfig": {
|
|
||||||
"extends": [
|
|
||||||
"next",
|
|
||||||
"eslint:recommended",
|
|
||||||
"plugin:@next/next/recommended",
|
|
||||||
"plugin:react-hooks/recommended",
|
|
||||||
"plugin:react/recommended",
|
|
||||||
"plugin:@typescript-eslint/recommended",
|
|
||||||
"plugin:vitest/recommended"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"testing-library",
|
|
||||||
"unused-imports",
|
|
||||||
"react",
|
|
||||||
"vitest"
|
|
||||||
],
|
|
||||||
"overrides": [
|
|
||||||
{
|
|
||||||
"files": [
|
|
||||||
"**/?(*.)+(spec|test).[jt]s?(x)"
|
|
||||||
],
|
|
||||||
"extends": [
|
|
||||||
"plugin:testing-library/react"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parser": "@typescript-eslint/parser",
|
|
||||||
"parserOptions": {
|
|
||||||
"project": "./tsconfig.json"
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"import/no-cycle": "off",
|
|
||||||
"react/react-in-jsx-scope": "off",
|
|
||||||
"react/no-children-prop": "off",
|
|
||||||
"@typescript-eslint/no-unused-vars": "off",
|
|
||||||
"@typescript-eslint/no-unused-imports": "off",
|
|
||||||
"@typescript-eslint/no-unused-expressions": "off",
|
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
|
||||||
"@typescript-eslint/no-shadow": "off",
|
|
||||||
"@typescript-eslint/no-use-before-define": "off",
|
|
||||||
"@typescript-eslint/no-non-null-assertion": "off",
|
|
||||||
"no-continue": "off",
|
|
||||||
"linebreak-style": 0,
|
|
||||||
"import/extensions": "off",
|
|
||||||
"vitest/max-nested-describe": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"max": 3
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"testing-library/no-node-access": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"allowContainerFirstChild": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
public/favicon.png
Normal file
|
After Width: | Height: | Size: 110 KiB |
1
public/favicon.svg
Normal file
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 188 KiB |
@@ -1 +0,0 @@
|
|||||||
<svg viewBox="0 0 90 90" xmlns="http://www.w3.org/2000/svg"><g fill="none"><path fill="#31BEEC" d="M90 38.197v19.137L48.942 80.999V61.864z"/><path d="M41.086 61.863V81L0 57.333V38.197l18.566 10.687c.02.016.043.03.067.04l22.453 12.94Z" fill="#0095D5"/><path fill="#AEADAE" d="m61.621 45.506-16.607 9.576-16.622-9.576 16.622-9.575z"/><path fill="#0095D5" d="M86.086 31.416 69.464 40.99 48.942 29.15V10z"/><path fill="#31BEEC" d="M41.086 10v19.15l-20.55 11.827-16.621-9.561z"/></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 484 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><linearGradient id="a" x1="100%" x2="0" y1="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ff8d30"/><stop offset="1" stop-color="#e32929"/></linearGradient></defs><circle cx="50%" cy="50%" r="50%" fill="url(#a)"/><path fill="#fff" d="M246.6 200.8h18.7v110.6h-18.7zm-182.3 0H83v110.7H64.3zm91.1 123.9h18.7V367h-18.7zm-45.7-47.5h18.7v68.5h-18.7zm91.2 0h18.6v68.4h-18.6zm228.2-76.5h18.7v110.7h-18.7zM338 145.5h18.7v42.3H338zm45.7 21.2h18.7v68.2h-18.7zm-91.5 0h18.7v68.1h-18.7z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 577 B |
BIN
public/imgs/favicon.png
Normal file
|
After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 9.2 KiB |
@@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 483.71 327.04">
|
|
||||||
<defs>
|
|
||||||
<style>
|
|
||||||
.cls-1 {
|
|
||||||
fill: #fa5252;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</defs>
|
|
||||||
<path class="cls-1" d="M159.96,18.7c27.21,0,49.35,22.14,49.35,49.35v63.14c1.66-.56,3.4-.93,5.24-.93,5.56,0,10.45,2.76,13.46,6.97V68.05C228.01,30.53,197.49,0,159.96,0c-23.47,0-44.2,11.95-56.44,30.08,5.27,3.4,10.3,7.13,15.09,11.12,8.81-13.52,24.04-22.5,41.35-22.5Z"/>
|
|
||||||
<path class="cls-1" d="M269.15,130.26c1.84,0,3.59,.37,5.24,.93v-63.14c0-27.21,22.14-49.35,49.35-49.35,17.31,0,32.54,8.98,41.35,22.5,4.79-3.99,9.82-7.72,15.09-11.12C367.95,11.95,347.21,0,323.74,0c-37.52,0-68.05,30.53-68.05,68.05v69.18c3-4.2,7.89-6.96,13.45-6.96Z"/>
|
|
||||||
<path class="cls-1" d="M203.72,229.23c-33.72,8.1-62.37,26.51-83.25,51.05-11.51,13.49-20.67,28.91-27.04,45.39l44.02,.25,250.81,1.12s.04-.06,.04-.06c-27.59-73.49-106.29-116.57-184.57-97.75Z"/>
|
|
||||||
<path class="cls-1" d="M214.56,170.83c-9.15,0-16.56,7.41-16.56,16.56s7.41,16.56,16.56,16.56,16.56-7.41,16.56-16.56-7.41-16.56-16.56-16.56Z"/>
|
|
||||||
<path class="cls-1" d="M269.15,203.95c9.15,0,16.56-7.41,16.56-16.56s-7.41-16.56-16.56-16.56-16.56,7.41-16.56,16.56,7.41,16.56,16.56,16.56Z"/>
|
|
||||||
<path class="cls-1" d="M422.63,132.54l25.22-102.79s-.04-.04-.04-.04c-21.37,2.65-41.14,10.45-58.07,22.08-5.97,4.1-11.58,8.66-16.78,13.65-24.97,23.98-40.53,57.69-40.53,95.05,0,28.97,9.36,55.8,25.19,77.56,8.73,11.97,19.44,22.39,31.59,30.79l8.77-35.71c45.28-13.47,79.49-52.63,85.72-100.6h-61.07Z"/>
|
|
||||||
<path class="cls-1" d="M126.08,238.05c15.83-21.77,25.19-48.59,25.19-77.56,0-37.35-15.56-71.06-40.53-95.05-5.2-5-10.82-9.56-16.78-13.65-16.93-11.62-36.7-19.42-58.07-22.08,0,0-.04,0-.04,.04l25.22,102.79H0c6.22,47.97,40.44,87.14,85.72,100.6l8.77,35.71c12.16-8.41,22.86-18.82,31.59-30.79Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.8 KiB |
1
public/imgs/logo-color.svg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/imgs/logo.png
Normal file
|
After Width: | Height: | Size: 103 KiB |
247
public/imgs/logo.svg
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="1000.000000pt" height="1000.000000pt" viewBox="0 0 1000.000000 1000.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
|
||||||
|
<g transform="translate(0.000000,1000.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M6470 9752 c-179 -11 -423 -57 -605 -113 -94 -29 -116 -37 -212 -73
|
||||||
|
-381 -144 -693 -333 -1030 -621 -6 -5 -63 -61 -126 -123 l-114 -113 -179 88
|
||||||
|
c-223 110 -305 143 -386 158 -12 3 -34 8 -48 11 -14 3 -100 8 -191 10 -154 4
|
||||||
|
-171 3 -253 -21 -159 -46 -241 -93 -355 -201 -55 -53 -101 -100 -101 -104 0
|
||||||
|
-10 76 18 110 41 39 26 206 108 253 124 61 20 202 42 294 44 56 1 105 -6 178
|
||||||
|
-24 55 -15 110 -28 122 -31 76 -15 317 -112 410 -165 l52 -30 -78 -97 c-152
|
||||||
|
-190 -244 -324 -230 -333 8 -5 17 -9 20 -9 4 0 12 -13 19 -30 18 -44 5 -139
|
||||||
|
-39 -269 -20 -62 -34 -114 -31 -116 4 -2 24 14 45 35 22 22 43 40 49 40 5 0
|
||||||
|
23 -10 40 -23 56 -42 210 -135 276 -167 36 -17 72 -35 80 -39 37 -20 139 -43
|
||||||
|
187 -43 35 0 64 6 88 21 l36 21 57 -38 c31 -21 76 -46 100 -55 52 -21 149 -32
|
||||||
|
188 -23 l28 7 -29 23 -29 24 54 34 c78 49 180 84 191 67 37 -57 119 -207 165
|
||||||
|
-304 75 -157 122 -306 134 -421 16 -157 43 -193 152 -199 56 -4 62 -2 90 26
|
||||||
|
29 29 30 33 25 89 -13 122 -191 536 -326 759 -53 87 -58 100 -41 102 6 1 13 2
|
||||||
|
18 3 4 1 39 5 77 10 104 11 156 17 195 21 19 3 62 7 95 10 112 11 246 45 470
|
||||||
|
120 370 124 716 314 905 497 278 269 418 532 380 714 l-12 58 -35 -43 c-48
|
||||||
|
-57 -116 -90 -216 -102 -117 -15 -165 -29 -198 -56 -23 -19 -32 -22 -48 -14
|
||||||
|
-51 27 -95 7 -160 -75 -30 -37 -60 -64 -73 -66 -13 -2 -50 2 -83 10 -79 17
|
||||||
|
-112 10 -189 -43 -107 -73 -120 -78 -196 -70 -84 8 -97 2 -176 -82 -56 -59
|
||||||
|
-63 -63 -94 -58 -18 3 -37 8 -41 11 -4 2 -25 7 -47 10 -37 5 -43 2 -111 -60
|
||||||
|
l-71 -66 -65 0 c-90 0 -160 -28 -221 -90 -47 -47 -52 -50 -103 -50 -49 0 -57
|
||||||
|
-3 -94 -41 -48 -47 -65 -57 -92 -53 -11 1 -39 6 -62 9 -29 4 -43 11 -43 21 0
|
||||||
|
30 20 52 53 58 23 4 38 15 45 31 16 35 49 53 112 59 66 7 99 29 169 113 28 34
|
||||||
|
60 67 72 73 11 6 55 14 97 16 84 5 91 9 133 71 20 29 40 45 65 52 35 10 47 9
|
||||||
|
141 -10 61 -12 82 -4 163 65 57 49 103 62 173 52 41 -6 43 -5 85 44 68 79 92
|
||||||
|
86 268 80 84 -3 113 9 175 75 95 100 156 119 227 73 44 -29 61 -28 110 6 57
|
||||||
|
39 107 56 141 50 26 -6 38 1 92 49 72 66 120 79 184 53 21 -9 39 -15 40 -14 1
|
||||||
|
2 9 14 18 28 51 75 -5 176 -155 283 -146 104 -224 134 -478 182 -61 11 -221
|
||||||
|
34 -280 40 -69 8 -327 12 -400 7z"/>
|
||||||
|
<path d="M8256 8794 c-3 -8 -3 -46 0 -82 4 -47 1 -86 -10 -128 -9 -34 -16 -93
|
||||||
|
-16 -131 0 -44 -7 -92 -20 -128 -23 -66 -25 -108 -9 -186 9 -47 8 -60 -10
|
||||||
|
-102 -26 -60 -26 -101 -1 -196 20 -74 20 -75 0 -145 -13 -48 -19 -102 -19
|
||||||
|
-166 1 -135 -25 -322 -56 -403 -28 -75 -31 -112 -14 -185 13 -54 8 -78 -42
|
||||||
|
-189 -23 -52 -23 -53 -5 -108 l17 -55 -35 -79 c-33 -71 -36 -87 -36 -168 0
|
||||||
|
-122 -47 -273 -85 -273 -21 0 -19 21 14 138 17 57 32 131 36 165 3 34 17 104
|
||||||
|
31 155 23 81 25 99 15 137 -17 67 -14 90 21 158 34 67 36 86 57 467 6 95 14
|
||||||
|
160 25 190 19 49 15 93 -10 121 -15 16 -14 23 10 83 31 78 32 109 6 176 -27
|
||||||
|
70 -25 89 15 146 40 56 46 111 19 189 -23 69 -21 113 9 188 26 62 27 74 21
|
||||||
|
156 -6 80 -5 93 15 124 28 45 27 54 -10 73 -92 47 -184 -42 -338 -326 -161
|
||||||
|
-298 -197 -386 -285 -705 -103 -375 -123 -584 -96 -1025 12 -204 25 -312 52
|
||||||
|
-458 11 -62 18 -116 14 -119 -3 -3 -79 10 -168 30 -175 39 -357 74 -429 83
|
||||||
|
-24 3 -51 7 -58 10 -24 8 -159 18 -241 19 l-75 0 -3 -81 c-4 -127 -9 -124 233
|
||||||
|
-139 55 -3 111 -7 125 -10 14 -2 48 -6 77 -9 28 -3 77 -9 110 -15 32 -6 76
|
||||||
|
-13 98 -16 22 -4 56 -10 75 -15 19 -5 51 -11 70 -14 47 -8 85 -15 148 -30 l32
|
||||||
|
-8 0 -64 c0 -77 13 -110 75 -195 66 -90 81 -119 63 -130 -21 -14 -51 -10 -91
|
||||||
|
11 -44 24 -45 20 -18 -71 45 -149 37 -167 -56 -132 -10 4 5 -19 34 -50 28 -32
|
||||||
|
73 -92 99 -135 138 -222 189 -263 378 -302 107 -22 170 -49 187 -82 13 -23 14
|
||||||
|
-73 3 -120 -5 -25 -3 -28 21 -28 34 0 52 10 136 75 73 56 115 70 181 60 68
|
||||||
|
-11 138 46 104 84 -20 22 -21 18 62 191 35 74 80 183 100 242 l35 107 56 -40
|
||||||
|
c74 -53 164 -142 201 -199 91 -142 192 -648 151 -754 -19 -47 -5 -41 24 11 58
|
||||||
|
105 70 156 69 308 -1 121 -5 152 -27 226 -32 107 -94 250 -142 329 -45 75
|
||||||
|
-166 204 -234 250 -28 19 -51 39 -51 44 0 5 29 99 65 210 35 111 73 235 84
|
||||||
|
276 30 112 75 399 86 550 4 47 9 99 11 115 8 66 4 496 -6 593 -32 335 -162
|
||||||
|
788 -297 1042 -130 243 -283 386 -487 456 -82 28 -82 28 -90 8z"/>
|
||||||
|
<path d="M6300 7695 c-1 -143 -35 -481 -66 -659 -49 -276 -106 -466 -195 -644
|
||||||
|
-56 -112 -56 -113 -35 -127 41 -29 54 -19 102 76 149 298 211 539 229 904 7
|
||||||
|
142 -10 484 -25 499 -7 7 -10 -12 -10 -49z"/>
|
||||||
|
<path d="M4095 7698 c-3 -7 -6 -56 -7 -108 -3 -89 -4 -95 -23 -92 -11 2 -35
|
||||||
|
19 -52 39 -18 20 -34 34 -34 32 -1 -2 -3 -33 -4 -69 -4 -82 -13 -153 -27 -207
|
||||||
|
l-10 -43 -46 40 c-24 22 -48 40 -52 40 -11 0 -24 -221 -17 -309 6 -83 37 -178
|
||||||
|
66 -205 73 -66 245 -71 421 -12 58 19 130 45 160 56 30 12 69 26 86 31 31 9
|
||||||
|
31 10 36 87 3 56 12 94 33 140 15 34 25 65 22 68 -3 4 -18 7 -32 7 -40 0 -35
|
||||||
|
14 50 133 59 81 99 160 91 180 -3 8 -44 13 -123 17 -65 2 -127 7 -138 10 -127
|
||||||
|
33 -204 66 -321 137 -74 45 -73 45 -79 28z"/>
|
||||||
|
<path d="M3450 7544 c-123 -70 -410 -433 -412 -522 -2 -71 84 -177 137 -170
|
||||||
|
19 3 41 40 96 158 9 19 31 61 48 93 22 38 36 81 42 127 10 68 62 184 136 303
|
||||||
|
28 44 16 47 -47 11z"/>
|
||||||
|
<path d="M4972 7109 c-21 -6 -32 -15 -29 -23 3 -6 13 -40 22 -75 17 -60 19
|
||||||
|
-62 46 -56 15 3 45 2 66 -4 90 -23 132 -20 98 9 -33 28 -15 32 98 26 109 -7
|
||||||
|
226 -20 273 -32 22 -6 24 -4 18 27 -4 19 -9 37 -13 41 -7 8 -256 73 -316 82
|
||||||
|
-71 12 -229 14 -263 5z"/>
|
||||||
|
<path d="M4810 7085 c-36 -7 -81 -18 -100 -24 -67 -21 -66 -18 -35 -135 15
|
||||||
|
-58 33 -106 38 -106 14 0 135 68 142 80 3 5 26 12 50 16 25 3 45 8 45 11 0 3
|
||||||
|
-6 31 -14 62 -8 31 -17 68 -20 84 -7 30 -9 31 -106 12z"/>
|
||||||
|
<path d="M7315 6989 c-227 -53 -672 -275 -915 -457 -73 -55 -231 -196 -284
|
||||||
|
-252 l-48 -53 26 -25 25 -25 83 84 c119 121 227 202 478 361 113 72 265 152
|
||||||
|
437 232 216 100 260 123 268 136 7 12 -15 11 -70 -1z"/>
|
||||||
|
<path d="M2974 6954 c-7 -29 1 -307 14 -484 10 -129 25 -174 70 -212 48 -40
|
||||||
|
97 -53 127 -34 13 9 29 25 35 37 20 37 22 160 6 313 -9 82 -16 172 -16 202 l0
|
||||||
|
53 -30 -9 c-17 -5 -33 -9 -35 -10 -32 -5 -130 93 -140 141 -8 36 -23 37 -31 3z"/>
|
||||||
|
<path d="M2484 6858 c-73 -124 -162 -305 -184 -376 -24 -78 -17 -102 47 -142
|
||||||
|
57 -36 90 -39 103 -7 17 41 49 232 59 359 6 69 13 131 16 139 11 30 22 109 15
|
||||||
|
109 -4 0 -29 -37 -56 -82z"/>
|
||||||
|
<path d="M4563 6824 c-64 -39 -317 -95 -423 -94 -96 0 -119 4 -180 25 l-42 15
|
||||||
|
7 -28 c8 -32 34 -67 105 -142 28 -30 77 -84 108 -120 30 -36 89 -100 131 -142
|
||||||
|
l76 -78 -63 0 c-34 0 -62 -3 -62 -7 0 -32 78 -102 230 -208 47 -33 135 -96
|
||||||
|
195 -141 61 -44 120 -86 133 -93 29 -16 50 -4 127 69 33 31 80 70 105 86 25
|
||||||
|
16 47 31 50 35 5 6 110 66 185 106 85 45 76 75 -57 189 -57 48 -208 192 -336
|
||||||
|
318 -127 127 -235 232 -240 233 -4 1 -26 -9 -49 -23z"/>
|
||||||
|
<path d="M5840 6684 c-30 -8 -82 -14 -115 -13 -33 0 -66 0 -73 0 -10 -1 -12
|
||||||
|
-21 -10 -82 3 -75 5 -84 29 -101 49 -37 193 -36 216 1 14 23 29 211 17 210 -5
|
||||||
|
-1 -34 -7 -64 -15z"/>
|
||||||
|
<path d="M3914 6633 c-49 -114 -125 -336 -135 -397 -15 -86 -7 -135 27 -175
|
||||||
|
46 -55 140 -50 163 7 5 15 11 59 13 97 3 56 13 91 51 179 26 60 47 114 47 122
|
||||||
|
0 7 -20 36 -45 64 -25 28 -54 68 -65 90 -28 54 -37 56 -56 13z"/>
|
||||||
|
<path d="M5620 6407 c-12 -34 -36 -88 -53 -120 -16 -31 -28 -60 -25 -62 3 -3
|
||||||
|
41 3 84 13 43 11 112 20 153 21 41 1 78 4 81 6 4 3 10 30 14 60 3 31 13 72 21
|
||||||
|
92 14 33 14 35 -3 28 -9 -4 -51 -9 -92 -11 -57 -2 -85 1 -117 16 l-41 18 -22
|
||||||
|
-61z"/>
|
||||||
|
<path d="M2257 6308 c7 -119 45 -313 89 -448 54 -167 71 -198 116 -202 42 -4
|
||||||
|
98 9 120 29 22 20 19 36 -48 243 -61 190 -84 277 -84 314 0 17 -7 29 -17 32
|
||||||
|
-46 15 -100 41 -134 66 -22 16 -40 28 -42 28 -2 0 -2 -28 0 -62z"/>
|
||||||
|
<path d="M5935 6220 c-31 -44 -212 -222 -264 -259 -54 -38 -24 2 65 89 91 89
|
||||||
|
149 158 141 167 -7 6 -266 -22 -357 -39 -225 -42 -501 -216 -745 -470 -199
|
||||||
|
-206 -250 -272 -266 -349 -32 -150 60 -415 211 -604 152 -190 373 -343 525
|
||||||
|
-361 161 -19 456 6 511 43 23 16 231 377 296 513 36 76 104 281 153 464 35
|
||||||
|
128 30 177 -34 351 -69 185 -71 193 -71 248 0 44 -2 48 -16 36 -24 -20 -69
|
||||||
|
-114 -108 -229 -43 -124 -64 -154 -35 -49 33 121 103 284 150 351 11 14 19 30
|
||||||
|
19 35 0 5 -25 24 -55 42 -30 18 -59 39 -66 47 -17 21 -24 18 -54 -26z"/>
|
||||||
|
<path d="M6446 6230 c-44 -16 -83 -35 -88 -42 -9 -14 -2 -158 11 -204 12 -45
|
||||||
|
34 -52 78 -23 21 14 50 33 66 43 l27 17 -1 119 c0 66 -4 120 -7 119 -4 0 -43
|
||||||
|
-13 -86 -29z"/>
|
||||||
|
<path d="M3010 6219 c0 -59 289 -869 310 -869 4 0 14 24 20 53 25 105 54 140
|
||||||
|
113 133 20 -2 37 -3 37 -1 0 1 -24 70 -54 152 -30 83 -83 241 -119 351 l-63
|
||||||
|
200 -28 -34 c-23 -30 -33 -34 -72 -34 -53 0 -108 23 -129 54 -15 20 -15 20
|
||||||
|
-15 -5z"/>
|
||||||
|
<path d="M6244 6124 c-99 -79 -102 -86 -80 -181 10 -43 30 -114 43 -157 25
|
||||||
|
-80 25 -80 38 -50 7 16 36 60 64 99 42 56 51 74 46 95 -4 14 -12 73 -19 133
|
||||||
|
-7 59 -15 109 -17 112 -3 2 -36 -20 -75 -51z"/>
|
||||||
|
<path d="M3980 6022 c0 -6 -14 -19 -32 -28 -32 -16 -118 -16 -161 1 -12 5 12
|
||||||
|
-54 79 -191 53 -110 143 -298 201 -419 57 -121 111 -227 119 -235 13 -13 18
|
||||||
|
-11 41 20 15 19 50 59 80 88 29 29 53 57 53 63 0 6 -63 122 -139 257 -77 136
|
||||||
|
-162 294 -190 351 -28 57 -51 99 -51 93z"/>
|
||||||
|
<path d="M6710 5911 c0 -5 20 -53 44 -107 73 -168 156 -442 156 -520 0 -45 4
|
||||||
|
-55 27 -74 30 -23 30 -23 118 14 33 13 76 26 95 28 31 4 35 8 38 38 6 62 -52
|
||||||
|
170 -92 170 -12 0 -14 -5 -6 -25 10 -25 4 -55 -10 -55 -4 0 -17 30 -29 68 -34
|
||||||
|
105 -161 299 -270 415 -51 54 -71 68 -71 48z"/>
|
||||||
|
<path d="M2571 5645 c-46 -37 -105 -47 -129 -23 -24 24 -11 -5 45 -100 127
|
||||||
|
-218 184 -296 292 -402 58 -58 138 -126 176 -152 l70 -46 5 53 c5 56 23 85 72
|
||||||
|
115 l28 17 -55 37 c-69 48 -253 262 -405 473 -25 34 -47 63 -50 63 -3 0 -25
|
||||||
|
-16 -49 -35z"/>
|
||||||
|
<path d="M3451 5493 c-38 -19 -78 -74 -87 -121 -6 -27 0 -40 35 -86 81 -105
|
||||||
|
479 -476 511 -476 6 0 122 145 128 159 7 19 -301 349 -441 473 -42 37 -85 68
|
||||||
|
-95 68 -9 0 -32 -8 -51 -17z"/>
|
||||||
|
<path d="M6261 5478 c-5 -18 -26 -95 -46 -172 -43 -164 -75 -256 -122 -350
|
||||||
|
-19 -37 -33 -69 -31 -70 87 -59 168 -125 365 -303 50 -44 100 -86 112 -92 18
|
||||||
|
-10 21 -9 21 9 0 11 -9 38 -20 60 -35 69 -24 89 27 46 15 -13 96 -70 178 -127
|
||||||
|
152 -105 292 -181 354 -193 l33 -6 -16 25 c-76 115 -126 250 -166 440 -12 61
|
||||||
|
-31 146 -41 190 l-18 80 -88 83 c-47 46 -159 137 -247 203 -89 65 -187 139
|
||||||
|
-218 164 -32 25 -59 45 -62 45 -2 0 -9 -15 -15 -32z"/>
|
||||||
|
<path d="M4348 5238 c-144 -142 -397 -435 -508 -588 -30 -41 -57 -77 -61 -80
|
||||||
|
-3 -3 -47 -66 -96 -140 -171 -258 -272 -462 -317 -640 -15 -63 -15 -69 5 -140
|
||||||
|
25 -90 96 -235 155 -315 75 -101 203 -224 329 -313 233 -166 540 -300 669
|
||||||
|
-293 26 1 149 124 355 352 192 213 185 205 287 334 298 379 438 604 535 862
|
||||||
|
22 57 39 106 39 108 0 3 -10 0 -22 -6 -59 -31 -124 -39 -318 -35 -214 4 -266
|
||||||
|
13 -379 68 -226 110 -420 341 -526 628 -25 66 -28 90 -29 192 -1 65 -2 118 -2
|
||||||
|
118 -1 0 -53 -51 -116 -112z"/>
|
||||||
|
<path d="M7119 5202 c-40 -20 -88 -35 -123 -39 l-58 -6 6 -30 c3 -16 6 -54 6
|
||||||
|
-83 0 -70 22 -84 90 -59 25 9 71 25 103 34 32 9 62 23 66 29 8 13 -4 139 -17
|
||||||
|
169 -6 17 -12 16 -73 -15z"/>
|
||||||
|
<path d="M7547 5062 c-107 -101 -138 -112 -183 -67 -19 19 -25 35 -24 63 1 20
|
||||||
|
2 41 1 45 -1 5 -19 -14 -41 -42 -25 -31 -60 -61 -91 -77 -55 -27 -60 -29 -159
|
||||||
|
-49 -63 -13 -90 -32 -90 -64 0 -75 49 -233 138 -441 53 -125 57 -130 106 -130
|
||||||
|
22 0 68 7 101 14 33 8 105 17 160 20 55 4 108 9 118 12 16 5 16 7 -3 31 -13
|
||||||
|
17 -17 30 -11 36 5 5 76 16 158 24 81 7 159 16 173 19 l25 6 -22 18 c-13 10
|
||||||
|
-23 22 -23 27 0 4 63 8 139 8 124 0 181 9 143 22 -31 11 -107 70 -110 84 -2
|
||||||
|
10 16 31 46 53 28 20 53 43 56 51 17 46 -45 76 -176 85 -80 6 -105 12 -145 35
|
||||||
|
-71 41 -115 93 -163 189 -23 47 -46 86 -52 86 -5 0 -37 -26 -71 -58z"/>
|
||||||
|
<path d="M3110 5050 c-30 -32 -60 -89 -60 -113 0 -30 218 -189 335 -245 28
|
||||||
|
-13 70 -34 95 -45 25 -12 83 -46 129 -76 l83 -54 19 24 c38 49 99 140 99 148
|
||||||
|
0 7 -271 201 -294 210 -6 2 -38 23 -71 47 -94 65 -234 134 -273 134 -25 0 -41
|
||||||
|
-8 -62 -30z"/>
|
||||||
|
<path d="M6768 4376 c-23 -32 -125 -100 -168 -114 -19 -5 -61 -13 -94 -16 -32
|
||||||
|
-4 -66 -11 -77 -16 -18 -10 -17 -11 3 -45 16 -29 19 -47 16 -93 -3 -31 -9 -65
|
||||||
|
-13 -76 -8 -18 -4 -18 61 -11 90 9 200 47 272 92 31 20 91 69 132 111 69 68
|
||||||
|
73 75 56 86 -11 6 -48 30 -84 54 -82 56 -84 56 -104 28z"/>
|
||||||
|
<path d="M7617 4137 l-168 -258 19 -42 c29 -64 55 -82 118 -81 64 0 107 30
|
||||||
|
167 114 45 64 47 78 8 51 -59 -42 -69 -12 -20 62 37 57 51 147 47 306 l-3 105
|
||||||
|
-168 -257z"/>
|
||||||
|
<path d="M5727 4246 c-18 -28 -87 -175 -87 -186 0 -10 16 -15 90 -29 142 -26
|
||||||
|
251 -34 442 -35 240 -1 239 -2 245 86 5 62 -18 117 -57 135 -14 6 -63 14 -110
|
||||||
|
18 -47 4 -98 9 -115 10 -39 4 -264 17 -337 20 -49 2 -60 -1 -71 -19z"/>
|
||||||
|
<path d="M7380 3778 c-132 -121 -284 -208 -435 -248 -44 -12 -84 -26 -89 -31
|
||||||
|
-12 -11 56 -94 103 -124 51 -34 83 -37 155 -15 61 19 75 27 181 101 28 19 86
|
||||||
|
56 130 82 57 34 95 66 133 112 28 35 52 66 52 69 0 4 -18 3 -39 0 -51 -8 -98
|
||||||
|
18 -120 68 l-16 36 -55 -50z"/>
|
||||||
|
<path d="M5472 3742 c-73 -100 -95 -133 -91 -136 11 -10 139 -84 169 -98 83
|
||||||
|
-39 250 -94 340 -113 8 -2 54 -12 101 -24 99 -24 102 -24 94 -11 -3 5 5 31 19
|
||||||
|
57 23 45 32 58 91 124 l23 27 -96 36 c-272 104 -445 166 -472 171 -16 3 -40 9
|
||||||
|
-54 15 -15 5 -26 7 -26 5 0 -2 -11 0 -24 5 -23 8 -29 3 -74 -58z"/>
|
||||||
|
<path d="M3247 3598 c-86 -146 -197 -363 -197 -384 0 -31 93 -210 170 -329
|
||||||
|
111 -171 289 -335 485 -450 61 -36 171 -90 205 -100 14 -4 30 -12 37 -17 6 -5
|
||||||
|
34 -12 60 -15 l49 -5 175 150 c194 167 261 232 239 233 -16 1 -36 4 -90 15
|
||||||
|
-19 4 -40 8 -47 10 -15 3 -103 30 -168 51 -27 9 -66 26 -85 37 -38 22 -192
|
||||||
|
127 -200 136 -3 3 -36 31 -75 62 -150 119 -296 276 -368 395 -21 34 -59 116
|
||||||
|
-86 183 l-48 122 -56 -94z"/>
|
||||||
|
<path d="M6223 3515 c-36 -15 -91 -77 -99 -112 -9 -34 5 -72 36 -94 79 -58
|
||||||
|
450 -92 655 -60 86 13 205 49 205 63 0 5 -4 7 -8 4 -5 -3 -31 5 -58 18 -57 26
|
||||||
|
-130 103 -139 147 -4 16 -10 27 -14 25 -26 -16 -282 -25 -341 -12 -140 31
|
||||||
|
-200 36 -237 21z"/>
|
||||||
|
<path d="M5280 3493 c0 -4 -13 -24 -29 -43 -124 -152 -122 -149 -103 -167 10
|
||||||
|
-10 60 -58 112 -107 52 -50 145 -138 205 -196 169 -162 200 -185 252 -185 39
|
||||||
|
0 49 5 79 37 19 22 34 48 34 62 0 55 -269 393 -388 487 -94 75 -162 122 -162
|
||||||
|
112z"/>
|
||||||
|
<path d="M7664 3103 c-32 -43 -63 -83 -68 -89 -6 -6 -29 -31 -51 -55 -63 -68
|
||||||
|
-155 -144 -205 -169 -113 -56 -129 -89 -73 -151 19 -21 51 -48 70 -60 l34 -21
|
||||||
|
22 20 c12 11 39 25 59 31 32 11 108 79 108 98 0 4 -5 2 -12 -5 -18 -18 -38
|
||||||
|
-15 -38 6 0 10 34 69 75 132 74 113 127 229 138 303 3 20 4 37 2 37 -2 0 -30
|
||||||
|
-35 -61 -77z"/>
|
||||||
|
<path d="M2978 3107 c-21 -34 -53 -87 -73 -116 -66 -103 -66 -103 10 -253 37
|
||||||
|
-73 93 -169 124 -212 69 -96 201 -232 279 -284 125 -86 361 -182 444 -182 15
|
||||||
|
0 47 16 75 36 53 40 173 154 173 166 0 3 -26 12 -57 18 -159 33 -220 63 -387
|
||||||
|
189 -235 178 -341 305 -483 576 -35 69 -65 125 -66 125 -1 0 -19 -28 -39 -63z"/>
|
||||||
|
<path d="M5845 2923 c28 -66 6 -126 -53 -142 -20 -6 -43 -11 -51 -11 -25 0 7
|
||||||
|
-27 125 -106 208 -138 505 -293 577 -301 57 -7 65 7 28 50 -35 39 -53 80 -45
|
||||||
|
101 3 8 21 20 41 27 20 6 39 21 45 35 13 28 4 42 -32 49 -44 8 -95 28 -145 55
|
||||||
|
-90 49 -178 96 -320 170 -77 40 -144 77 -149 81 -17 15 -29 10 -21 -8z"/>
|
||||||
|
<path d="M2810 2819 c0 -6 -41 -92 -91 -192 l-90 -182 80 -160 c44 -88 100
|
||||||
|
-186 125 -217 98 -123 325 -272 503 -329 71 -22 72 -22 115 -4 28 13 87 63
|
||||||
|
172 149 l130 130 -55 11 c-174 36 -347 131 -537 295 -107 92 -167 175 -260
|
||||||
|
357 -70 139 -92 173 -92 142z"/>
|
||||||
|
<path d="M7160 2680 c-33 -16 -114 -36 -305 -74 -88 -18 -270 -25 -297 -12
|
||||||
|
-15 7 -18 3 -18 -20 0 -39 -12 -56 -51 -68 -18 -6 -34 -17 -37 -24 -6 -18 66
|
||||||
|
-83 122 -111 55 -27 122 -24 310 13 321 64 429 96 464 139 11 12 7 16 -20 21
|
||||||
|
-57 12 -118 81 -118 136 0 23 -4 24 -50 0z"/>
|
||||||
|
<path d="M2517 2261 c-49 -79 -87 -151 -87 -165 0 -136 113 -336 251 -444 112
|
||||||
|
-88 271 -171 355 -186 16 -3 40 -8 54 -11 106 -21 112 -20 169 31 29 26 75 80
|
||||||
|
103 118 l50 71 -29 3 c-128 12 -337 119 -478 245 -87 78 -147 164 -231 334
|
||||||
|
l-70 144 -87 -140z"/>
|
||||||
|
<path d="M1575 2228 c-31 -18 -52 -48 -91 -126 -55 -113 -65 -150 -71 -254
|
||||||
|
-10 -168 27 -325 92 -394 30 -31 38 -35 65 -29 71 16 287 113 626 281 l251
|
||||||
|
125 -24 87 c-59 212 -46 189 -106 201 -28 6 -65 13 -82 16 -28 5 -46 8 -105
|
||||||
|
20 -14 2 -41 7 -60 10 -19 3 -71 12 -115 20 -44 8 -96 17 -115 20 -19 3 -46 7
|
||||||
|
-60 10 -117 21 -185 25 -205 13z"/>
|
||||||
|
<path d="M2365 1759 c-44 -21 -168 -81 -275 -133 -240 -116 -441 -226 -497
|
||||||
|
-272 l-42 -34 15 -53 c21 -69 86 -190 145 -269 96 -128 273 -278 329 -278 27
|
||||||
|
0 34 8 165 175 52 66 277 383 375 529 l91 136 -102 120 c-56 66 -107 120 -113
|
||||||
|
119 -6 0 -47 -18 -91 -40z"/>
|
||||||
|
<path d="M2635 1413 c-44 -60 -136 -187 -205 -283 -69 -96 -147 -204 -172
|
||||||
|
-240 -26 -36 -58 -79 -71 -95 -14 -17 -35 -47 -47 -68 -31 -53 -16 -84 71
|
||||||
|
-147 96 -70 184 -113 294 -145 309 -90 341 -79 360 120 7 71 65 426 111 673
|
||||||
|
13 73 24 140 24 148 0 8 -24 25 -52 38 -29 13 -92 42 -140 65 -48 22 -88 41
|
||||||
|
-90 41 -2 0 -39 -48 -83 -107z"/>
|
||||||
|
<path d="M3130 1390 c-14 -4 -39 -8 -57 -9 -17 -1 -34 -5 -37 -10 -22 -36
|
||||||
|
-127 -689 -133 -833 -7 -162 -9 -160 106 -157 47 2 100 6 116 10 17 4 44 10
|
||||||
|
60 12 86 13 298 79 368 114 66 33 74 54 47 134 -29 88 -159 348 -283 564 -95
|
||||||
|
166 -105 180 -133 182 -16 1 -40 -2 -54 -7z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 16 KiB |
@@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 483.71 327.04">
|
|
||||||
<defs>
|
|
||||||
<style>
|
|
||||||
.cls-1 {
|
|
||||||
fill: #fa5252;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</defs>
|
|
||||||
<path class="cls-1" d="M159.96,18.7c27.21,0,49.35,22.14,49.35,49.35v63.14c1.66-.56,3.4-.93,5.24-.93,5.56,0,10.45,2.76,13.46,6.97V68.05C228.01,30.53,197.49,0,159.96,0c-23.47,0-44.2,11.95-56.44,30.08,5.27,3.4,10.3,7.13,15.09,11.12,8.81-13.52,24.04-22.5,41.35-22.5Z"/>
|
|
||||||
<path class="cls-1" d="M269.15,130.26c1.84,0,3.59,.37,5.24,.93v-63.14c0-27.21,22.14-49.35,49.35-49.35,17.31,0,32.54,8.98,41.35,22.5,4.79-3.99,9.82-7.72,15.09-11.12C367.95,11.95,347.21,0,323.74,0c-37.52,0-68.05,30.53-68.05,68.05v69.18c3-4.2,7.89-6.96,13.45-6.96Z"/>
|
|
||||||
<path class="cls-1" d="M203.72,229.23c-33.72,8.1-62.37,26.51-83.25,51.05-11.51,13.49-20.67,28.91-27.04,45.39l44.02,.25,250.81,1.12s.04-.06,.04-.06c-27.59-73.49-106.29-116.57-184.57-97.75Z"/>
|
|
||||||
<path class="cls-1" d="M214.56,170.83c-9.15,0-16.56,7.41-16.56,16.56s7.41,16.56,16.56,16.56,16.56-7.41,16.56-16.56-7.41-16.56-16.56-16.56Z"/>
|
|
||||||
<path class="cls-1" d="M269.15,203.95c9.15,0,16.56-7.41,16.56-16.56s-7.41-16.56-16.56-16.56-16.56,7.41-16.56,16.56,7.41,16.56,16.56,16.56Z"/>
|
|
||||||
<path class="cls-1" d="M422.63,132.54l25.22-102.79s-.04-.04-.04-.04c-21.37,2.65-41.14,10.45-58.07,22.08-5.97,4.1-11.58,8.66-16.78,13.65-24.97,23.98-40.53,57.69-40.53,95.05,0,28.97,9.36,55.8,25.19,77.56,8.73,11.97,19.44,22.39,31.59,30.79l8.77-35.71c45.28-13.47,79.49-52.63,85.72-100.6h-61.07Z"/>
|
|
||||||
<path class="cls-1" d="M126.08,238.05c15.83-21.77,25.19-48.59,25.19-77.56,0-37.35-15.56-71.06-40.53-95.05-5.2-5-10.82-9.56-16.78-13.65-16.93-11.62-36.7-19.42-58.07-22.08,0,0-.04,0-.04,.04l25.22,102.79H0c6.22,47.97,40.44,87.14,85.72,100.6l8.77,35.71c12.16-8.41,22.86-18.82,31.59-30.79Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 9.2 KiB |
@@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 483.71 327.04">
|
|
||||||
<defs>
|
|
||||||
<style>
|
|
||||||
.cls-1 {
|
|
||||||
fill: #fa5252;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</defs>
|
|
||||||
<path class="cls-1" d="M159.96,18.7c27.21,0,49.35,22.14,49.35,49.35v63.14c1.66-.56,3.4-.93,5.24-.93,5.56,0,10.45,2.76,13.46,6.97V68.05C228.01,30.53,197.49,0,159.96,0c-23.47,0-44.2,11.95-56.44,30.08,5.27,3.4,10.3,7.13,15.09,11.12,8.81-13.52,24.04-22.5,41.35-22.5Z"/>
|
|
||||||
<path class="cls-1" d="M269.15,130.26c1.84,0,3.59,.37,5.24,.93v-63.14c0-27.21,22.14-49.35,49.35-49.35,17.31,0,32.54,8.98,41.35,22.5,4.79-3.99,9.82-7.72,15.09-11.12C367.95,11.95,347.21,0,323.74,0c-37.52,0-68.05,30.53-68.05,68.05v69.18c3-4.2,7.89-6.96,13.45-6.96Z"/>
|
|
||||||
<path class="cls-1" d="M203.72,229.23c-33.72,8.1-62.37,26.51-83.25,51.05-11.51,13.49-20.67,28.91-27.04,45.39l44.02,.25,250.81,1.12s.04-.06,.04-.06c-27.59-73.49-106.29-116.57-184.57-97.75Z"/>
|
|
||||||
<path class="cls-1" d="M214.56,170.83c-9.15,0-16.56,7.41-16.56,16.56s7.41,16.56,16.56,16.56,16.56-7.41,16.56-16.56-7.41-16.56-16.56-16.56Z"/>
|
|
||||||
<path class="cls-1" d="M269.15,203.95c9.15,0,16.56-7.41,16.56-16.56s-7.41-16.56-16.56-16.56-16.56,7.41-16.56,16.56,7.41,16.56,16.56,16.56Z"/>
|
|
||||||
<path class="cls-1" d="M422.63,132.54l25.22-102.79s-.04-.04-.04-.04c-21.37,2.65-41.14,10.45-58.07,22.08-5.97,4.1-11.58,8.66-16.78,13.65-24.97,23.98-40.53,57.69-40.53,95.05,0,28.97,9.36,55.8,25.19,77.56,8.73,11.97,19.44,22.39,31.59,30.79l8.77-35.71c45.28-13.47,79.49-52.63,85.72-100.6h-61.07Z"/>
|
|
||||||
<path class="cls-1" d="M126.08,238.05c15.83-21.77,25.19-48.59,25.19-77.56,0-37.35-15.56-71.06-40.53-95.05-5.2-5-10.82-9.56-16.78-13.65-16.93-11.62-36.7-19.42-58.07-22.08,0,0-.04,0-.04,.04l25.22,102.79H0c6.22,47.97,40.44,87.14,85.72,100.6l8.77,35.71c12.16-8.41,22.86-18.82,31.59-30.79Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 11 KiB |
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"metaTitle": "创建账号",
|
|
||||||
"title": "创建账号",
|
|
||||||
"text": "请在下面定义您的凭据",
|
|
||||||
"form": {
|
|
||||||
"fields": {
|
|
||||||
"username": {
|
|
||||||
"label": "用户名"
|
|
||||||
},
|
|
||||||
"password": {
|
|
||||||
"label": "密码"
|
|
||||||
},
|
|
||||||
"passwordConfirmation": {
|
|
||||||
"label": "确认密码"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"buttons": {
|
|
||||||
"submit": "创建账号"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notifications": {
|
|
||||||
"loading": {
|
|
||||||
"title": "正在创建账号...",
|
|
||||||
"text": "请稍等"
|
|
||||||
},
|
|
||||||
"success": {
|
|
||||||
"title": "账号已创建",
|
|
||||||
"text": "您的账号创建成功"
|
|
||||||
},
|
|
||||||
"error": {
|
|
||||||
"title": "错误",
|
|
||||||
"text": "出错了,出现以下错误: {{error}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
{
|
|
||||||
"metaTitle": "登录",
|
|
||||||
"title": "欢迎回来!",
|
|
||||||
"text": "请确认您的凭证",
|
|
||||||
"form": {
|
|
||||||
"fields": {
|
|
||||||
"username": {
|
|
||||||
"label": "用户名"
|
|
||||||
},
|
|
||||||
"password": {
|
|
||||||
"label": "密码"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"buttons": {
|
|
||||||
"submit": "登录"
|
|
||||||
},
|
|
||||||
"afterLoginRedirection": "登录后,您将被重定向到 {{url}}",
|
|
||||||
"providersEmpty": {
|
|
||||||
"title": "验证提供程序错误",
|
|
||||||
"message": "服务提供商未设置,请检查您的日志获取更多信息。"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"alert": "您的凭据不正确或此账户不存在。请重试。"
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"header": {
|
|
||||||
"customize": "自定义面板"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"metaTitle": "自定义 {{name}} 面板",
|
|
||||||
"pageTitle": "自定义 {{name}} 面板",
|
|
||||||
"backToBoard": "返回面板",
|
|
||||||
"settings": {
|
|
||||||
"appearance": {
|
|
||||||
"primaryColor": "主体色",
|
|
||||||
"secondaryColor": "辅助色"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"save": {
|
|
||||||
"button": "保存更改",
|
|
||||||
"note": "小心,您有未保存的更改!"
|
|
||||||
},
|
|
||||||
"notifications": {
|
|
||||||
"pending": {
|
|
||||||
"title": "自定义保存中",
|
|
||||||
"message": "请稍候,我们正在保存您的自定义"
|
|
||||||
},
|
|
||||||
"success": {
|
|
||||||
"title": "已保存自定义",
|
|
||||||
"message": "您的自定义已成功保存"
|
|
||||||
},
|
|
||||||
"error": {
|
|
||||||
"title": "错误",
|
|
||||||
"message": "无法保存更改"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
{
|
|
||||||
"save": "保存",
|
|
||||||
"apply": "应用",
|
|
||||||
"insert": "插入",
|
|
||||||
"about": "关于",
|
|
||||||
"cancel": "取消",
|
|
||||||
"close": "关闭",
|
|
||||||
"back": "返回",
|
|
||||||
"delete": "删除",
|
|
||||||
"ok": "确定",
|
|
||||||
"edit": "编辑",
|
|
||||||
"next": "下一步",
|
|
||||||
"previous": "上一步",
|
|
||||||
"confirm": "确认",
|
|
||||||
"enabled": "已启用",
|
|
||||||
"duplicate": "复制",
|
|
||||||
"disabled": "已禁用",
|
|
||||||
"enableAll": "全部启用",
|
|
||||||
"disableAll": "全部禁用",
|
|
||||||
"setTimer": "设置计时器",
|
|
||||||
"version": "版本",
|
|
||||||
"changePosition": "换位",
|
|
||||||
"remove": "删除",
|
|
||||||
"removeConfirm": "你确定要删除 {{item}} 吗?",
|
|
||||||
"createItem": "创建{{item}}",
|
|
||||||
"sections": {
|
|
||||||
"settings": "设置",
|
|
||||||
"dangerZone": "危险"
|
|
||||||
},
|
|
||||||
"secrets": {
|
|
||||||
"apiKey": "API密钥",
|
|
||||||
"username": "用户名",
|
|
||||||
"password": "密码"
|
|
||||||
},
|
|
||||||
"tip": "提示: ",
|
|
||||||
"time": {
|
|
||||||
"seconds": "秒",
|
|
||||||
"minutes": "分钟",
|
|
||||||
"hours": "小时"
|
|
||||||
},
|
|
||||||
"loading": "正在加载...",
|
|
||||||
"breakPoints": {
|
|
||||||
"small": "小",
|
|
||||||
"medium": "中",
|
|
||||||
"large": "大"
|
|
||||||
},
|
|
||||||
"seeMore": "查看更多...",
|
|
||||||
"position": {
|
|
||||||
"left": "左边",
|
|
||||||
"center": "居中",
|
|
||||||
"right": "右边"
|
|
||||||
},
|
|
||||||
"attributes": {
|
|
||||||
"width": "宽度",
|
|
||||||
"height": "高度"
|
|
||||||
},
|
|
||||||
"public": "公开",
|
|
||||||
"restricted": "限制"
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"modals": {
|
|
||||||
"blockedPopups": {
|
|
||||||
"title": "阻止弹出窗口",
|
|
||||||
"text": "您的浏览器阻止了 Homarr 访问其 API。最常见的原因是广告拦截器或权限被拒绝。Homarr 无法自动请求权限。",
|
|
||||||
"list": {
|
|
||||||
"browserPermission": "点击链接旁的图标并检查权限,允许弹出窗口",
|
|
||||||
"adBlockers": "禁用浏览器中的广告拦截器和安全工具",
|
|
||||||
"otherBrowser": "尝试使用其它的浏览器"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"actions": {
|
|
||||||
"category": {
|
|
||||||
"openAllInNewTab": "在新标签页中打开全部内容"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"menu": {
|
|
||||||
"moveUp": "上移",
|
|
||||||
"moveDown": "下移",
|
|
||||||
"addCategory": "{{location}}添加分类",
|
|
||||||
"addAbove": "在上方",
|
|
||||||
"addBelow": "在下方"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
{
|
|
||||||
"modal": {
|
|
||||||
"title": "添加新磁贴",
|
|
||||||
"text": "磁贴是 Homarr 的主要组成元素。它们被用来显示你的应用程序和其他信息。您可以根据需要增加任意数量的磁贴。"
|
|
||||||
},
|
|
||||||
"widgetDescription": "组件与您的应用交互,为您提供更多的应用程序控制。它们在使用前通常需要额外的配置。",
|
|
||||||
"goBack": "上一步",
|
|
||||||
"actionIcon": {
|
|
||||||
"tooltip": "添加磁贴"
|
|
||||||
},
|
|
||||||
"apps": "应用",
|
|
||||||
"app": {
|
|
||||||
"defaultName": "您的应用"
|
|
||||||
},
|
|
||||||
"widgets": "组件",
|
|
||||||
"categories": "分类",
|
|
||||||
"category": {
|
|
||||||
"newName": "新分类名称",
|
|
||||||
"defaultName": "新建分类",
|
|
||||||
"created": {
|
|
||||||
"title": "分类已创建",
|
|
||||||
"message": "已创建分类\"{{name}}\""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"importFromDocker": "从 docker 导入"
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "拒绝访问",
|
|
||||||
"text": "您没有足够的权限访问此页面。如果你相信, 这不是有意的, 请联系您的系统管理员。",
|
|
||||||
"switchAccount": "切换到其他账户"
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "无法找到页面",
|
|
||||||
"text": "找不到该页面。该页面的 URL 可能已过期、URL 无效或您现在没有访问该资源所需的权限。",
|
|
||||||
"button": "返回首页"
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"search": {
|
|
||||||
"label": "搜索",
|
|
||||||
"engines": {
|
|
||||||
"web": "在网上搜索 {{query}}",
|
|
||||||
"youtube": "在 YouTube 上搜索 {{query}}",
|
|
||||||
"torrent": "搜索 {{query}} Torrents",
|
|
||||||
"movie": "在 {{app}} 上搜索 {{query}}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"actions": {
|
|
||||||
"avatar": {
|
|
||||||
"switchTheme": "切换主题",
|
|
||||||
"preferences": "用户选项",
|
|
||||||
"defaultBoard": "默认面板",
|
|
||||||
"manage": "管理中心",
|
|
||||||
"logout": "注销 {{username}}",
|
|
||||||
"login": "登录"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"modals": {
|
|
||||||
"movie": {
|
|
||||||
"title": "",
|
|
||||||
"topResults": "最高 {{count}} 结果为 <b>{{search}}</b>。"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "在编辑模式下,您可以调整磁贴和配置应用。在退出编辑模式之前不会保存更改。",
|
|
||||||
"button": {
|
|
||||||
"disabled": "进入编辑模式",
|
|
||||||
"enabled": "退出并保存"
|
|
||||||
},
|
|
||||||
"popover": {
|
|
||||||
"title": "启用 <1>{{size}}</1> 尺寸编辑模式",
|
|
||||||
"text": "现在您可以调整和配置您的应用了,在退出编辑模式之前<strong>不会保存</strong>更改 。"
|
|
||||||
},
|
|
||||||
"unloadEvent": "退出编辑模式以保存更改"
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
"navigation": {
|
|
||||||
"home": {
|
|
||||||
"title": "首页"
|
|
||||||
},
|
|
||||||
"boards": {
|
|
||||||
"title": "面板"
|
|
||||||
},
|
|
||||||
"users": {
|
|
||||||
"title": "用户",
|
|
||||||
"items": {
|
|
||||||
"manage": "管理",
|
|
||||||
"invites": "邀请"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"help": {
|
|
||||||
"title": "帮助",
|
|
||||||
"items": {
|
|
||||||
"documentation": "文档",
|
|
||||||
"report": "报告问题 / bug",
|
|
||||||
"discord": "Discord 社区",
|
|
||||||
"contribute": "贡献"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tools": {
|
|
||||||
"title": "工具",
|
|
||||||
"items": {
|
|
||||||
"docker": "Docker",
|
|
||||||
"api": "API",
|
|
||||||
"migrate": "迁移到 1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"about": {
|
|
||||||
"title": "关于"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "{{position}} 侧边栏"
|
|
||||||
}
|
|
||||||