mirror of https://github.com/BRAVO68WEB/shx.git
Merge pull request #76 from BRAVO68WEB/issue-74-Settings_Section
Issue 74 settings section
This commit is contained in:
commit
6973dfd1ca
|
@ -0,0 +1,7 @@
|
|||
import React from 'react'
|
||||
|
||||
function Page() {
|
||||
return <div>Page</div>;
|
||||
}
|
||||
|
||||
export default Page;
|
|
@ -0,0 +1,54 @@
|
|||
import React from 'react';
|
||||
|
||||
function Page() {
|
||||
const urls = [
|
||||
{
|
||||
id: 'afdas',
|
||||
originalURL: 'https://www.google.com',
|
||||
shortenedURL: 'https://www.google.com',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<table className="min-w-full divide-y divide-gray-700">
|
||||
<thead className="p-2">
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
className="py-3.5 pl-4 pr-5 text-left text-lg font-semibold text-white"
|
||||
>
|
||||
Original URL
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="py-3.5 pl-4 pr-3 w-full text-left text-lg font-semibold text-white"
|
||||
>
|
||||
Shortened URL
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y p-2">
|
||||
{urls.map(({ originalURL, shortenedURL, id }) => (
|
||||
<tr className="bg-gray-900 rounded" key={id}>
|
||||
<td className="whitespace-nowrap pl-4 pr-20 text-sm font-medium text-white">
|
||||
<div className="flex items-center gap-3">
|
||||
{originalURL}
|
||||
|
||||
</div>
|
||||
</td>
|
||||
<td className="whitespace-nowrap pl-4 text-sm font-medium text-white">
|
||||
<div className="flex items-center gap-3">
|
||||
{shortenedURL}
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
|
@ -0,0 +1,69 @@
|
|||
'use client';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import Link from 'next/link';
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
name: 'Instance Info',
|
||||
href: '/dashboard/utilities/instance-info',
|
||||
current: false,
|
||||
},
|
||||
{ name: 'Settings', href: '/dashboard/utilities/settings', current: false },
|
||||
{
|
||||
name: 'Config Download',
|
||||
href: '/dashboard/utilities/download-config',
|
||||
current: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default function Example({ children }: { children: React.ReactNode }) {
|
||||
const pathname = usePathname();
|
||||
function isCurrent(href: string) {
|
||||
return href === pathname;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<h1 className="text-4xl mb-10">My Utilities</h1>
|
||||
<div className="sm:hidden">
|
||||
<label htmlFor="tabs" className="sr-only">
|
||||
Select a tab
|
||||
</label>
|
||||
{/* Use an "onChange" listener to redirect the user to the selected tab URL. */}
|
||||
<select
|
||||
id="tabs"
|
||||
name="tabs"
|
||||
className="block w-full rounded-md border-gray-300 focus:border-indigo-500 focus:ring-indigo-500"
|
||||
defaultValue={tabs.find(tab => tab.current)?.name}
|
||||
>
|
||||
{tabs.map(tab => (
|
||||
<option key={tab.name}>{tab.name}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="hidden sm:block">
|
||||
<div className="border-b border-gray-200">
|
||||
<nav className="-mb-px flex" aria-label="Tabs">
|
||||
{tabs.map(tab => (
|
||||
<Link
|
||||
key={tab.name}
|
||||
href={tab.href}
|
||||
className={cn(
|
||||
isCurrent(tab.href)
|
||||
? 'border-primary text-primary'
|
||||
: 'border-transparent text-white',
|
||||
'w-full border-b-2 py-4 px-1 text-center text-sm font-medium '
|
||||
)}
|
||||
aria-current={tab.current ? 'page' : undefined}
|
||||
>
|
||||
{tab.name}
|
||||
</Link>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
"use client"
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import Button from '@/components/ui/Button';
|
||||
import Input from '@/components/ui/Input';
|
||||
import TagInput from '@/components/TagInput';
|
||||
|
||||
function Page() {
|
||||
const [imageExts, setImageExts] = useState<string[]>([]);
|
||||
const [fileExts, setFileExts] = useState<string[]>([]);
|
||||
|
||||
const addImageExt = (tag: string) => {
|
||||
setImageExts(old => {
|
||||
return [...old, tag];
|
||||
});
|
||||
};
|
||||
const addFileExt = (tag: string) => {
|
||||
setFileExts(old => {
|
||||
return [...old, tag];
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-8 w-full mt-10">
|
||||
<div>
|
||||
<label
|
||||
htmlFor="theme"
|
||||
className="block text-sm font-medium leading-6 text-white"
|
||||
>
|
||||
Theme
|
||||
</label>
|
||||
<select
|
||||
id="theme"
|
||||
name="theme"
|
||||
className="mt-2 block w-full bg-transparent rounded-md py-1.5 pl-3 pr-10 text-white sm:text-sm sm:leading-6 border-primary border"
|
||||
defaultValue="dark"
|
||||
>
|
||||
<option value={'dark'}>Dark</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label
|
||||
htmlFor="Language"
|
||||
className="block text-sm font-medium leading-6 text-white"
|
||||
>
|
||||
Language
|
||||
</label>
|
||||
<select
|
||||
id="Language"
|
||||
name="Language"
|
||||
className="mt-2 bg-transparent block w-full rounded-md py-1.5 pl-3 pr-10 text-white sm:text-sm sm:leading-6 border border-primary"
|
||||
defaultValue="en"
|
||||
>
|
||||
<option value={'en'}>English</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="flex items-center w-full">
|
||||
<Input
|
||||
id="instance-url"
|
||||
withLabel
|
||||
label="Instance URL"
|
||||
type="text"
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
<TagInput
|
||||
tags={imageExts}
|
||||
onAddTags={addImageExt}
|
||||
placeholder="Image Extensions"
|
||||
/>
|
||||
<TagInput
|
||||
tags={fileExts}
|
||||
onAddTags={addFileExt}
|
||||
placeholder="File Extensions"
|
||||
/>
|
||||
<Button>Save</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
|
@ -0,0 +1,41 @@
|
|||
import React, { FormEventHandler, useRef } from 'react';
|
||||
import Input from './ui/Input';
|
||||
import Button from './ui/Button';
|
||||
|
||||
interface TagInput {
|
||||
tags: string[];
|
||||
onAddTags: (value: string) => void;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
function TagInput({ tags, placeholder, onAddTags }: TagInput) {
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const onSubmit: FormEventHandler<HTMLFormElement> = evt => {
|
||||
evt.preventDefault();
|
||||
if (inputRef.current?.value && inputRef.current.value.trim() !== '') {
|
||||
onAddTags(inputRef.current.value);
|
||||
inputRef.current.value = '';
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="w-full flex flex-wrap gap-2">
|
||||
{tags.map((tag, index) => (
|
||||
<Button key={index} className="rounded w-min m-0 items-center">
|
||||
{tag}
|
||||
</Button>
|
||||
))}
|
||||
|
||||
<form onSubmit={onSubmit} className="w-40">
|
||||
<Input
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
placeholder={placeholder}
|
||||
className="text-lg h-full my-0 p-2"
|
||||
/>
|
||||
<button hidden type="submit" />
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default TagInput;
|
|
@ -3,6 +3,7 @@ import React, {
|
|||
InputHTMLAttributes,
|
||||
LegacyRef,
|
||||
MutableRefObject,
|
||||
RefObject,
|
||||
} from 'react';
|
||||
import { cva, VariantProps } from 'class-variance-authority';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
@ -27,7 +28,7 @@ interface InputProps
|
|||
VariantProps<typeof inputVariance> {
|
||||
label?: string;
|
||||
withLabel?: boolean;
|
||||
ref?: MutableRefObject<HTMLInputElement> | RefCallBack;
|
||||
ref?: MutableRefObject<HTMLInputElement> |RefObject<HTMLInputElement>| RefCallBack;
|
||||
}
|
||||
|
||||
const Input = forwardRef<HTMLInputElement | InputProps>(
|
||||
|
|
88
yarn.lock
88
yarn.lock
|
@ -2343,6 +2343,13 @@
|
|||
dependencies:
|
||||
regenerator-runtime "^0.13.11"
|
||||
|
||||
"@babel/runtime@^7.9.2":
|
||||
version "7.22.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec"
|
||||
integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.11"
|
||||
|
||||
"@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.21.9":
|
||||
version "7.21.9"
|
||||
resolved "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz"
|
||||
|
@ -3700,6 +3707,21 @@
|
|||
schema-utils "^3.0.0"
|
||||
source-map "^0.7.3"
|
||||
|
||||
"@react-dnd/asap@^5.0.1":
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@react-dnd/asap/-/asap-5.0.2.tgz#1f81f124c1cd6f39511c11a881cfb0f715343488"
|
||||
integrity sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==
|
||||
|
||||
"@react-dnd/invariant@^4.0.1":
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@react-dnd/invariant/-/invariant-4.0.2.tgz#b92edffca10a26466643349fac7cdfb8799769df"
|
||||
integrity sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==
|
||||
|
||||
"@react-dnd/shallowequal@^4.0.1":
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz#d1b4befa423f692fa4abf1c79209702e7d8ae4b4"
|
||||
integrity sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==
|
||||
|
||||
"@redis/bloom@1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz"
|
||||
|
@ -5463,6 +5485,13 @@
|
|||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-tag-input@^6.6.1":
|
||||
version "6.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-tag-input/-/react-tag-input-6.6.1.tgz#c7f12fec61a5f2b98028fa1e47ae64bd29a7c453"
|
||||
integrity sha512-IaCnZu4gplbt2pR+3bD/yy9SdzsuT+fTOLeJcwYuyBw0aoHAuiTg8lKPii1fPPrV+nisxOWU3SmEqL9VwqaXuw==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@18.2.7", "@types/react@>=16":
|
||||
version "18.2.7"
|
||||
resolved "https://registry.npmjs.org/@types/react/-/react-18.2.7.tgz"
|
||||
|
@ -6983,6 +7012,11 @@ class-variance-authority@^0.6.0:
|
|||
dependencies:
|
||||
clsx "1.2.1"
|
||||
|
||||
classnames@~2.3.1:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924"
|
||||
integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==
|
||||
|
||||
clean-css@^5.2.2:
|
||||
version "5.3.2"
|
||||
resolved "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz"
|
||||
|
@ -7899,6 +7933,15 @@ dlv@^1.1.3:
|
|||
resolved "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz"
|
||||
integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
|
||||
|
||||
dnd-core@^16.0.1:
|
||||
version "16.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dnd-core/-/dnd-core-16.0.1.tgz#a1c213ed08961f6bd1959a28bb76f1a868360d19"
|
||||
integrity sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==
|
||||
dependencies:
|
||||
"@react-dnd/asap" "^5.0.1"
|
||||
"@react-dnd/invariant" "^4.0.1"
|
||||
redux "^4.2.0"
|
||||
|
||||
doctrine@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz"
|
||||
|
@ -9653,6 +9696,13 @@ hmac-drbg@^1.0.1:
|
|||
minimalistic-assert "^1.0.0"
|
||||
minimalistic-crypto-utils "^1.0.1"
|
||||
|
||||
hoist-non-react-statics@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
||||
dependencies:
|
||||
react-is "^16.7.0"
|
||||
|
||||
hosted-git-info@^2.1.4:
|
||||
version "2.8.9"
|
||||
resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz"
|
||||
|
@ -10826,7 +10876,7 @@ lodash.templatesettings@^4.0.0:
|
|||
dependencies:
|
||||
lodash._reinterpolate "^3.0.0"
|
||||
|
||||
lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@~4.17.0:
|
||||
lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@~4.17.0, lodash@~4.17.12:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
@ -12607,6 +12657,24 @@ react-colorful@^5.1.2:
|
|||
resolved "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz"
|
||||
integrity sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==
|
||||
|
||||
react-dnd-html5-backend@^16.0.1:
|
||||
version "16.0.1"
|
||||
resolved "https://registry.yarnpkg.com/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz#87faef15845d512a23b3c08d29ecfd34871688b6"
|
||||
integrity sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==
|
||||
dependencies:
|
||||
dnd-core "^16.0.1"
|
||||
|
||||
react-dnd@^16.0.1:
|
||||
version "16.0.1"
|
||||
resolved "https://registry.yarnpkg.com/react-dnd/-/react-dnd-16.0.1.tgz#2442a3ec67892c60d40a1559eef45498ba26fa37"
|
||||
integrity sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==
|
||||
dependencies:
|
||||
"@react-dnd/invariant" "^4.0.1"
|
||||
"@react-dnd/shallowequal" "^4.0.1"
|
||||
dnd-core "^16.0.1"
|
||||
fast-deep-equal "^3.1.3"
|
||||
hoist-non-react-statics "^3.3.2"
|
||||
|
||||
react-docgen-typescript@^2.2.2:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz"
|
||||
|
@ -12667,7 +12735,7 @@ react-is@18.1.0:
|
|||
resolved "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz"
|
||||
integrity sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==
|
||||
|
||||
react-is@^16.13.1:
|
||||
react-is@^16.13.1, react-is@^16.7.0:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
@ -12682,6 +12750,15 @@ react-refresh@^0.11.0:
|
|||
resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz"
|
||||
integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==
|
||||
|
||||
react-tag-input@^6.8.1:
|
||||
version "6.8.1"
|
||||
resolved "https://registry.yarnpkg.com/react-tag-input/-/react-tag-input-6.8.1.tgz#bbf6e4e0765c0565470cc48a44dc4757c75784b9"
|
||||
integrity sha512-eD8SCFVMGbnDP0qnlpMnalw6POJVnkOh0M7FhuVyR3u/Mf+lgAuvl+GbrtGaFZcw3qz2sWo6j3jrrHUV2gO6Cg==
|
||||
dependencies:
|
||||
classnames "~2.3.1"
|
||||
lodash "~4.17.12"
|
||||
prop-types "^15.7.2"
|
||||
|
||||
react@18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
|
||||
|
@ -12808,6 +12885,13 @@ redis@^4.6.6, redis@^4.6.7:
|
|||
"@redis/search" "1.1.3"
|
||||
"@redis/time-series" "1.0.4"
|
||||
|
||||
redux@^4.2.0:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197"
|
||||
integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.9.2"
|
||||
|
||||
regenerate-unicode-properties@^10.1.0:
|
||||
version "10.1.0"
|
||||
resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz"
|
||||
|
|
Loading…
Reference in New Issue