F: Add QR feature for RSForm

This commit is contained in:
Ivan 2024-12-18 12:35:48 +03:00
parent 97178d8114
commit dc7cea8eaa
7 changed files with 63 additions and 2 deletions

View File

@ -42,6 +42,7 @@ This readme file is used mostly to document project dependencies and conventions
- reactflow - reactflow
- js-file-download - js-file-download
- use-debounce - use-debounce
- qrcode.react
- html-to-image - html-to-image
- @tanstack/react-table - @tanstack/react-table
- @uiw/react-codemirror - @uiw/react-codemirror

View File

@ -17,6 +17,7 @@
"clsx": "^2.1.1", "clsx": "^2.1.1",
"html-to-image": "^1.11.11", "html-to-image": "^1.11.11",
"js-file-download": "^0.4.12", "js-file-download": "^0.4.12",
"qrcode.react": "^4.2.0",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-error-boundary": "^4.1.2", "react-error-boundary": "^4.1.2",
@ -8666,6 +8667,15 @@
], ],
"license": "MIT" "license": "MIT"
}, },
"node_modules/qrcode.react": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-4.2.0.tgz",
"integrity": "sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA==",
"license": "ISC",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/queue-microtask": { "node_modules/queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",

View File

@ -21,6 +21,7 @@
"clsx": "^2.1.1", "clsx": "^2.1.1",
"html-to-image": "^1.11.11", "html-to-image": "^1.11.11",
"js-file-download": "^0.4.12", "js-file-download": "^0.4.12",
"qrcode.react": "^4.2.0",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-error-boundary": "^4.1.2", "react-error-boundary": "^4.1.2",

View File

@ -20,6 +20,7 @@ export { TbEye as IconShow } from 'react-icons/tb';
export { TbEyeX as IconHide } from 'react-icons/tb'; export { TbEyeX as IconHide } from 'react-icons/tb';
export { BiShareAlt as IconShare } from 'react-icons/bi'; export { BiShareAlt as IconShare } from 'react-icons/bi';
export { LuFilter as IconFilter } from 'react-icons/lu'; export { LuFilter as IconFilter } from 'react-icons/lu';
export { LuQrCode as IconQR } from 'react-icons/lu';
export { LuFilterX as IconFilterReset } from 'react-icons/lu'; export { LuFilterX as IconFilterReset } from 'react-icons/lu';
export {BiDownArrowCircle as IconOpenList } from 'react-icons/bi'; export {BiDownArrowCircle as IconOpenList } from 'react-icons/bi';
export { LuTriangleAlert as IconAlert } from 'react-icons/lu'; export { LuTriangleAlert as IconAlert } from 'react-icons/lu';

View File

@ -0,0 +1,26 @@
'use client';
import clsx from 'clsx';
import { QRCodeSVG } from 'qrcode.react';
import Modal, { ModalProps } from '@/components/ui/Modal';
interface DlgShowQRProps extends Pick<ModalProps, 'hideWindow'> {
target: string;
}
function DlgShowQR({ hideWindow, target }: DlgShowQRProps) {
return (
<Modal
readonly
hideWindow={hideWindow}
className={clsx('w-[30rem]', 'py-12 pr-3 pl-6 flex gap-3 justify-center items-center')}
>
<div className='bg-[#ffffff] p-4 border'>
<QRCodeSVG value={target} size={256} />
</div>
</Modal>
);
}
export default DlgShowQR;

View File

