2024-10-25 18:38:47 +02:00
|
|
|
import { CurrentUserMark, Mark, MarkLocation } from '../types/mark.ts'
|
2024-08-02 11:31:25 +01:00
|
|
|
import { hexToNpub } from './nostr.ts'
|
|
|
|
import { Meta, SignedEventContent } from '../types'
|
|
|
|
import { Event } from 'nostr-tools'
|
2024-08-11 22:19:26 +03:00
|
|
|
import { EMPTY } from './const.ts'
|
2024-09-19 13:15:54 +02:00
|
|
|
import { DrawTool, MarkType } from '../types/drawing.ts'
|
2024-09-17 14:33:50 +02:00
|
|
|
import {
|
|
|
|
faT,
|
|
|
|
faSignature,
|
|
|
|
faBriefcase,
|
|
|
|
faIdCard,
|
|
|
|
faClock,
|
2024-09-19 13:15:54 +02:00
|
|
|
fa1,
|
|
|
|
faCalendarDays,
|
|
|
|
faCheckDouble,
|
|
|
|
faCircleDot,
|
|
|
|
faCreditCard,
|
|
|
|
faHeading,
|
|
|
|
faImage,
|
|
|
|
faPaperclip,
|
|
|
|
faPhone,
|
|
|
|
faSquareCaretDown,
|
|
|
|
faSquareCheck,
|
|
|
|
faStamp,
|
|
|
|
faTableCellsLarge
|
2024-09-17 14:33:50 +02:00
|
|
|
} from '@fortawesome/free-solid-svg-icons'
|
2024-10-25 18:38:47 +02:00
|
|
|
import { Config, optimize } from 'svgo'
|
2024-08-02 11:31:25 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Takes in an array of Marks already filtered by User.
|
|
|
|
* Returns an array of CurrentUserMarks with correct values mix-and-matched.
|
|
|
|
* @param marks - default Marks extracted from Meta
|
|
|
|
* @param signedMetaMarks - signed user Marks extracted from DocSignatures
|
|
|
|
*/
|
2024-08-11 22:19:26 +03:00
|
|
|
const getCurrentUserMarks = (
|
|
|
|
marks: Mark[],
|
|
|
|
signedMetaMarks: Mark[]
|
|
|
|
): CurrentUserMark[] => {
|
2024-08-02 11:31:25 +01:00
|
|
|
return marks.map((mark, index, arr) => {
|
2024-08-11 22:19:26 +03:00
|
|
|
const signedMark = signedMetaMarks.find((m) => m.id === mark.id)
|
2024-08-02 11:31:25 +01:00
|
|
|
return {
|
|
|
|
mark,
|
2024-08-11 22:19:26 +03:00
|
|
|
currentValue: signedMark?.value ?? EMPTY,
|
|
|
|
id: index + 1,
|
2024-08-02 11:31:25 +01:00
|
|
|
isLast: isLast(index, arr),
|
2024-08-11 22:19:26 +03:00
|
|
|
isCompleted: !!signedMark?.value
|
2024-08-02 11:31:25 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns next incomplete CurrentUserMark if there is one
|
|
|
|
* @param usersMarks
|
|
|
|
*/
|
2024-08-11 22:19:26 +03:00
|
|
|
const findNextIncompleteCurrentUserMark = (
|
|
|
|
usersMarks: CurrentUserMark[]
|
|
|
|
): CurrentUserMark | undefined => {
|
|
|
|
return usersMarks.find((mark) => !mark.isCompleted)
|
2024-08-02 11:31:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns Marks that are assigned to a specific user
|
|
|
|
* @param marks
|
|
|
|
* @param pubkey
|
|
|
|
*/
|
|
|
|
const filterMarksByPubkey = (marks: Mark[], pubkey: string): Mark[] => {
|
2024-08-11 22:19:26 +03:00
|
|
|
return marks.filter((mark) => mark.npub === hexToNpub(pubkey))
|
2024-08-02 11:31:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Takes Signed Doc Signatures part of Meta and extracts
|
2024-08-27 17:47:19 +02:00
|
|
|
* all Marks into one flat array, regardless of the user.
|
2024-08-02 11:31:25 +01:00
|
|
|
* @param meta
|
|
|
|
*/
|
|
|
|
const extractMarksFromSignedMeta = (meta: Meta): Mark[] => {
|
|
|
|
return Object.values(meta.docSignatures)
|
|
|
|
.map((val: string) => JSON.parse(val as string))
|
|
|
|
.map((val: Event) => JSON.parse(val.content))
|
|
|
|
.flatMap((val: SignedEventContent) => val.marks)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks the CurrentUserMarks array that every element in that array has been
|
|
|
|
* marked as complete.
|
|
|
|
* @param currentUserMarks
|
|
|
|
*/
|
2024-08-11 22:19:26 +03:00
|
|
|
const isCurrentUserMarksComplete = (
|
|
|
|
currentUserMarks: CurrentUserMark[]
|
|
|
|
): boolean => {
|
2024-08-02 11:31:25 +01:00
|
|
|
return currentUserMarks.every((mark) => mark.isCompleted)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Inserts an updated mark into an existing array of marks. Returns a copy of the
|
|
|
|
* existing array with a new value inserted
|
|
|
|
* @param marks
|
|
|
|
* @param markToUpdate
|
|
|
|
*/
|
|
|
|
const updateMarks = (marks: Mark[], markToUpdate: Mark): Mark[] => {
|
2024-08-11 22:19:26 +03:00
|
|
|
const indexToUpdate = marks.findIndex((mark) => mark.id === markToUpdate.id)
|
2024-08-02 11:31:25 +01:00
|
|
|
return [
|
|
|
|
...marks.slice(0, indexToUpdate),
|
|
|
|
markToUpdate,
|
|
|
|
...marks.slice(indexToUpdate + 1)
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
2024-08-11 22:19:26 +03:00
|
|
|
const updateCurrentUserMarks = (
|
|
|
|
currentUserMarks: CurrentUserMark[],
|
|
|
|
markToUpdate: CurrentUserMark
|
|
|
|
): CurrentUserMark[] => {
|
|
|
|
const indexToUpdate = currentUserMarks.findIndex(
|
|
|
|
(m) => m.mark.id === markToUpdate.mark.id
|
|
|
|
)
|
2024-08-02 11:31:25 +01:00
|
|
|
return [
|
|
|
|
...currentUserMarks.slice(0, indexToUpdate),
|
|
|
|
markToUpdate,
|
|
|
|
...currentUserMarks.slice(indexToUpdate + 1)
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
2024-08-11 22:19:26 +03:00
|
|
|
const isLast = <T>(index: number, arr: T[]) => index === arr.length - 1
|
|
|
|
|
|
|
|
const isCurrentValueLast = (
|
|
|
|
currentUserMarks: CurrentUserMark[],
|
|
|
|
selectedMark: CurrentUserMark,
|
|
|
|
selectedMarkValue: string
|
|
|
|
) => {
|
|
|
|
const filteredMarks = currentUserMarks.filter(
|
|
|
|
(mark) => mark.id !== selectedMark.id
|
|
|
|
)
|
|
|
|
return (
|
|
|
|
isCurrentUserMarksComplete(filteredMarks) && selectedMarkValue.length > 0
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
const getUpdatedMark = (
|
|
|
|
selectedMark: CurrentUserMark,
|
|
|
|
selectedMarkValue: string
|
|
|
|
): CurrentUserMark => {
|
|
|
|
return {
|
|
|
|
...selectedMark,
|
|
|
|
currentValue: selectedMarkValue,
|
2024-08-15 16:43:10 +02:00
|
|
|
isCompleted: !!selectedMarkValue,
|
|
|
|
mark: {
|
|
|
|
...selectedMark.mark,
|
|
|
|
value: selectedMarkValue
|
|
|
|
}
|
2024-08-11 22:19:26 +03:00
|
|
|
}
|
|
|
|
}
|
2024-08-02 11:31:25 +01:00
|
|
|
|
2024-08-20 17:04:27 +03:00
|
|
|
const findOtherUserMarks = (marks: Mark[], pubkey: string): Mark[] => {
|
|
|
|
return marks.filter((mark) => mark.npub !== hexToNpub(pubkey))
|
|
|
|
}
|
|
|
|
|
2024-09-19 13:15:54 +02:00
|
|
|
export const DEFAULT_TOOLBOX: DrawTool[] = [
|
2024-10-07 12:53:43 +02:00
|
|
|
{
|
|
|
|
identifier: MarkType.TEXT,
|
|
|
|
icon: faT,
|
|
|
|
label: 'Text'
|
|
|
|
},
|
2024-10-25 18:38:47 +02:00
|
|
|
{
|
|
|
|
identifier: MarkType.SIGNATURE,
|
|
|
|
icon: faSignature,
|
|
|
|
label: 'Signature'
|
|
|
|
},
|
2024-09-17 14:33:50 +02:00
|
|
|
{
|
2024-09-17 15:04:54 +02:00
|
|
|
identifier: MarkType.FULLNAME,
|
|
|
|
icon: faIdCard,
|
|
|
|
label: 'Full Name',
|
2024-09-19 13:15:54 +02:00
|
|
|
isComingSoon: true
|
2024-09-17 14:33:50 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.JOBTITLE,
|
|
|
|
icon: faBriefcase,
|
|
|
|
label: 'Job Title',
|
2024-09-19 13:15:54 +02:00
|
|
|
isComingSoon: true
|
2024-09-17 14:33:50 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.DATETIME,
|
|
|
|
icon: faClock,
|
|
|
|
label: 'Date Time',
|
2024-09-19 13:15:54 +02:00
|
|
|
isComingSoon: true
|
2024-09-17 14:33:50 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.NUMBER,
|
|
|
|
icon: fa1,
|
|
|
|
label: 'Number',
|
2024-09-19 13:15:54 +02:00
|
|
|
isComingSoon: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.INITIALS,
|
|
|
|
icon: faHeading,
|
|
|
|
label: 'Initials',
|
|
|
|
isHidden: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.DATE,
|
|
|
|
icon: faCalendarDays,
|
|
|
|
label: 'Date',
|
|
|
|
isHidden: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.IMAGES,
|
|
|
|
icon: faImage,
|
|
|
|
label: 'Images',
|
|
|
|
isHidden: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.CHECKBOX,
|
|
|
|
icon: faSquareCheck,
|
|
|
|
label: 'Checkbox',
|
|
|
|
isHidden: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.MULTIPLE,
|
|
|
|
icon: faCheckDouble,
|
|
|
|
label: 'Multiple',
|
|
|
|
isHidden: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.FILE,
|
|
|
|
icon: faPaperclip,
|
|
|
|
label: 'File',
|
|
|
|
isHidden: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.RADIO,
|
|
|
|
icon: faCircleDot,
|
|
|
|
label: 'Radio',
|
|
|
|
isHidden: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.SELECT,
|
|
|
|
icon: faSquareCaretDown,
|
|
|
|
label: 'Select',
|
|
|
|
isHidden: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.CELLS,
|
|
|
|
icon: faTableCellsLarge,
|
|
|
|
label: 'Cells',
|
|
|
|
isHidden: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.STAMP,
|
|
|
|
icon: faStamp,
|
|
|
|
label: 'Stamp',
|
|
|
|
isHidden: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.PAYMENT,
|
|
|
|
icon: faCreditCard,
|
|
|
|
label: 'Payment',
|
|
|
|
isHidden: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: MarkType.PHONE,
|
|
|
|
icon: faPhone,
|
|
|
|
label: 'Phone',
|
|
|
|
isHidden: true
|
2024-09-17 14:33:50 +02:00
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
export const getToolboxLabelByMarkType = (markType: MarkType) => {
|
|
|
|
return DEFAULT_TOOLBOX.find((t) => t.identifier === markType)?.label
|
|
|
|
}
|
|
|
|
|
2024-10-25 18:38:47 +02:00
|
|
|
export const optimizeSVG = (location: MarkLocation, paths: string[]) => {
|
|
|
|
const svgContent = `<svg xmlns="http://www.w3.org/2000/svg" width="${location.width}" height="${location.height}">${paths.map((path) => `<path d="${path}" stroke="black" fill="none" />`).join('')}</svg>`
|
|
|
|
const optimizedSVG = optimize(svgContent, {
|
|
|
|
multipass: true, // Optimize multiple times if needed
|
|
|
|
floatPrecision: 2 // Adjust precision
|
|
|
|
} as Config)
|
|
|
|
|
|
|
|
return optimizedSVG.data
|
|
|
|
}
|
|
|
|
|
|
|
|
export const getOptimizedPaths = (svgString: string) => {
|
|
|
|
const regex = / d="([^"]*)"/g
|
|
|
|
const matches = [...svgString.matchAll(regex)]
|
|
|
|
const pathValues = matches.map((match) => match[1])
|
|
|
|
|
|
|
|
return pathValues
|
|
|
|
}
|
|
|
|
|
2024-08-02 11:31:25 +01:00
|
|
|
export {
|
|
|
|
getCurrentUserMarks,
|
|
|
|
filterMarksByPubkey,
|
|
|
|
extractMarksFromSignedMeta,
|
|
|
|
isCurrentUserMarksComplete,
|
2024-08-11 22:19:26 +03:00
|
|
|
findNextIncompleteCurrentUserMark,
|
2024-08-02 11:31:25 +01:00
|
|
|
updateMarks,
|
|
|
|
updateCurrentUserMarks,
|
2024-08-11 22:19:26 +03:00
|
|
|
isCurrentValueLast,
|
2024-08-20 17:04:27 +03:00
|
|
|
getUpdatedMark,
|
|
|
|
findOtherUserMarks
|
2024-08-02 11:31:25 +01:00
|
|
|
}
|