add template grades, custom name, fix previously introduced bugs

This commit is contained in:
kac5a
2022-09-20 10:37:57 +02:00
parent 7c50c4970c
commit 3fe42a0ce9
21 changed files with 161 additions and 66 deletions

View File

@@ -97,33 +97,29 @@ function detachPaper()
DeleteEntity(prop)
end
local function toggleNuiFrame(shouldShow, shouldHoldDocument, givenDocument)
local function toggleNuiFrame(shouldShow, shouldHoldDocument)
holdDocument(shouldHoldDocument)
SetNuiFocus(shouldShow, shouldShow)
print(givenDocument)
SendReactMessage('setVisible', {
app = shouldShow,
givenDocument = givenDocument
})
SendReactMessage('setVisible', shouldShow)
end
-- local function toggleDocumentFrame(shouldShow, document)
-- holdDocument(shouldShow)
-- SetNuiFocus(shouldShow, shouldShow)
-- SendReactMessage('setDocument', document)
-- end
local function toggleDocumentFrame(shouldShow, document)
holdDocument(shouldShow)
SetNuiFocus(shouldShow, shouldShow)
SendReactMessage('setDocument', document)
end
-- RegisterNUICallback('hideDocument', function(_, cb)
-- toggleDocumentFrame(false, nil)
-- cb({})
-- end)
RegisterNUICallback('hideDocument', function(_, cb)
toggleDocumentFrame(false, nil)
cb({})
end)
RegisterCommand(Config.Command, function()
toggleNuiFrame(true, true, nil)
toggleNuiFrame(true, true)
end)
RegisterNUICallback('hideFrame', function(_, cb)
toggleNuiFrame(false, false, nil)
toggleNuiFrame(false, false)
cb({})
end)
@@ -232,8 +228,6 @@ RegisterNUICallback('showDocument', function(data, cb)
Citizen.CreateThread(function()
local targetId = playerSelector(Config.Locale.showDocument)
if targetId == -1 then
print("asd")
TriggerServerEvent("k5_documents:receiveDocument", data, -1)
holdDocument(false)
else
holdDocument(false)
@@ -258,8 +252,7 @@ end)
RegisterNetEvent('k5_documents:viewDocument')
AddEventHandler('k5_documents:viewDocument', function(data)
print(data)
toggleNuiFrame(true, true, data.data)
toggleDocumentFrame(true, data.data)
end)
function playerSelector(confirmText)

View File

@@ -2,8 +2,8 @@ fx_version "cerulean"
description "A better document management script"
author "K5 Scripts"
version '1.1.4'
update "Fixed visual bug when giving document to someone"
version '1.1.5'
update "Custom document names, template creation set for job grades, bug fixes"
repository 'https://github.com/kac5a/k5_documents'
lua54 'yes'

View File

@@ -1,11 +1,11 @@
{
"files": {
"main.js": "/web/build/static/js/main.10eced3f.js",
"main.js": "/web/build/static/js/main.8a2981e6.js",
"static/media/city_logo.png": "/web/build/static/media/city_logo.008b591a2d4e6445d96c.png",
"index.html": "/web/build/index.html",
"main.10eced3f.js.map": "/web/build/static/js/main.10eced3f.js.map"
"main.8a2981e6.js.map": "/web/build/static/js/main.8a2981e6.js.map"
},
"entrypoints": [
"static/js/main.10eced3f.js"
"static/js/main.8a2981e6.js"
]
}

View File

@@ -1,5 +1,18 @@
// These are the jobs that can create documents. The boss rank of this job can create document templates.
const AVAILABLE_JOBS = ['police', 'ambulance', 'mechanic']
const AVAILABLE_JOBS = [
{
job: 'police',
templateGrades: [3, 4],
},
{
job: 'ambulance',
templateGrades: [3],
},
{
job: 'mechanic',
templateGrades: [4],
},
]
const COLORS = {
// These are hexadecimal color codes for the main theme. You can change them as you wish.
@@ -20,7 +33,10 @@ const TEXTS = {
myDocumentsTitle: 'My Documents',
issuedDocumentsTitle: 'Issued Documents',
templatesTitle: 'Templates',
customDocumentName: 'Custom Document Name',
documentType: 'Type',
documentName: 'Name',
unnamed: 'Unnamed',
actions: 'Actions',
edit: 'Edit',
cancel: 'Cancel',

View File

@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><link rel="preconnect" href="https://fonts.googleapis.com"/><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/><link href="https://fonts.googleapis.com/css2?family=Oooh+Baby&display=swap" rel="stylesheet"/><title>K5 Documents</title><script type="text/javascript" src="/web/build/config.js"></script><script defer="defer" src="/web/build/static/js/main.10eced3f.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><link rel="preconnect" href="https://fonts.googleapis.com"/><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/><link href="https://fonts.googleapis.com/css2?family=Oooh+Baby&display=swap" rel="stylesheet"/><title>K5 Documents</title><script type="text/javascript" src="/web/build/config.js"></script><script defer="defer" src="/web/build/static/js/main.8a2981e6.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,18 @@
// These are the jobs that can create documents. The boss rank of this job can create document templates.
const AVAILABLE_JOBS = ['police', 'ambulance', 'mechanic']
const AVAILABLE_JOBS = [
{
job: 'police',
templateGrades: [3, 4],
},
{
job: 'ambulance',
templateGrades: [3],
},
{
job: 'mechanic',
templateGrades: [4],
},
]
const COLORS = {
// These are hexadecimal color codes for the main theme. You can change them as you wish.
@@ -20,7 +33,10 @@ const TEXTS = {
myDocumentsTitle: 'My Documents',
issuedDocumentsTitle: 'Issued Documents',
templatesTitle: 'Templates',
customDocumentName: 'Custom Document Name',
documentType: 'Type',
documentName: 'Name',
unnamed: 'Unnamed',
actions: 'Actions',
edit: 'Edit',
cancel: 'Cancel',

View File

@@ -1,6 +1,6 @@
declare var TEXTS: { [key: string]: string }
declare var COLORS: { [key: string]: string }
declare var AVAILABLE_JOBS: string[]
declare var AVAILABLE_JOBS: {job:string, templateGrades: number[]}[]
export const texts = typeof TEXTS === "undefined" ? {} : TEXTS
export const colors = typeof COLORS === "undefined" ? {} : COLORS

View File

@@ -2,18 +2,15 @@ import Box from '@mui/material/Box';
import { Grid } from '@mui/material';
import Header from './Header';
import Menu from './Menu/Menu';
import { useContext, useState } from 'react';
import { useState } from 'react';
import { NavLinks } from './Menu/NavLinks';
import { useJob } from '../hooks/useJob';
import { debugData } from '../utils/debugData';
import { ContextProvider } from '../context/Context';
import { VisibilityCtx } from '../providers/VisibilityProvider';
import DocumentViewFromPlayer from './Components/DocumentViewFromPlayer';
export default function App() {
const [selectedPage, setSelectedPage] = useState<Page>(NavLinks[0])
const { isBoss, job } = useJob()
const {visible, givenDocument} = useContext(VisibilityCtx)
const { job } = useJob()
debugData([
{
@@ -24,10 +21,10 @@ export default function App() {
return (
<ContextProvider>
{visible && !givenDocument && <Box sx={{ p:0, height: "70vh", width: "70vw", display: "flex", alignItems: "center" }}>
<Box sx={{ p:0, height: "70vh", width: "70vw", display: "flex", alignItems: "center" }}>
<Grid container sx={{height: '100%'}}>
<Grid item xs={3} style={{marginTop: "auto", marginBottom: "auto"}}>
<Menu selected={selectedPage} isBoss={isBoss} job={job?.name!} setSelected={setSelectedPage}/>
<Menu selected={selectedPage} jobGrade={job?.grade!} job={job?.name!} setSelected={setSelectedPage}/>
</Grid>
<Grid item xs={9}>
<Box
@@ -40,8 +37,7 @@ export default function App() {
</Box>
</Grid>
</Grid>
</Box>}
{visible && givenDocument && <DocumentViewFromPlayer />}
</Box>
</ContextProvider>
);
}

View File

@@ -8,13 +8,13 @@ import SignedArea from "./SignedArea"
import { DATE_FORMAT_SHORT } from "../../utils/consts"
import { useContext } from "react"
import { texts } from "../../AppConfig"
import { VisibilityCtx } from "../../providers/VisibilityProvider"
import { DocumentCtx } from "../../providers/DocumentProvider"
const DocumentViewFromPlayer = () => {
const { givenDocument: document } = useContext(VisibilityCtx)
const { document } = useContext(DocumentCtx)
return (
<Paper>
<StyledDocument>

View File

@@ -48,10 +48,11 @@ const CreateDocument = ({ template, handleCreate, handleClose }: Props) => {
rules: { required: texts.requiredError }
})
const handleCreateTemplate: SubmitHandler<K5Document> = (data: K5Document) => {
const handleCreateDocument: SubmitHandler<K5Document> = (data: K5Document) => {
let result = {
name: data.name,
createdAt: (new Date()).toString(),
customName: data.customName,
description: data.description,
fields: data.fields,
isCopy: false,
@@ -69,7 +70,7 @@ const CreateDocument = ({ template, handleCreate, handleClose }: Props) => {
}
return (
<form onSubmit={handleSubmit(handleCreateTemplate)}>
<form onSubmit={handleSubmit(handleCreateDocument)}>
<StyledDocument>
<Box style={{width: 0}} sx={{ flexGrow: 1 }}>
<Grid
@@ -170,6 +171,14 @@ const CreateDocument = ({ template, handleCreate, handleClose }: Props) => {
</Grid>
</Grid>
<Grid item container justifyContent="center" flex={1} style={{ marginTop: "1.5vh" }}>
<DocTextField
size="small"
label={texts.customDocumentName}
error={!!errors.customName}
style={{width: "auto", marginRight: "auto", justifySelf: "flex-start"}}
helperText={errors.customName?.message as string}
{...register("customName")}
/>
<Button disabled={!isSigned} type="submit" variant="contained" color="success" >{texts.createDocumentBtn}</Button>
<Button variant="contained" color="secondary" style={{marginLeft: "1.8vh"}} onClick={handleClose} >{texts.cancel}</Button>
</Grid>

View File

@@ -8,10 +8,10 @@ type Props = {
selected: Page
setSelected: (selectedPage: Page) => void
job: string
isBoss: boolean
jobGrade: number
}
const Menu = ({isBoss, selected, job, setSelected}: Props) => {
const Menu = ({jobGrade, selected, job, setSelected}: Props) => {
const handleListItemClick = (selectedPage: Page) => {
setSelected(selectedPage);
@@ -21,13 +21,13 @@ const Menu = ({isBoss, selected, job, setSelected}: Props) => {
if (!navLink.jobAccess) {
return true
} else if (!navLink.bossOnly) {
if (availableJobs.includes(job)) {
if (availableJobs.filter(j => j.job === job).length) {
return true
} else {
return false
}
} else {
if (availableJobs.includes(job) && isBoss) {
if (availableJobs.filter(j => j.job === job && j.templateGrades.includes(jobGrade)).length) {
return true
} else {
return false

View File

@@ -1,4 +1,4 @@
import { DataGrid, GridActionsCellItem, GridColumns, GridRowParams, GridValueGetterParams } from "@mui/x-data-grid"
import { DataGrid, GridActionsCellItem, GridColumns, GridRenderCellParams, GridRowParams, GridValueGetterParams } from "@mui/x-data-grid"
import DeleteIcon from "@mui/icons-material/Delete"
import { useCallback, useContext, useEffect, useState } from "react"
import { fetchNui } from "../../utils/fetchNui"
@@ -46,9 +46,15 @@ const IssuedDocuments = () => {
} = useDeleteDocument({ handleGetDocuments, setDocumentsLoading })
const columns: GridColumns<K5Document> = [
{
field: 'customName',
headerName: texts.customName,
flex: 1,
renderCell: (params: GridRenderCellParams<string | undefined>) => (params.value === undefined ? <div style={{ fontStyle: "italic" }}>{texts.unnamed}</div> : params.value)
},
{
field: 'name',
headerName: texts.documentName,
headerName: texts.documentType,
flex: 1,
},
{

View File

@@ -27,6 +27,7 @@ declare type Field = {
declare type K5Document = {
id?: string
name: string
customName?: string
createdAt: string
description: string
fields: Field[]

View File

@@ -7,6 +7,8 @@ import theme from './theme/theme';
import { createRoot } from 'react-dom/client';
import { GlobalStyles } from '@mui/material';
import { Box } from '@mui/system';
import { DocumentProvider } from './providers/DocumentProvider';
import DocumentViewFromPlayer from './components/Components/DocumentViewFromPlayer';
const root = createRoot(document.getElementById('root')!);
@@ -21,10 +23,22 @@ root.render(
body: { backgroundColor: "transparent"},
}}
/>
<Box style={{ height: "100vh", width: "100vw", display: 'flex', justifyContent: "center", alignItems: "center"}}>
<Box style={{position: "fixed", top:0, left: 0, height: "100vh", width: "100vw", display: 'flex', justifyContent: "center", alignItems: "center"}}>
<App />
</Box>
</VisibilityProvider>
<DocumentProvider>
<CssBaseline />
<GlobalStyles
styles={{
body: { backgroundColor: "transparent"},
}}
/>
<Box style={{position: "fixed", top:0, left: 0, height: "100vh", width: "100vw", display: 'flex', justifyContent: "center", alignItems: "center"}}>
<DocumentViewFromPlayer/>
</Box>
</DocumentProvider>
</ThemeProvider>
</React.StrictMode>

View File

@@ -0,0 +1,53 @@
import React, {createContext, useEffect, useState} from "react";
import {useNuiEvent} from "../hooks/useNuiEvent";
import { fetchNui } from "../utils/fetchNui";
import { isEnvBrowser } from "../utils/misc";
export const DocumentCtx = createContext<DocumentProviderValue>({} as DocumentProviderValue)
type DocumentProviderValue = {
document: K5Document | undefined
setDocument: (document: K5Document | undefined) => void
}
// This should be mounted at the top level of your application, it is currently set to
// apply a CSS visibility value. If this is non-performant, this should be customized.
export const DocumentProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [document, setDocument] = useState<K5Document | undefined>()
const [visible, setVisible] = useState<boolean>(false)
useNuiEvent<string>('setDocument', (data) => {
setVisible(!!data)
setDocument(data ? JSON.parse(data) as K5Document : undefined)
})
// Handle pressing escape/backspace
useEffect(() => {
// Only attach listener when we are visible
if (!visible) return;
const keyHandler = (e: KeyboardEvent) => {
if (!isEnvBrowser()) fetchNui("hideDocument").then((_d) => {}).catch(_e => {});
if (["Escape"].includes(e.code)) {
setVisible(!visible)
setDocument(undefined)
}
}
window.addEventListener("keydown", keyHandler)
return () => window.removeEventListener("keydown", keyHandler)
}, [visible])
return (
<DocumentCtx.Provider
value={{
document,
setDocument,
}}
>
<div style={{ visibility: visible ? 'visible' : 'hidden', height: '100%'}}>
{document && children}
</div>
</DocumentCtx.Provider>)
}

View File

@@ -8,21 +8,14 @@ export const VisibilityCtx = createContext<VisibilityProviderValue>({} as Visibi
type VisibilityProviderValue = {
setVisible: (visible: boolean) => void
visible: boolean
givenDocument: K5Document | undefined
setGivenDocument: (doc: K5Document | undefined) => void
}
// This should be mounted at the top level of your application, it is currently set to
// apply a CSS visibility value. If this is non-performant, this should be customized.
export const VisibilityProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [visible, setVisible] = useState(false)
const [givenDocument, setGivenDocument] = useState<K5Document| undefined>()
useNuiEvent<{ app: boolean, givenDocument: string | undefined }>('setVisible', (data: { app: boolean, givenDocument: string | undefined }) => {
console.log(data.givenDocument)
setVisible(data.app)
data.givenDocument && setGivenDocument(JSON.parse(data.givenDocument) as K5Document)
})
useNuiEvent<boolean>('setVisible', setVisible)
// Handle pressing escape/backspace
useEffect(() => {
@@ -48,12 +41,10 @@ export const VisibilityProvider: React.FC<{ children: React.ReactNode }> = ({ ch
value={{
visible,
setVisible,
givenDocument,
setGivenDocument
}}
>
<div style={{ visibility: visible ? 'visible' : 'hidden', height: '100%'}}>
{children}
{visible && children}
</div>
</VisibilityCtx.Provider>)
}