@ -19,6 +19,7 @@ import {
IconNewVersion, IconNewVersion,
IconOSS, IconOSS,
IconOwner, IconOwner,
IconQR,
IconReader, IconReader,
IconReplace, IconReplace,
IconShare, IconShare,
@ -85,6 +86,11 @@ function MenuRSTabs({ onDestroy }: MenuRSTabsProps) {
controller.share(); controller.share();
} }
function handleShowQR() {
schemaMenu.hide();
controller.showQR();
}
function handleCreateVersion() { function handleCreateVersion() {
schemaMenu.hide(); schemaMenu.hide();
controller.createVersion(); controller.createVersion();
@ -155,10 +161,16 @@ function MenuRSTabs({ onDestroy }: MenuRSTabsProps) {
onClick={handleShare} onClick={handleShare}
disabled={controller.schema?.access_policy !== AccessPolicy.PUBLIC} disabled={controller.schema?.access_policy !== AccessPolicy.PUBLIC}
/> />
<DropdownButton
text='QR-код'
title='Показать QR-код схемы'
icon={<IconQR size='1rem' className='icon-primary' />}
onClick={handleShowQR}
/>
{user ? ( {user ? (
<DropdownButton <DropdownButton
text='Клонировать' text='Клонировать'
icon={<IconClone size='1rem' className='icon-primary' />} icon={<IconClone size='1rem' className='icon-green' />}
disabled={model.isArchive} disabled={model.isArchive}
onClick={handleClone} onClick={handleClone}
/> />

View File

@ -21,6 +21,7 @@ import DlgEditVersions from '@/dialogs/DlgEditVersions';
import DlgEditWordForms from '@/dialogs/DlgEditWordForms'; import DlgEditWordForms from '@/dialogs/DlgEditWordForms';
import DlgInlineSynthesis from '@/dialogs/DlgInlineSynthesis'; import DlgInlineSynthesis from '@/dialogs/DlgInlineSynthesis';
import DlgRenameCst from '@/dialogs/DlgRenameCst'; import DlgRenameCst from '@/dialogs/DlgRenameCst';
import DlgShowQR from '@/dialogs/DlgShowQR';
import DlgShowTypeGraph from '@/dialogs/DlgShowTypeGraph'; import DlgShowTypeGraph from '@/dialogs/DlgShowTypeGraph';
import DlgSubstituteCst from '@/dialogs/DlgSubstituteCst'; import DlgSubstituteCst from '@/dialogs/DlgSubstituteCst';
import DlgUploadRSForm from '@/dialogs/DlgUploadRSForm'; import DlgUploadRSForm from '@/dialogs/DlgUploadRSForm';
@ -108,6 +109,7 @@ export interface IRSEditContext extends ILibraryItemEditor {
substitute: () => void; substitute: () => void;
showTypeGraph: () => void; showTypeGraph: () => void;
showQR: () => void;
} }
const RSEditContext = createContext<IRSEditContext | null>(null); const RSEditContext = createContext<IRSEditContext | null>(null);
@ -172,6 +174,7 @@ export const RSEditState = ({
const [showEditVersions, setShowEditVersions] = useState(false); const [showEditVersions, setShowEditVersions] = useState(false);
const [showInlineSynthesis, setShowInlineSynthesis] = useState(false); const [showInlineSynthesis, setShowInlineSynthesis] = useState(false);
const [showTypeGraph, setShowTypeGraph] = useState(false); const [showTypeGraph, setShowTypeGraph] = useState(false);
const [showQR, setShowQR] = useState(false);
const [createInitialData, setCreateInitialData] = useState<ICstCreateData>(); const [createInitialData, setCreateInitialData] = useState<ICstCreateData>();
const [showCreateCst, setShowCreateCst] = useState(false); const [showCreateCst, setShowCreateCst] = useState(false);
@ -627,6 +630,11 @@ export const RSEditState = ({
[model] [model]
); );
function generateQR(): string {
const currentRef = window.location.href;
return currentRef.includes('?') ? currentRef + '&qr' : currentRef + '?qr';
}
return ( return (
<RSEditContext <RSEditContext
value={{ value={{
@ -679,11 +687,13 @@ export const RSEditState = ({
produceStructure, produceStructure,
substitute, substitute,
showTypeGraph: () => setShowTypeGraph(true) showTypeGraph: () => setShowTypeGraph(true),
showQR: () => setShowQR(true)
}} }}
> >
{model.schema ? ( {model.schema ? (
<> <>
{showQR ? <DlgShowQR hideWindow={() => setShowQR(false)} target={generateQR()} /> : null}
{showUpload ? <DlgUploadRSForm hideWindow={() => setShowUpload(false)} /> : null} {showUpload ? <DlgUploadRSForm hideWindow={() => setShowUpload(false)} /> : null}
{showClone ? ( {showClone ? (
<DlgCloneLibraryItem <DlgCloneLibraryItem