diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml
index b02b79780..8b973d92f 100644
--- a/.github/ISSUE_TEMPLATE/feature-request.yml
+++ b/.github/ISSUE_TEMPLATE/feature-request.yml
@@ -1,12 +1,13 @@
name: โจ Feature Request
description: Request a feature to help improve Homarr!
title: '
'
+labels: ['โจ Feature']
body:
- type: textarea
id: feature
attributes:
label: Description
- description: Describe the feature you would like to see. Tell us how you imagine it and try to provide as much usefull information as possible. **PLEASE** use images or drawings or anything to image your thoughts. Also please do not say "Like X and Y do" as we sometimes don't know what X and Y are.
+ description: Describe the feature you would like to see. Tell us how you imagine it and try to provide as much useful information as possible. **PLEASE** use images/screenshots, include details about X & Y when requesting changes like X & Y service does, make your description atleast 300 characters. Having an unclear issue with too little detail will result in your issue being marked as invalid and closed.
placeholder: An outline of the feature you would like to see implemented, include as much detail as possible!
validations:
required: true
@@ -21,3 +22,13 @@ body:
- High (App breaking feature)
validations:
required: true
+ - type: checkboxes
+ id: idiot-check
+ attributes:
+ label: Please tick the boxes
+ description: Before submitting, please ensure that
+ options:
+ - 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
diff --git a/.github/ISSUE_TEMPLATE/idea.yml b/.github/ISSUE_TEMPLATE/idea.yml
new file mode 100644
index 000000000..594101d00
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/idea.yml
@@ -0,0 +1,23 @@
+name: ๐ค Idea
+description: Tell us your idea! We may implement it.
+title: ''
+labels: ['๐ค Idea']
+body:
+ - type: textarea
+ id: feature
+ attributes:
+ label: Description
+ description: Tell us your idea! Please add as much details as possible.
+ placeholder: Maybe move ... to ...! Maybe add the version of Homarr somewhere...! Etc.
+ validations:
+ required: true
+ - type: checkboxes
+ id: idiot-check
+ attributes:
+ label: Please tick the boxes
+ description: Before submitting, please ensure that
+ options:
+ - 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
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 0270806fe..4bd399d2a 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -1,18 +1,24 @@
-name: Build and publish Docker image
+name: Master docker CI
+# Workflow to build and publish docker image
on:
push:
+ branches: [master]
tags:
- v*
workflow_dispatch:
env:
- IMAGE_NAME: homarr
+ # Use docker.io for Docker Hub if empty
+ REGISTRY: ghcr.io
+ # github.repository as /
+ IMAGE_NAME: ${{ github.repository }}
jobs:
# Push image to GitHub Packages.
# See also https://docs.docker.com/docker-hub/builds/
- build:
+ yarn_install_and_build:
+ # Will run yarn install && yarn build
runs-on: ubuntu-latest
steps:
- name: Setup
@@ -20,9 +26,11 @@ jobs:
- 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:
@@ -43,6 +51,7 @@ jobs:
- run: yarn install --frozen-lockfile
- run: yarn build
- name: Cache build output
+ # to copy needed files to docker build job
uses: actions/cache@v2
id: restore-build
with:
@@ -52,11 +61,11 @@ jobs:
./public/
./.next/static/
./.next/standalone/
- ./packages.jsan
+ ./packages.json
key: ${{ github.sha }}
- docker:
- needs: [build]
+ docker_image_build_and_push:
+ needs: [yarn_install_and_build]
runs-on: ubuntu-latest
permissions:
packages: write
@@ -73,14 +82,14 @@ jobs:
./public/
./.next/static/
./.next/standalone/
- ./packages.jsan
+ ./packages.json
key: ${{ github.sha }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
# list of Docker images to use as base name for tags
- images: ghcr.io/${{ github.repository }}
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# generate Docker tags based on the following events/attributes
tags: |
type=raw,value=latest
@@ -90,7 +99,6 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to GHCR
- if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
registry: ghcr.io
diff --git a/.github/workflows/docker_dev.yml b/.github/workflows/docker_dev.yml
new file mode 100644
index 000000000..cbf6b819f
--- /dev/null
+++ b/.github/workflows/docker_dev.yml
@@ -0,0 +1,116 @@
+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:
+ push:
+ branches: [dev]
+ pull_request:
+ workflow_dispatch:
+ inputs:
+ tags:
+ requierd: true
+ description: 'Tags to deploy to'
+
+env:
+ # Use docker.io for Docker Hub if empty
+ REGISTRY: ghcr.io
+ # github.repository as /
+ IMAGE_NAME: ${{ github.repository }}
+
+jobs:
+ # Push image to GitHub Packages.
+ # See also https://docs.docker.com/docker-hub/builds/
+ yarn_install_and_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
+ id: yarn-cache-dir-path
+ run: echo "::set-output name=dir::$(yarn cache dir)"
+ - name: Yarn cache
+ 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 --frozen-lockfile
+ - run: yarn 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 }}
+
+ docker_image_build_and_push:
+ needs: [yarn_install_and_build]
+ runs-on: ubuntu-latest
+ permissions:
+ packages: write
+ contents: read
+ steps:
+ - name: Checkout
+ uses: actions/checkout@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
+ id: meta
+ uses: docker/metadata-action@v4
+ with:
+ # list of Docker images to use as base name for tags
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
+ # generate Docker tags based on the following events/attributes
+ tags: |
+ type=ref,event=pr
+ tpye=raw,value=dev,priority=1
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v2
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v2
+ - name: Login to GHCR
+ uses: docker/login-action@v2
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Build and push
+ uses: docker/build-push-action@v3
+ with:
+ platforms: linux/amd64,linux/arm64,linux/arm/v7
+ context: .
+ push: true
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
diff --git a/.storybook/main.js b/.storybook/main.js
index d1506f5e8..6449361d8 100644
--- a/.storybook/main.js
+++ b/.storybook/main.js
@@ -1,5 +1,5 @@
module.exports = {
- stories: ['../components/**/*.story.mdx', '../components/**/*.story.*'],
+ stories: ['../src/components/**/*.story.mdx', '../src/components/**/*.story.*'],
addons: [
'storybook-dark-mode',
'@storybook/addon-links',
diff --git a/Dockerfile b/Dockerfile
index 5d13c04aa..95fbce619 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -10,11 +10,10 @@ COPY /package.json ./package.json
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
-COPY --chown=nextjs:nodejs /.next/standalone ./
-COPY --chown=nextjs:nodejs /.next/static ./.next/static
+COPY /.next/standalone ./
+COPY /.next/static ./.next/static
-USER nextjs
EXPOSE 7575
ENV PORT 7575
VOLUME /app/data/configs
-CMD ["node", "server.js"]
+CMD ["node", "server.js"]
\ No newline at end of file
diff --git a/README.md b/README.md
index f0c01a4ca..a05fd2ef5 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,17 @@
-
Homarr
+
+
+
+
+
+
+
+
+
-
+
+
+
A homepage for your server.
@@ -11,10 +21,11 @@
Join the discord!
-
+
+
+
-
# ๐ Table of Contents
- [๐ Table of Contents](#-table-of-contents)
- [๐ Getting Started](#-getting-started)
@@ -34,11 +45,6 @@ Homarr is a simple and lightweight homepage for your server, that helps you easi
**[โคด๏ธ Back to Top](#-table-of-contents)**
-## ๐ Known Issues
-
-- Application cards not responsive https://github.com/ajnart/homarr/issues/47
-- Icon alignment out for specific icons https://github.com/ajnart/homarr/issues/82
-
## โก Installation
### Deploying from Docker Image ๐ณ
diff --git a/components/AppShelf/AppShelf.tsx b/components/AppShelf/AppShelf.tsx
deleted file mode 100644
index af5f85340..000000000
--- a/components/AppShelf/AppShelf.tsx
+++ /dev/null
@@ -1,93 +0,0 @@
-import React, { useState } from 'react';
-import { motion } from 'framer-motion';
-import { Text, AspectRatio, SimpleGrid, Card, Image, Group, Space } from '@mantine/core';
-import { useConfig } from '../../tools/state';
-import { serviceItem } from '../../tools/types';
-import AddItemShelfItem from './AddAppShelfItem';
-import { AppShelfItemWrapper } from './AppShelfItemWrapper';
-import AppShelfMenu from './AppShelfMenu';
-
-const AppShelf = () => {
- const { config } = useConfig();
-
- return (
-
- {config.services.map((service) => (
-
- ))}
-
-
- );
-};
-
-export function AppShelfItem(props: any) {
- const { service }: { service: serviceItem } = props;
- const [hovering, setHovering] = useState(false);
- return (
- {
- setHovering(true);
- }}
- onHoverEnd={() => {
- setHovering(false);
- }}
- >
-
-
-
-
-
- {service.name}
-
-
-
-
-
-
-
-
-
- {
- window.open(service.url);
- }}
- style={{
- maxWidth: '50%',
- marginBottom: 10,
- }}
- src={service.icon}
- />
-
-
-
-
-
- );
-}
-
-export default AppShelf;
diff --git a/components/Welcome/Welcome.story.tsx b/components/Welcome/Welcome.story.tsx
deleted file mode 100644
index 9c4600005..000000000
--- a/components/Welcome/Welcome.story.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-import { Welcome } from './Welcome';
-
-export default {
- title: 'Welcome',
-};
-
-export const Usage = () => ;
diff --git a/components/Welcome/Welcome.styles.ts b/components/Welcome/Welcome.styles.ts
deleted file mode 100644
index d1b99469f..000000000
--- a/components/Welcome/Welcome.styles.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { createStyles } from '@mantine/core';
-
-export default createStyles((theme) => ({
- title: {
- color: theme.colorScheme === 'dark' ? theme.white : theme.black,
- fontSize: 100,
- fontWeight: 900,
- letterSpacing: -2,
-
- [theme.fn.smallerThan('md')]: {
- fontSize: 50,
- },
- },
-}));
diff --git a/components/Welcome/Welcome.test.tsx b/components/Welcome/Welcome.test.tsx
deleted file mode 100644
index c3b94254e..000000000
--- a/components/Welcome/Welcome.test.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import { render, screen } from '@testing-library/react';
-import { Welcome } from './Welcome';
-
-describe('Welcome component', () => {
- it('has correct Next.js theming section link', () => {
- render();
- expect(screen.getByText('this guide')).toHaveAttribute(
- 'href',
- 'https://mantine.dev/theming/next/'
- );
- });
-});
diff --git a/components/Welcome/Welcome.tsx b/components/Welcome/Welcome.tsx
deleted file mode 100644
index 8ade7ec0b..000000000
--- a/components/Welcome/Welcome.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { Title, Text, Anchor } from '@mantine/core';
-import useStyles from './Welcome.styles';
-
-export function Welcome() {
- const { classes } = useStyles();
-
- return (
- <>
-
- Welcome to{' '}
-
- Mantine
-
-
-
- This starter Next.js project includes a minimal setup for server side rendering, if you want
- to learn more on Mantine + Next.js integration follow{' '}
-
- this guide
-
- . To get started edit index.tsx file.
-
- >
- );
-}
diff --git a/components/layout/Logo.tsx b/components/layout/Logo.tsx
deleted file mode 100644
index 824688a1b..000000000
--- a/components/layout/Logo.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import { Text } from '@mantine/core';
-import * as React from 'react';
-
-export function Logo({ style }: any) {
- return (
-
- Homarr
-
- );
-}
diff --git a/data/configs/config_new.json b/data/configs/config_new.json
index a938826f0..283a8b971 100644
--- a/data/configs/config_new.json
+++ b/data/configs/config_new.json
@@ -10,7 +10,7 @@
],
"settings": {
"searchBar": true,
- "searchUrl": "https://google.com/search?q=",
+ "searchUrl": "https://duckduckgo.com/?q=",
"enabledModules": []
}
}
\ No newline at end of file
diff --git a/data/constants.ts b/data/constants.ts
index 3d4ed3dad..a03b01ee9 100644
--- a/data/constants.ts
+++ b/data/constants.ts
@@ -1,2 +1,2 @@
export const REPO_URL = 'ajnart/homarr';
-export const CURRENT_VERSION = 'v0.2.0';
+export const CURRENT_VERSION = 'v0.3.0';
diff --git a/jest.config.js b/jest.config.js
deleted file mode 100644
index 7365fc753..000000000
--- a/jest.config.js
+++ /dev/null
@@ -1,16 +0,0 @@
-const nextJest = require('next/jest');
-
-const createJestConfig = nextJest({
- dir: './',
-});
-
-const customJestConfig = {
- setupFilesAfterEnv: ['/jest.setup.js'],
- moduleNameMapper: {
- '^@/components/(.*)$': '/components/$1',
- '^@/pages/(.*)$': '/pages/$1',
- },
- testEnvironment: 'jest-environment-jsdom',
-};
-
-module.exports = createJestConfig(customJestConfig);
diff --git a/jest.setup.js b/jest.setup.js
deleted file mode 100644
index 666127af3..000000000
--- a/jest.setup.js
+++ /dev/null
@@ -1 +0,0 @@
-import '@testing-library/jest-dom/extend-expect';
diff --git a/package.json b/package.json
index 961298b49..6c6ee0354 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
{
"name": "homarr",
- "version": "0.1.6",
+ "version": "0.3.0",
"private": "false",
- "description": "Homarr - A homepage for your server.",
+ "description": "Homarr - A homepage for your server.",
"repository": {
"type": "git",
"url": "https://github.com/ajnart/homarr"
diff --git a/public/favicon.png b/public/favicon.png
new file mode 100644
index 000000000..8565f6c31
Binary files /dev/null and b/public/favicon.png differ
diff --git a/public/favicon.svg b/public/favicon.svg
index 5b4f8fe08..c5c6c1a70 100644
--- a/public/favicon.svg
+++ b/public/favicon.svg
@@ -1,6 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/public/imgs/favicon.png b/public/imgs/favicon.png
new file mode 100644
index 000000000..8565f6c31
Binary files /dev/null and b/public/imgs/favicon.png differ
diff --git a/public/imgs/logo-color.svg b/public/imgs/logo-color.svg
new file mode 100644
index 000000000..c5c6c1a70
--- /dev/null
+++ b/public/imgs/logo-color.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/imgs/logo.png b/public/imgs/logo.png
new file mode 100644
index 000000000..2b0fd46aa
Binary files /dev/null and b/public/imgs/logo.png differ
diff --git a/public/imgs/logo.svg b/public/imgs/logo.svg
new file mode 100644
index 000000000..9da9311c8
--- /dev/null
+++ b/public/imgs/logo.svg
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/AppShelf/AddAppShelfItem.tsx b/src/components/AppShelf/AddAppShelfItem.tsx
similarity index 89%
rename from components/AppShelf/AddAppShelfItem.tsx
rename to src/components/AppShelf/AddAppShelfItem.tsx
index 5f42d2af2..9a413ba5d 100644
--- a/components/AppShelf/AddAppShelfItem.tsx
+++ b/src/components/AppShelf/AddAppShelfItem.tsx
@@ -10,6 +10,8 @@ import {
Text,
Card,
LoadingOverlay,
+ ActionIcon,
+ Tooltip,
} from '@mantine/core';
import { useForm } from '@mantine/form';
import { motion } from 'framer-motion';
@@ -19,13 +21,42 @@ import { useConfig } from '../../tools/state';
import { ServiceTypeList } from '../../tools/types';
import { AppShelfItemWrapper } from './AppShelfItemWrapper';
+export function AddItemShelfButton(props: any) {
+ const [opened, setOpened] = useState(false);
+ return (
+ <>
+ setOpened(false)}
+ title="Add a service"
+ >
+
+
+ setOpened(true)}
+ >
+
+
+
+
+ >
+ );
+}
+
export default function AddItemShelfItem(props: any) {
const [opened, setOpened] = useState(false);
return (
<>
setOpened(false)}
title="Add a service"
diff --git a/components/AppShelf/AppShelf.story.tsx b/src/components/AppShelf/AppShelf.story.tsx
similarity index 69%
rename from components/AppShelf/AppShelf.story.tsx
rename to src/components/AppShelf/AppShelf.story.tsx
index 610f1370c..928510aac 100644
--- a/components/AppShelf/AppShelf.story.tsx
+++ b/src/components/AppShelf/AppShelf.story.tsx
@@ -1,3 +1,4 @@
+import { SimpleGrid } from '@mantine/core';
import AppShelf, { AppShelfItem } from './AppShelf';
export default {
@@ -16,3 +17,10 @@ export default {
export const Default = (args: any) => ;
export const One = (args: any) => ;
+export const Ten = (args: any) => (
+
+ {Array.from(Array(10)).map((_, i) => (
+
+ ))}
+
+);
diff --git a/src/components/AppShelf/AppShelf.tsx b/src/components/AppShelf/AppShelf.tsx
new file mode 100644
index 000000000..d76413811
--- /dev/null
+++ b/src/components/AppShelf/AppShelf.tsx
@@ -0,0 +1,104 @@
+import React, { useState } from 'react';
+import { motion } from 'framer-motion';
+import { Text, AspectRatio, SimpleGrid, Card, Image, useMantineTheme } from '@mantine/core';
+import { useConfig } from '../../tools/state';
+import { serviceItem } from '../../tools/types';
+import AppShelfMenu from './AppShelfMenu';
+
+const AppShelf = () => {
+ const { config } = useConfig();
+
+ return (
+
+ {config.services.map((service) => (
+
+ ))}
+
+ );
+};
+
+export function AppShelfItem(props: any) {
+ const { service }: { service: serviceItem } = props;
+ const [hovering, setHovering] = useState(false);
+ const theme = useMantineTheme();
+ return (
+ {
+ setHovering(true);
+ }}
+ onHoverEnd={() => {
+ setHovering(false);
+ }}
+ >
+
+
+
+ {service.name}
+
+
+
+
+
+
+
+
+ {
+ window.open(service.url);
+ }}
+ src={service.icon}
+ />
+
+
+
+
+
+ );
+}
+
+export default AppShelf;
diff --git a/components/AppShelf/AppShelfItemWrapper.tsx b/src/components/AppShelf/AppShelfItemWrapper.tsx
similarity index 78%
rename from components/AppShelf/AppShelfItemWrapper.tsx
rename to src/components/AppShelf/AppShelfItemWrapper.tsx
index a305661e6..ffe409062 100644
--- a/components/AppShelf/AppShelfItemWrapper.tsx
+++ b/src/components/AppShelf/AppShelfItemWrapper.tsx
@@ -8,10 +8,6 @@ export function AppShelfItemWrapper(props: any) {
style={{
boxShadow: hovering ? '0px 0px 3px rgba(0, 0, 0, 0.5)' : '0px 0px 1px rgba(0, 0, 0, 0.5)',
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[1],
-
- //TODO: #3 Fix this temporary fix and make the width and height dynamic / responsive
- width: 200,
- height: 180,
}}
radius="md"
>
diff --git a/components/AppShelf/AppShelfMenu.tsx b/src/components/AppShelf/AppShelfMenu.tsx
similarity index 100%
rename from components/AppShelf/AppShelfMenu.tsx
rename to src/components/AppShelf/AppShelfMenu.tsx
diff --git a/components/ColorSchemeToggle/ColorSchemeSwitch.tsx b/src/components/ColorSchemeToggle/ColorSchemeSwitch.tsx
similarity index 100%
rename from components/ColorSchemeToggle/ColorSchemeSwitch.tsx
rename to src/components/ColorSchemeToggle/ColorSchemeSwitch.tsx
diff --git a/components/ColorSchemeToggle/ColorSchemeToggle.tsx b/src/components/ColorSchemeToggle/ColorSchemeToggle.tsx
similarity index 100%
rename from components/ColorSchemeToggle/ColorSchemeToggle.tsx
rename to src/components/ColorSchemeToggle/ColorSchemeToggle.tsx
diff --git a/components/Config/ConfigChanger.tsx b/src/components/Config/ConfigChanger.tsx
similarity index 100%
rename from components/Config/ConfigChanger.tsx
rename to src/components/Config/ConfigChanger.tsx
diff --git a/components/Config/LoadConfig.tsx b/src/components/Config/LoadConfig.tsx
similarity index 100%
rename from components/Config/LoadConfig.tsx
rename to src/components/Config/LoadConfig.tsx
diff --git a/components/Config/SaveConfig.tsx b/src/components/Config/SaveConfig.tsx
similarity index 100%
rename from components/Config/SaveConfig.tsx
rename to src/components/Config/SaveConfig.tsx
diff --git a/components/Config/SelectConfig.tsx b/src/components/Config/SelectConfig.tsx
similarity index 100%
rename from components/Config/SelectConfig.tsx
rename to src/components/Config/SelectConfig.tsx
diff --git a/components/SearchBar/SearchBar.story.tsx b/src/components/SearchBar/SearchBar.story.tsx
similarity index 100%
rename from components/SearchBar/SearchBar.story.tsx
rename to src/components/SearchBar/SearchBar.story.tsx
diff --git a/components/SearchBar/SearchBar.tsx b/src/components/SearchBar/SearchBar.tsx
similarity index 94%
rename from components/SearchBar/SearchBar.tsx
rename to src/components/SearchBar/SearchBar.tsx
index fec0dffe4..7a40ea4c0 100644
--- a/components/SearchBar/SearchBar.tsx
+++ b/src/components/SearchBar/SearchBar.tsx
@@ -22,6 +22,7 @@ export default function SearchBar(props: any) {
return (
- tip: You can prefix your querry with !yt or !t to research on youtube or
- for a torrent
+ tip: Use the prefixes !yt and !t in front of your query to search on YouTube or for a Torrent respectively.
diff --git a/components/Settings/ModuleEnabler.tsx b/src/components/Settings/ModuleEnabler.tsx
similarity index 100%
rename from components/Settings/ModuleEnabler.tsx
rename to src/components/Settings/ModuleEnabler.tsx
diff --git a/components/Settings/SettingsMenu.story.tsx b/src/components/Settings/SettingsMenu.story.tsx
similarity index 100%
rename from components/Settings/SettingsMenu.story.tsx
rename to src/components/Settings/SettingsMenu.story.tsx
diff --git a/components/Settings/SettingsMenu.tsx b/src/components/Settings/SettingsMenu.tsx
similarity index 77%
rename from components/Settings/SettingsMenu.tsx
rename to src/components/Settings/SettingsMenu.tsx
index b8fed02eb..74b5c1b93 100644
--- a/components/Settings/SettingsMenu.tsx
+++ b/src/components/Settings/SettingsMenu.tsx
@@ -9,11 +9,12 @@ import {
SegmentedControl,
Indicator,
Alert,
+ TextInput,
} from '@mantine/core';
import { useColorScheme } from '@mantine/hooks';
import { useEffect, useState } from 'react';
import { AlertCircle, Settings as SettingsIcon } from 'tabler-icons-react';
-import { CURRENT_VERSION, REPO_URL } from '../../data/constants';
+import { CURRENT_VERSION, REPO_URL } from '../../../data/constants';
import { useConfig } from '../../tools/state';
import { ColorSchemeSwitch } from '../ColorSchemeToggle/ColorSchemeSwitch';
import ConfigChanger from '../Config/ConfigChanger';
@@ -24,11 +25,19 @@ function SettingsMenu(props: any) {
const { config, setConfig } = useConfig();
const colorScheme = useColorScheme();
const { current, latest } = props;
+
const matches = [
{ label: 'Google', value: 'https://google.com/search?q=' },
{ label: 'DuckDuckGo', value: 'https://duckduckgo.com/?q=' },
{ label: 'Bing', value: 'https://bing.com/search?q=' },
+ { label: 'Custom', value: 'Custom' },
];
+
+ const [customSearchUrl, setCustomSearchUrl] = useState(config.settings.searchUrl);
+ const [searchUrl, setSearchUrl] = useState(
+ matches.find((match) => match.value === config.settings.searchUrl)?.value ?? 'Custom'
+ );
+
return (
- Version {latest} is available. Current : {current}
+ Version {latest} is available. Current: {current}
-
+
+ Search engine
match.value === config.settings.searchUrl)?.value ?? 'Google'
+ searchUrl
}
onChange={
// Set config.settings.searchUrl to the value of the selected item
- (e) =>
+ (e) => {
+ setSearchUrl(e);
setConfig({
...config,
settings: {
...config.settings,
searchUrl: e,
},
- })
+ });
+ }
}
data={matches}
/>
- Search engine
+ {searchUrl === 'Custom' && (
+ {
+ setCustomSearchUrl(event.currentTarget.value);
+ setConfig({
+ ...config,
+ settings: {
+ ...config.settings,
+ searchUrl: event.currentTarget.value,
+ },
+ });
+ }}
+ />
+ )}
-
+
+
+
);
}
diff --git a/components/layout/Footer.tsx b/src/components/layout/Footer.tsx
similarity index 51%
rename from components/layout/Footer.tsx
rename to src/components/layout/Footer.tsx
index 8727905c4..b89fb2fcb 100644
--- a/components/layout/Footer.tsx
+++ b/src/components/layout/Footer.tsx
@@ -1,5 +1,12 @@
import React from 'react';
-import { createStyles, Anchor, Text, Group, ActionIcon } from '@mantine/core';
+import {
+ createStyles,
+ Anchor,
+ Text,
+ Group,
+ ActionIcon,
+ Footer as FooterComponent,
+} from '@mantine/core';
import { BrandGithub } from 'tabler-icons-react';
const useStyles = createStyles((theme) => ({
@@ -48,34 +55,39 @@ export function Footer({ links }: FooterCenteredProps) {
));
return (
-
- {items}
-
- component="a" href="https://github.com/ajnart/homarr" size="lg">
-
-
-
-
+
- Made with โค๏ธ by @
-
- ajnart
-
-
-
+ {items}
+
+ component="a" href="https://github.com/ajnart/homarr" size="lg">
+
+
+
+
+ Made with โค๏ธ by @
+
+ ajnart
+
+
+
+
);
}
diff --git a/components/layout/Header.tsx b/src/components/layout/Header.tsx
similarity index 57%
rename from components/layout/Header.tsx
rename to src/components/layout/Header.tsx
index b8eb2a9ab..44185e28e 100644
--- a/components/layout/Header.tsx
+++ b/src/components/layout/Header.tsx
@@ -1,18 +1,11 @@
-import React, { useState } from 'react';
-import {
- createStyles,
- Header as Head,
- Container,
- Group,
- Burger,
- Drawer,
- Center,
-} from '@mantine/core';
+import React from 'react';
+import { createStyles, Header as Head, Group, Drawer, Center } from '@mantine/core';
import { useBooleanToggle } from '@mantine/hooks';
import { NextLink } from '@mantine/next';
import { Logo } from './Logo';
-import { SettingsMenuButton } from '../Settings/SettingsMenu';
import CalendarComponent from '../modules/calendar/CalendarModule';
+import { SettingsMenuButton } from '../Settings/SettingsMenu';
+import { AddItemShelfButton } from '../AppShelf/AddAppShelfItem';
const HEADER_HEIGHT = 60;
@@ -40,8 +33,6 @@ const useStyles = createStyles((theme) => ({
header: {
display: 'flex',
- justifyContent: 'space-between',
- alignItems: 'center',
height: '100%',
},
@@ -94,62 +85,33 @@ interface HeaderResponsiveProps {
export function Header({ links }: HeaderResponsiveProps) {
const [opened, toggleOpened] = useBooleanToggle(false);
- const [active, setActive] = useState('/');
const { classes, cx } = useStyles();
- const items = (
- <>
- {links.map((link) => (
- {
- setActive(link.link);
- toggleOpened(false);
- }}
- >
- {link.label}
-
- ))}
- >
- );
return (
-
-
-
-
-
-
-
-
- {items}
-
+
+
+
+
+
-
- toggleOpened()}
- className={classes.burger}
- size="sm"
- />
+
+
- toggleOpened()}
- position="right"
- >
- {opened ?? (
-
-
-
- )}
-
-
+ toggleOpened()}
+ position="right"
+ >
+ {opened ?? (
+
+
+
+ )}
+
);
}
diff --git a/components/layout/Layout.tsx b/src/components/layout/Layout.tsx
similarity index 97%
rename from components/layout/Layout.tsx
rename to src/components/layout/Layout.tsx
index bfb1a2dc3..ab646803d 100644
--- a/components/layout/Layout.tsx
+++ b/src/components/layout/Layout.tsx
@@ -7,7 +7,7 @@ import Navbar from './Navbar';
const useStyles = createStyles((theme) => ({
main: {
[theme.fn.largerThan('md')]: {
- width: 1200,
+ maxWidth: 1500,
},
},
}));
diff --git a/src/components/layout/Logo.tsx b/src/components/layout/Logo.tsx
new file mode 100644
index 000000000..92ea10606
--- /dev/null
+++ b/src/components/layout/Logo.tsx
@@ -0,0 +1,40 @@
+import { Group, Image, Text } from '@mantine/core';
+import * as React from 'react';
+import { CURRENT_VERSION } from '../../../data/constants';
+
+export function Logo({ style }: any) {
+ return (
+
+
+
+ Homarr
+
+
+ {CURRENT_VERSION}
+
+
+ );
+}
diff --git a/components/layout/Navbar.tsx b/src/components/layout/Navbar.tsx
similarity index 52%
rename from components/layout/Navbar.tsx
rename to src/components/layout/Navbar.tsx
index 2f9b26f0b..7bb7a8410 100644
--- a/components/layout/Navbar.tsx
+++ b/src/components/layout/Navbar.tsx
@@ -1,18 +1,22 @@
-import { Navbar as MantineNavbar } from '@mantine/core';
+import { Group, Navbar as MantineNavbar } from '@mantine/core';
import { DateModule } from '../modules/date/DateModule';
import ModuleWrapper from '../modules/moduleWrapper';
export default function Navbar() {
return (
-
+
+
+
);
}
diff --git a/components/modules/calendar/CalendarComponent.story.tsx b/src/components/modules/calendar/CalendarComponent.story.tsx
similarity index 100%
rename from components/modules/calendar/CalendarComponent.story.tsx
rename to src/components/modules/calendar/CalendarComponent.story.tsx
diff --git a/components/modules/calendar/CalendarModule.tsx b/src/components/modules/calendar/CalendarModule.tsx
similarity index 98%
rename from components/modules/calendar/CalendarModule.tsx
rename to src/components/modules/calendar/CalendarModule.tsx
index 0af7a9a92..dd84050fa 100644
--- a/components/modules/calendar/CalendarModule.tsx
+++ b/src/components/modules/calendar/CalendarModule.tsx
@@ -2,9 +2,8 @@
import { Popover, Box, ScrollArea, Divider, Indicator } from '@mantine/core';
import React, { useEffect, useState } from 'react';
import { Calendar } from '@mantine/dates';
-import { CalendarIcon } from '@modulz/radix-icons';
import { showNotification } from '@mantine/notifications';
-import { Check } from 'tabler-icons-react';
+import { Calendar as CalendarIcon, Check } from 'tabler-icons-react';
import { RadarrMediaDisplay, SonarrMediaDisplay } from './MediaDisplay';
import { useConfig } from '../../../tools/state';
import { IModule } from '../modules';
diff --git a/components/modules/calendar/MediaDisplay.story.tsx b/src/components/modules/calendar/MediaDisplay.story.tsx
similarity index 100%
rename from components/modules/calendar/MediaDisplay.story.tsx
rename to src/components/modules/calendar/MediaDisplay.story.tsx
diff --git a/components/modules/calendar/MediaDisplay.tsx b/src/components/modules/calendar/MediaDisplay.tsx
similarity index 100%
rename from components/modules/calendar/MediaDisplay.tsx
rename to src/components/modules/calendar/MediaDisplay.tsx
diff --git a/components/modules/calendar/index.ts b/src/components/modules/calendar/index.ts
similarity index 100%
rename from components/modules/calendar/index.ts
rename to src/components/modules/calendar/index.ts
diff --git a/components/modules/calendar/mediaExample.ts b/src/components/modules/calendar/mediaExample.ts
similarity index 100%
rename from components/modules/calendar/mediaExample.ts
rename to src/components/modules/calendar/mediaExample.ts
diff --git a/components/modules/date/DateModule.story.tsx b/src/components/modules/date/DateModule.story.tsx
similarity index 100%
rename from components/modules/date/DateModule.story.tsx
rename to src/components/modules/date/DateModule.story.tsx
diff --git a/components/modules/date/DateModule.tsx b/src/components/modules/date/DateModule.tsx
similarity index 100%
rename from components/modules/date/DateModule.tsx
rename to src/components/modules/date/DateModule.tsx
diff --git a/components/modules/date/index.ts b/src/components/modules/date/index.ts
similarity index 100%
rename from components/modules/date/index.ts
rename to src/components/modules/date/index.ts
diff --git a/components/modules/index.ts b/src/components/modules/index.ts
similarity index 100%
rename from components/modules/index.ts
rename to src/components/modules/index.ts
diff --git a/components/modules/moduleWrapper.tsx b/src/components/modules/moduleWrapper.tsx
similarity index 100%
rename from components/modules/moduleWrapper.tsx
rename to src/components/modules/moduleWrapper.tsx
diff --git a/components/modules/modules.tsx b/src/components/modules/modules.tsx
similarity index 100%
rename from components/modules/modules.tsx
rename to src/components/modules/modules.tsx
diff --git a/components/modules/readme.md b/src/components/modules/readme.md
similarity index 100%
rename from components/modules/readme.md
rename to src/components/modules/readme.md
diff --git a/pages/_app.tsx b/src/pages/_app.tsx
similarity index 95%
rename from pages/_app.tsx
rename to src/pages/_app.tsx
index 89887632d..3b2271307 100644
--- a/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -5,6 +5,7 @@ import { getCookie, setCookies } from 'cookies-next';
import Head from 'next/head';
import { MantineProvider, ColorScheme, ColorSchemeProvider } from '@mantine/core';
import { NotificationsProvider } from '@mantine/notifications';
+import { useHotkeys } from '@mantine/hooks';
import Layout from '../components/layout/Layout';
import { ConfigProvider } from '../tools/state';
import { theme } from '../tools/theme';
@@ -18,6 +19,7 @@ export default function App(props: AppProps & { colorScheme: ColorScheme }) {
setColorScheme(nextColorScheme);
setCookies('color-scheme', nextColorScheme, { maxAge: 60 * 60 * 24 * 30 });
};
+ useHotkeys([['mod+J', () => toggleColorScheme()]]);
return (
<>
diff --git a/pages/_document.tsx b/src/pages/_document.tsx
similarity index 100%
rename from pages/_document.tsx
rename to src/pages/_document.tsx
diff --git a/pages/api/configs/[slug].ts b/src/pages/api/configs/[slug].ts
similarity index 100%
rename from pages/api/configs/[slug].ts
rename to src/pages/api/configs/[slug].ts
diff --git a/pages/api/configs/index.ts b/src/pages/api/configs/index.ts
similarity index 100%
rename from pages/api/configs/index.ts
rename to src/pages/api/configs/index.ts
diff --git a/pages/index.tsx b/src/pages/index.tsx
similarity index 100%
rename from pages/index.tsx
rename to src/pages/index.tsx
diff --git a/tools/state.tsx b/src/tools/state.tsx
similarity index 100%
rename from tools/state.tsx
rename to src/tools/state.tsx
diff --git a/tools/theme.ts b/src/tools/theme.ts
similarity index 100%
rename from tools/theme.ts
rename to src/tools/theme.ts
diff --git a/tools/types.ts b/src/tools/types.ts
similarity index 100%
rename from tools/types.ts
rename to src/tools/types.ts
diff --git a/tsconfig.json b/tsconfig.json
index 99710e857..3ff0501fd 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -15,6 +15,6 @@
"jsx": "preserve",
"incremental": true
},
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "next.config.js"],
"exclude": ["node_modules"]
}