@visns-studio/visns-components 5.13.12 → 5.13.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
89
89
|
},
|
|
90
90
|
"name": "@visns-studio/visns-components",
|
|
91
|
-
"version": "5.13.
|
|
91
|
+
"version": "5.13.13",
|
|
92
92
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
93
93
|
"main": "src/index.js",
|
|
94
94
|
"files": [
|
|
@@ -87,6 +87,13 @@
|
|
|
87
87
|
margin-bottom: 1rem;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
.signature-editor-label-with-button {
|
|
91
|
+
display: flex;
|
|
92
|
+
align-items: center;
|
|
93
|
+
justify-content: space-between;
|
|
94
|
+
margin-bottom: 0.5rem;
|
|
95
|
+
}
|
|
96
|
+
|
|
90
97
|
.signature-btn {
|
|
91
98
|
display: inline-flex;
|
|
92
99
|
align-items: center;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
2
|
-
import { Plus, Trash2, Move, Type, Edit3, Save, X } from 'lucide-react';
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
2
|
+
import { Plus, Trash2, Move, Type, Edit3, Save, X, Tag } from 'lucide-react';
|
|
3
3
|
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
|
|
4
4
|
import { arrayMoveImmutable } from 'array-move';
|
|
5
5
|
import { toast } from 'react-toastify';
|
|
6
6
|
import { buildUrl, defaultProposalApiEndpoints } from '../../utils/urlBuilder';
|
|
7
|
+
import VariableInserter from './VariableInserter';
|
|
7
8
|
import './AgreementSignatureEditor.css';
|
|
8
9
|
|
|
9
10
|
const DragHandle = SortableHandle(() => (
|
|
@@ -195,6 +196,8 @@ const AgreementSignatureEditor = ({
|
|
|
195
196
|
const [editingField, setEditingField] = useState(null);
|
|
196
197
|
const [showFieldEditor, setShowFieldEditor] = useState(false);
|
|
197
198
|
const [isLoading, setIsLoading] = useState(false);
|
|
199
|
+
const [showVariableInserter, setShowVariableInserter] = useState(false);
|
|
200
|
+
const bodyTextRef = useRef(null);
|
|
198
201
|
|
|
199
202
|
// Helper function to replace template variables in URLs
|
|
200
203
|
const buildUrlWithTemplate = (urlTemplate, params = {}) => {
|
|
@@ -399,6 +402,33 @@ const AgreementSignatureEditor = ({
|
|
|
399
402
|
});
|
|
400
403
|
};
|
|
401
404
|
|
|
405
|
+
const handleVariableInsert = (variableName) => {
|
|
406
|
+
const textarea = bodyTextRef.current;
|
|
407
|
+
if (!textarea) return;
|
|
408
|
+
|
|
409
|
+
const start = textarea.selectionStart;
|
|
410
|
+
const end = textarea.selectionEnd;
|
|
411
|
+
const text = textarea.value;
|
|
412
|
+
const before = text.substring(0, start);
|
|
413
|
+
const after = text.substring(end, text.length);
|
|
414
|
+
const variableText = `{{${variableName}}}`;
|
|
415
|
+
|
|
416
|
+
const newText = before + variableText + after;
|
|
417
|
+
|
|
418
|
+
setTemplate({
|
|
419
|
+
...template,
|
|
420
|
+
bodyText: newText
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
// Reset cursor position after the inserted variable
|
|
424
|
+
setTimeout(() => {
|
|
425
|
+
textarea.focus();
|
|
426
|
+
textarea.setSelectionRange(start + variableText.length, start + variableText.length);
|
|
427
|
+
}, 0);
|
|
428
|
+
|
|
429
|
+
setShowVariableInserter(false);
|
|
430
|
+
};
|
|
431
|
+
|
|
402
432
|
const handleSaveTemplate = async () => {
|
|
403
433
|
try {
|
|
404
434
|
setIsLoading(true);
|
|
@@ -508,7 +538,7 @@ const AgreementSignatureEditor = ({
|
|
|
508
538
|
.join('');
|
|
509
539
|
|
|
510
540
|
return `
|
|
511
|
-
<div style="padding: 2rem;
|
|
541
|
+
<div style="padding: 2rem;">
|
|
512
542
|
${templateData.headerText ? `<h3 style="margin-bottom: 1rem; color: #333;">${templateData.headerText}</h3>` : ''}
|
|
513
543
|
<p style="margin-bottom: 2rem; line-height: 1.6;">${templateData.bodyText}</p>
|
|
514
544
|
<div style="clear: both;">${fieldsHtml}</div>
|
|
@@ -548,8 +578,20 @@ const AgreementSignatureEditor = ({
|
|
|
548
578
|
</div>
|
|
549
579
|
|
|
550
580
|
<div className="signature-editor-section">
|
|
551
|
-
<
|
|
581
|
+
<div className="signature-editor-label-with-button">
|
|
582
|
+
<label className="signature-editor-label">Body Text</label>
|
|
583
|
+
<button
|
|
584
|
+
type="button"
|
|
585
|
+
onClick={() => setShowVariableInserter(true)}
|
|
586
|
+
className="signature-btn secondary small"
|
|
587
|
+
title="Insert Variable"
|
|
588
|
+
>
|
|
589
|
+
<Tag size={16} />
|
|
590
|
+
Insert Variable
|
|
591
|
+
</button>
|
|
592
|
+
</div>
|
|
552
593
|
<textarea
|
|
594
|
+
ref={bodyTextRef}
|
|
553
595
|
value={template.bodyText}
|
|
554
596
|
onChange={(e) => setTemplate({...template, bodyText: e.target.value})}
|
|
555
597
|
placeholder="Enter the agreement text. Use {{variable_name}} for dynamic content."
|
|
@@ -557,7 +599,7 @@ const AgreementSignatureEditor = ({
|
|
|
557
599
|
rows="3"
|
|
558
600
|
/>
|
|
559
601
|
<small className="signature-editor-help">
|
|
560
|
-
Use variables like {'{{company_name}}'} for dynamic content
|
|
602
|
+
Use variables like {'{{company_name}}'} for dynamic content. Click "Insert Variable" to browse available variables.
|
|
561
603
|
</small>
|
|
562
604
|
</div>
|
|
563
605
|
|
|
@@ -637,6 +679,14 @@ const AgreementSignatureEditor = ({
|
|
|
637
679
|
</div>
|
|
638
680
|
</div>
|
|
639
681
|
)}
|
|
682
|
+
|
|
683
|
+
{showVariableInserter && (
|
|
684
|
+
<VariableInserter
|
|
685
|
+
onInsert={handleVariableInsert}
|
|
686
|
+
onCancel={() => setShowVariableInserter(false)}
|
|
687
|
+
apiEndpoints={apiEndpoints}
|
|
688
|
+
/>
|
|
689
|
+
)}
|
|
640
690
|
</div>
|
|
641
691
|
);
|
|
642
692
|
};
|