Add new document management components and icons
- Introduced DocumentPrinters, DocumentSizes, and DocumentTemplates components for managing respective entities. - Added corresponding info and design components for each entity. - Created new SVG icons for document-related functionalities. - Implemented hooks for column visibility and view mode management in the new components. - Enhanced user experience with action buttons and modals for creating new entries.
BIN
src/assets/icons/documenticon.afdesign
Normal file
1
src/assets/icons/documenticon.min.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2" viewBox="0 0 64 64"><path d="M15.46 13.515c0-6.725 3.475-10.252 10.149-10.252h11.744c3.596 0 6.407.934 8.744 3.328l15.584 15.857c2.468 2.53 3.322 5.153 3.322 9.261v25.879c0 6.719-3.475 10.251-10.149 10.251h-6.939v-6.122h6.405c3.036 0 4.561-1.604 4.561-4.51V30.221H45.094c-3.841 0-5.878-2.011-5.878-5.878V9.386H26.118c-3.037 0-4.536 1.629-4.536 4.509v5.572a24 24 0 0 0-.543-.006H15.46zM44.326 23.57c0 1.071.443 1.54 1.515 1.54h11.446L44.326 11.945z" style="fill-rule:nonzero" transform="translate(7.224 .331)scale(.76231)"/><path d="M10.149 67.641h33.289c6.699 0 10.148-3.506 10.148-10.231V29.058c0-4.341-.558-6.333-3.278-9.104L33.894 3.284C31.282.616 29.111 0 25.212 0H10.149C3.481 0 0 3.532 0 10.257V57.41c0 6.751 3.455 10.231 10.149 10.231m.488-6.122c-3.016 0-4.515-1.578-4.515-4.49V10.637c0-2.885 1.499-4.515 4.541-4.515h13.321v17.139c0 4.472 2.183 6.634 6.635 6.634h16.845v27.134c0 2.912-1.499 4.49-4.535 4.49zm20.561-37.023c-1.295 0-1.814-.551-1.814-1.84V6.973l17.229 17.523z" style="fill-rule:nonzero" transform="translate(7.224 12.833)scale(.7121)"/><path d="M37.787 51.93c0-1.06-.86-1.921-1.92-1.921h-19.13a1.922 1.922 0 0 0 0 3.845h19.128c1.06 0 1.921-.862 1.921-1.923m.001-6.297c0-1.06-.86-1.922-1.92-1.922h-19.13a1.922 1.922 0 0 0 0 3.845h19.128c1.06 0 1.921-.861 1.921-1.923m.001-6.397c0-1.06-.86-1.922-1.92-1.922h-19.13a1.922 1.922 0 0 0 0 3.845h19.128c1.06 0 1.921-.861 1.921-1.923m-16.139-6.473c0-1.06-.861-1.922-1.922-1.922H16.74a1.923 1.923 0 0 0 0 3.845h2.986c1.06 0 1.922-.861 1.922-1.923"/></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
26
src/assets/icons/documenticon.svg
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(0.75929,0,0,0.75929,7.36648,3.81256)">
|
||||
<g transform="matrix(1.00398,0,0,1.00398,-0.188198,-4.58479)">
|
||||
<path d="M15.46,13.515C15.46,6.79 18.935,3.263 25.609,3.263L37.353,3.263C40.949,3.263 43.76,4.197 46.097,6.591L61.681,22.448C64.149,24.978 65.003,27.601 65.003,31.709L65.003,57.588C65.003,64.307 61.528,67.839 54.854,67.839L47.915,67.839L47.915,61.717L54.32,61.717C57.356,61.717 58.881,60.113 58.881,57.207L58.881,30.221L45.094,30.221C41.253,30.221 39.216,28.21 39.216,24.343L39.216,9.386L26.118,9.386C23.081,9.386 21.582,11.015 21.582,13.895L21.582,19.467C21.407,19.463 21.225,19.461 21.039,19.461L15.46,19.461L15.46,13.515ZM44.326,23.57C44.326,24.641 44.769,25.11 45.841,25.11L57.287,25.11L44.326,11.945L44.326,23.57Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.937843,0,0,0.937843,-0.188198,11.8804)">
|
||||
<path d="M10.149,67.641L43.438,67.641C50.137,67.641 53.586,64.135 53.586,57.41L53.586,29.058C53.586,24.717 53.028,22.725 50.308,19.954L33.894,3.284C31.282,0.616 29.111,0 25.212,0L10.149,0C3.481,0 0,3.532 0,10.257L0,57.41C0,64.161 3.455,67.641 10.149,67.641ZM10.637,61.519C7.621,61.519 6.122,59.941 6.122,57.029L6.122,10.637C6.122,7.752 7.621,6.122 10.663,6.122L23.984,6.122L23.984,23.261C23.984,27.733 26.167,29.895 30.619,29.895L47.464,29.895L47.464,57.029C47.464,59.941 45.965,61.519 42.929,61.519L10.637,61.519ZM31.198,24.496C29.903,24.496 29.384,23.945 29.384,22.656L29.384,6.973L46.613,24.496L31.198,24.496Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.937843,0,0,0.937843,-0.188198,12.4057)">
|
||||
<g transform="matrix(4.7745,0,0,1.46137,-127.467,5.67668)">
|
||||
<path d="M35.687,33.303C35.687,32.284 35.434,31.456 35.122,31.456L29.496,31.456C29.184,31.456 28.931,32.284 28.931,33.303C28.931,34.323 29.184,35.151 29.496,35.151L35.122,35.151C35.434,35.151 35.687,34.323 35.687,33.303Z"/>
|
||||
</g>
|
||||
<g transform="matrix(4.7745,0,0,1.46137,-127.467,-3.16531)">
|
||||
<path d="M35.687,33.303C35.687,32.284 35.434,31.456 35.122,31.456L29.496,31.456C29.184,31.456 28.931,32.284 28.931,33.303C28.931,34.323 29.184,35.151 29.496,35.151L35.122,35.151C35.434,35.151 35.687,34.323 35.687,33.303Z"/>
|
||||
</g>
|
||||
<g transform="matrix(4.7745,0,0,1.46137,-127.467,-12.1487)">
|
||||
<path d="M35.687,33.303C35.687,32.284 35.434,31.456 35.122,31.456L29.496,31.456C29.184,31.456 28.931,32.284 28.931,33.303C28.931,34.323 29.184,35.151 29.496,35.151L35.122,35.151C35.434,35.151 35.687,34.323 35.687,33.303Z"/>
|
||||
</g>
|
||||
<g transform="matrix(1.41967,0,0,1.46137,-30.4087,-21.2388)">
|
||||
<path d="M35.687,33.303C35.687,32.284 34.835,31.456 33.786,31.456L30.832,31.456C29.783,31.456 28.931,32.284 28.931,33.303C28.931,34.323 29.783,35.151 30.832,35.151L33.786,35.151C34.835,35.151 35.687,34.323 35.687,33.303Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/assets/icons/documentprintericon.afdesign
Normal file
1
src/assets/icons/documentprintericon.min.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2" viewBox="0 0 64 64"><path d="M58.753 9.703v1.679h-5.704V9.269c0-2.366-1.2-3.535-3.555-3.535H21.921c-2.329 0-3.555 1.169-3.555 3.535v2.113h-5.704V9.703c0-6.347 3.417-9.234 9.265-9.234h27.56c6.111 0 9.266 2.887 9.266 9.234m12.662 11.358v28.755c0 6.375-3.432 9.68-9.782 9.68h-3.245v-5.535h3.251c2.565 0 3.918-1.347 3.918-3.917V20.839c0-2.57-1.353-3.928-3.918-3.928H9.801c-2.59 0-3.917 1.358-3.917 3.928v29.205c0 2.57 1.327 3.917 3.917 3.917h3.226v5.535h-3.22C3.432 59.496 0 56.191 0 49.816V21.061c0-6.349 3.694-9.679 9.807-9.679h51.826c6.35 0 9.782 3.33 9.782 9.679m-12.861 3.172c0 2.235-1.843 4.052-4.027 4.052a4.057 4.057 0 0 1-4.053-4.052c0-2.184 1.818-4.027 4.053-4.027 2.184 0 4.027 1.843 4.027 4.027" style="fill-rule:nonzero" transform="translate(4 4.73)scale(.78415)"/><path d="M19.642 69.086h32.131c4.43 0 6.615-2.032 6.615-6.621V37.831c0-4.583-2.185-6.615-6.615-6.615H19.642c-4.27 0-6.615 2.032-6.615 6.615v24.634c0 4.589 2.186 6.621 6.615 6.621m1.316-5.393c-1.494 0-2.27-.745-2.27-2.27v-22.57c0-1.524.776-2.238 2.27-2.238h29.525c1.519 0 2.244.714 2.244 2.238v22.57c0 1.525-.725 2.27-2.244 2.27zm4.428-16.733h20.711c1.221 0 2.124-.928 2.124-2.154 0-1.164-.903-2.061-2.124-2.061H25.386c-1.232 0-2.155.897-2.155 2.061 0 1.226.928 2.154 2.155 2.154m0 10.636h20.711c1.221 0 2.124-.922 2.124-2.092 0-1.2-.903-2.128-2.124-2.128H25.386c-1.227 0-2.155.928-2.155 2.128 0 1.17.923 2.092 2.155 2.092" style="fill-rule:nonzero" transform="translate(4 4.73)scale(.78415)"/></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
15
src/assets/icons/documentprintericon.svg
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(0.784149,0,0,0.784149,2.8024,2.29292)">
|
||||
<g transform="matrix(1,0,0,1,1.52726,3.10699)">
|
||||
<path d="M58.753,9.703L58.753,11.382L53.049,11.382L53.049,9.269C53.049,6.903 51.849,5.734 49.494,5.734L21.921,5.734C19.592,5.734 18.366,6.903 18.366,9.269L18.366,11.382L12.662,11.382L12.662,9.703C12.662,3.356 16.079,0.469 21.927,0.469L49.487,0.469C55.598,0.469 58.753,3.356 58.753,9.703Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,1.52726,3.10699)">
|
||||
<path d="M71.415,21.061L71.415,49.816C71.415,56.191 67.983,59.496 61.633,59.496L58.388,59.496L58.388,53.961L61.639,53.961C64.204,53.961 65.557,52.614 65.557,50.044L65.557,20.839C65.557,18.269 64.204,16.911 61.639,16.911L9.801,16.911C7.211,16.911 5.884,18.269 5.884,20.839L5.884,50.044C5.884,52.614 7.211,53.961 9.801,53.961L13.027,53.961L13.027,59.496L9.807,59.496C3.432,59.496 0,56.191 0,49.816L0,21.061C0,14.712 3.694,11.382 9.807,11.382L61.633,11.382C67.983,11.382 71.415,14.712 71.415,21.061ZM58.554,24.233C58.554,26.468 56.711,28.285 54.527,28.285C52.292,28.285 50.474,26.468 50.474,24.233C50.474,22.049 52.292,20.206 54.527,20.206C56.711,20.206 58.554,22.049 58.554,24.233Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,1.52726,3.10699)">
|
||||
<path d="M19.642,69.086L51.773,69.086C56.203,69.086 58.388,67.054 58.388,62.465L58.388,37.831C58.388,33.248 56.203,31.216 51.773,31.216L19.642,31.216C15.372,31.216 13.027,33.248 13.027,37.831L13.027,62.465C13.027,67.054 15.213,69.086 19.642,69.086ZM20.958,63.693C19.464,63.693 18.688,62.948 18.688,61.423L18.688,38.853C18.688,37.329 19.464,36.615 20.958,36.615L50.483,36.615C52.002,36.615 52.727,37.329 52.727,38.853L52.727,61.423C52.727,62.948 52.002,63.693 50.483,63.693L20.958,63.693ZM25.386,46.96L46.097,46.96C47.318,46.96 48.221,46.032 48.221,44.806C48.221,43.642 47.318,42.745 46.097,42.745L25.386,42.745C24.154,42.745 23.231,43.642 23.231,44.806C23.231,46.032 24.159,46.96 25.386,46.96ZM25.386,57.596L46.097,57.596C47.318,57.596 48.221,56.674 48.221,55.504C48.221,54.304 47.318,53.376 46.097,53.376L25.386,53.376C24.159,53.376 23.231,54.304 23.231,55.504C23.231,56.674 24.154,57.596 25.386,57.596Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
BIN
src/assets/icons/documentsizeicon.afdesign
Normal file
1
src/assets/icons/documentsizeicon.min.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2" viewBox="0 0 64 64"><path d="M52.109 26.338V23.46h-10.51c-2.928 0-4.481-1.534-4.481-4.481V7.577h-9.985c-2.314 0-3.457 1.242-3.457 3.437v4.248a18 18 0 0 0-.414-.005h-4.253v-4.533c0-5.126 2.649-7.814 7.736-7.814h8.953c2.742 0 4.884.711 6.666 2.536l11.88 12.088c1.881 1.929 2.532 3.928 2.532 7.06v1.744zM41.014 18.39c0 .816.338 1.174 1.155 1.174h8.725l-9.88-10.037z" style="fill-rule:nonzero"/><path d="M26.506 61.09H14.451c-4.767 0-7.227-2.478-7.227-7.285V20.228c0-4.789 2.478-7.304 7.227-7.304h10.726c2.776 0 4.322.438 6.182 2.338l10.906 11.076h-5.81l-8.307-8.449v10.824a7.1 7.1 0 0 0-1.81 4.738v.216c-1.363-.701-2.036-2.084-2.036-4.179V17.283h-9.485c-2.167 0-3.234 1.161-3.234 3.215v33.036c0 2.073 1.067 3.197 3.215 3.197h11.54v2.818q.002.795.168 1.541" style="fill-rule:nonzero"/><path d="M26.338 50.1H16.74a1.923 1.923 0 0 0 0 3.844h9.6zm0-6.297H16.74a1.923 1.923 0 0 0 0 3.845h9.6zm0-6.397H16.74a1.923 1.923 0 0 0 0 3.845h9.6zm-4.691-4.551c0-1.06-.861-1.922-1.922-1.922H16.74a1.923 1.923 0 0 0 0 3.845h2.986c1.06 0 1.922-.862 1.922-1.923"/><path d="m25.075 47.705-1.007-1.007-1.894-1.796-2.246-2.465.056 2.381.033 2.347c.032.471-.16.965-.496 1.3-.675.676-1.668.694-2.332.029-.384-.383-.524-.801-.488-1.331l.35-8.005c.031-.659.186-1.097.546-1.458.361-.36.799-.516 1.458-.546l8.005-.35c.53-.036.948.104 1.331.487.665.665.657 1.648-.031 2.336a1.76 1.76 0 0 1-1.298.493l-2.349-.03-2.379-.059 2.465 2.247 1.425 1.326 1.945 1.945 1.327 1.425 2.246 2.465-.059-2.379-.03-2.349a1.76 1.76 0 0 1 .493-1.298c.688-.688 1.671-.696 2.336-.031.383.383.523.801.487 1.331l-.35 8.005c-.03.659-.186 1.097-.546 1.458s-.799.515-1.458.546l-8.005.35c-.53.036-.947-.104-1.331-.488-.665-.664-.647-1.657.029-2.332a1.72 1.72 0 0 1 1.3-.496l2.347.033 2.381.056-2.465-2.246z" style="fill-rule:nonzero" transform="matrix(-1.06473 0 0 1.06473 74.043 -2.257)"/><path d="M11.031 59.75h37.688c7.14 0 11.031-3.859 11.031-10.953V10.969C59.75 3.891 55.859 0 48.719 0H11.031C3.906 0 0 3.891 0 10.969v37.828C0 55.891 3.906 59.75 11.031 59.75m.875-8.062c-2.515 0-3.843-1.219-3.843-3.875V11.969c0-2.656 1.328-3.891 3.843-3.891h35.938c2.5 0 3.844 1.235 3.844 3.891v35.844c0 2.656-1.344 3.875-3.844 3.875z" style="fill-rule:nonzero" transform="translate(29 29)scale(.58577)"/></svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
32
src/assets/icons/documentsizeicon.svg
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(0.75929,0,0,0.75929,7.36648,3.90301)">
|
||||
<g transform="matrix(1.31702,0,0,1.31702,-9.70181,-5.14035)">
|
||||
<path d="M52.109,26.338L52.109,23.46L41.599,23.46C38.671,23.46 37.118,21.926 37.118,18.979L37.118,7.577L27.133,7.577C24.819,7.577 23.676,8.819 23.676,11.014L23.676,15.262C23.543,15.259 23.404,15.257 23.262,15.257L19.009,15.257L19.009,10.724C19.009,5.598 21.658,2.91 26.745,2.91L35.698,2.91C38.44,2.91 40.582,3.621 42.364,5.446L54.244,17.534C56.125,19.463 56.776,21.462 56.776,24.594L56.776,26.338L52.109,26.338ZM41.014,18.39C41.014,19.206 41.352,19.564 42.169,19.564L50.894,19.564L41.014,9.527L41.014,18.39Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.31702,0,0,1.31702,-9.70181,-5.14035)">
|
||||
<path d="M26.506,61.09L14.451,61.09C9.684,61.09 7.224,58.612 7.224,53.805L7.224,20.228C7.224,15.439 9.702,12.924 14.451,12.924L25.177,12.924C27.953,12.924 29.499,13.362 31.359,15.262L42.265,26.338L36.455,26.338L28.148,17.889L28.148,28.713C27.023,29.971 26.338,31.632 26.338,33.451L26.338,33.667C24.975,32.966 24.302,31.583 24.302,29.488L24.302,17.283L14.817,17.283C12.65,17.283 11.583,18.444 11.583,20.498L11.583,53.534C11.583,55.607 12.65,56.731 14.798,56.731L26.338,56.731L26.338,59.549C26.338,60.078 26.396,60.594 26.506,61.09Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.937843,0,0,0.937843,-0.188198,12.4057)">
|
||||
<g transform="matrix(1.40431,0,0,1.40431,-10.1441,-18.7089)">
|
||||
<path d="M26.338,50.099L16.739,50.099C15.678,50.099 14.817,50.961 14.817,52.022C14.817,53.083 15.678,53.944 16.739,53.944L26.338,53.944L26.338,50.099Z"/>
|
||||
</g>
|
||||
<g transform="matrix(1.40431,0,0,1.40431,-10.1441,-18.7089)">
|
||||
<path d="M26.338,43.803L16.739,43.803C15.678,43.803 14.817,44.664 14.817,45.725C14.817,46.786 15.678,47.648 16.739,47.648L26.338,47.648L26.338,43.803Z"/>
|
||||
</g>
|
||||
<g transform="matrix(1.40431,0,0,1.40431,-10.1441,-18.7089)">
|
||||
<path d="M26.338,37.406L16.739,37.406C15.678,37.406 14.817,38.267 14.817,39.328C14.817,40.389 15.678,41.251 16.739,41.251L26.338,41.251L26.338,37.406Z"/>
|
||||
</g>
|
||||
<g transform="matrix(1.41967,0,0,1.46137,-30.4087,-21.2388)">
|
||||
<path d="M35.687,33.303C35.687,32.284 34.835,31.456 33.786,31.456L30.832,31.456C29.783,31.456 28.931,32.284 28.931,33.303C28.931,34.323 29.783,35.151 30.832,35.151L33.786,35.151C34.835,35.151 35.687,34.323 35.687,33.303Z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(-1.40227,0,0,1.40227,87.814,-8.11344)">
|
||||
<path d="M25.075,47.705C24.894,47.524 24.249,46.879 24.068,46.698L22.174,44.902L19.928,42.437L19.984,44.818L20.017,47.165C20.049,47.636 19.857,48.13 19.521,48.465C18.846,49.141 17.853,49.159 17.189,48.494C16.805,48.111 16.665,47.693 16.701,47.163L17.051,39.158C17.082,38.499 17.237,38.061 17.597,37.7C17.958,37.34 18.396,37.184 19.055,37.154L27.06,36.804C27.59,36.768 28.008,36.908 28.391,37.291C29.056,37.956 29.048,38.939 28.36,39.627C28.037,39.95 27.538,40.146 27.062,40.12L24.713,40.09L22.334,40.031L24.799,42.278L26.224,43.604L28.169,45.549L29.496,46.974L31.742,49.439L31.683,47.06L31.653,44.711C31.627,44.235 31.823,43.736 32.146,43.413C32.834,42.725 33.817,42.717 34.482,43.382C34.865,43.765 35.005,44.183 34.969,44.713L34.619,52.718C34.589,53.377 34.433,53.815 34.073,54.176C33.712,54.537 33.274,54.691 32.615,54.722L24.61,55.072C24.08,55.108 23.663,54.968 23.279,54.584C22.614,53.92 22.632,52.927 23.308,52.252C23.643,51.916 24.137,51.724 24.608,51.756L26.955,51.789L29.336,51.845L26.871,49.599L25.075,47.705Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.771471,0,0,0.771471,28.4918,33.0532)">
|
||||
<path d="M11.031,59.75L48.719,59.75C55.859,59.75 59.75,55.891 59.75,48.797L59.75,10.969C59.75,3.891 55.859,-0 48.719,-0L11.031,-0C3.906,-0 -0,3.891 -0,10.969L-0,48.797C-0,55.891 3.906,59.75 11.031,59.75ZM11.906,51.688C9.391,51.688 8.063,50.469 8.063,47.813L8.063,11.969C8.063,9.313 9.391,8.078 11.906,8.078L47.844,8.078C50.344,8.078 51.688,9.313 51.688,11.969L51.688,47.813C51.688,50.469 50.344,51.688 47.844,51.688L11.906,51.688Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
BIN
src/assets/icons/documenttemplateicon.afdesign
Normal file
1
src/assets/icons/documenttemplateicon.min.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2" viewBox="0 0 64 64"><path d="M47.11 47.181h-1.17a2.342 2.342 0 0 0 0 4.683h1.17a2.343 2.343 0 0 0 2.341-2.341 2.343 2.343 0 0 0-2.341-2.342m4.74-2.243a3 3 0 0 1-.338.548 2.343 2.343 0 0 0 3.698 2.873q.523-.672.885-1.443a2.342 2.342 0 0 0-4.245-1.978m.244-7.137v1.17a2.344 2.344 0 0 0 2.342 2.34 2.343 2.343 0 0 0 2.34-2.342V37.8a2.341 2.341 0 1 0-4.683.002m-.006-8.195.001 1.17a2.343 2.343 0 0 0 2.343 2.34 2.343 2.343 0 0 0 2.34-2.342v-1.17a2.342 2.342 0 0 0-4.684.002m-.418-7.282c.093.236.161.476.213.736a2.343 2.343 0 0 0 4.59-.932 9 9 0 0 0-.442-1.51 2.342 2.342 0 0 0-4.361 1.706m-32.62-5.133v.008q-.001.078.004.155l.001.03.006.048v.014c.053.584.284 1.005.581 1.31a2.34 2.34 0 0 0 1.749.785s2.341-.162 2.341-2.356V16.03a2.342 2.342 0 0 0-4.683 0zm28.155-.568.81.845a2.343 2.343 0 0 0 3.312.067 2.343 2.343 0 0 0 .067-3.31l-.81-.845a2.342 2.342 0 0 0-3.379 3.243m-5.657-5.908q.406.42.784.821a2.342 2.342 0 0 0 3.405-3.214c-.267-.282-.545-.576-.832-.871a2.343 2.343 0 0 0-3.312-.047 2.343 2.343 0 0 0-.045 3.311M23.83 9.66q.088-.308.243-.593a2.342 2.342 0 1 0-4.105-2.252 7.5 7.5 0 0 0-.643 1.568A2.341 2.341 0 0 0 23.83 9.66M37.143 3h-.874a2.342 2.342 0 0 0 0 4.683h.874q.056 0 .111.004a2.34 2.34 0 1 0 .37-4.667q-.24-.02-.481-.02m-9.07 4.683h1.171a2.343 2.343 0 0 0 2.342-2.342A2.343 2.343 0 0 0 29.244 3h-1.17a2.342 2.342 0 0 0 0 4.683M48.471 19.87h-1.17a2.342 2.342 0 0 0 0 4.684h1.17a2.342 2.342 0 0 0 0-4.683m-6.548-.195a2.4 2.4 0 0 1-.4-.415 2.343 2.343 0 0 0-3.275-.482 2.343 2.343 0 0 0-.482 3.276 7 7 0 0 0 1.22 1.267 2.342 2.342 0 0 0 2.937-3.646m-.553-5.897v-1.171a2.343 2.343 0 0 0-2.342-2.341 2.344 2.344 0 0 0-2.341 2.341v1.17a2.342 2.342 0 0 0 4.683 0"/><path d="M10.149 67.641h33.289c6.699 0 10.148-3.506 10.148-10.231V29.058c0-4.341-.558-6.333-3.278-9.104L33.894 3.284C31.282.616 29.111 0 25.212 0H10.149C3.481 0 0 3.532 0 10.257V57.41c0 6.751 3.455 10.231 10.149 10.231m.488-6.122c-3.016 0-4.515-1.578-4.515-4.49V10.637c0-2.885 1.499-4.515 4.541-4.515h13.321v17.139c0 4.472 2.183 6.634 6.635 6.634h16.845v27.134c0 2.912-1.499 4.49-4.535 4.49zm20.561-37.023c-1.295 0-1.814-.551-1.814-1.84V6.973l17.229 17.523z" style="fill-rule:nonzero" transform="translate(7.224 12.833)scale(.7121)"/><path d="M37.787 51.93c0-1.06-.86-1.921-1.92-1.921h-19.13a1.922 1.922 0 0 0 0 3.845h19.128c1.06 0 1.921-.862 1.921-1.923m.001-6.297c0-1.06-.86-1.922-1.92-1.922h-19.13a1.922 1.922 0 0 0 0 3.845h19.128c1.06 0 1.921-.861 1.921-1.923m.001-6.397c0-1.06-.86-1.922-1.92-1.922h-19.13a1.922 1.922 0 0 0 0 3.845h19.128c1.06 0 1.921-.861 1.921-1.923m-16.139-6.473c0-1.06-.861-1.922-1.922-1.922H16.74a1.923 1.923 0 0 0 0 3.845h2.986c1.06 0 1.922-.861 1.922-1.923"/></svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
29
src/assets/icons/documenttemplateicon.svg
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(0.75929,0,0,0.75929,7.36648,3.81256)">
|
||||
<g transform="matrix(1.37054,0,0,1.37054,-11.3557,-4.11161)">
|
||||
<path d="M46.477,44.675L45.352,44.675C44.11,44.675 43.102,45.683 43.102,46.925C43.102,48.167 44.11,49.175 45.352,49.175L46.477,49.175C47.718,49.175 48.727,48.167 48.727,46.925C48.727,45.683 47.718,44.675 46.477,44.675ZM51.032,42.519C50.944,42.707 50.834,42.883 50.707,43.046C49.946,44.027 50.123,45.442 51.104,46.203C52.085,46.965 53.499,46.787 54.261,45.807C54.595,45.377 54.88,44.914 55.111,44.42C55.635,43.294 55.147,41.954 54.021,41.43C52.896,40.905 51.556,41.394 51.032,42.519ZM51.266,35.661C51.266,36.044 51.266,36.421 51.266,36.786C51.267,38.028 52.276,39.035 53.517,39.035C54.759,39.034 55.767,38.025 55.766,36.784C55.766,36.418 55.766,36.042 55.766,35.659C55.765,34.417 54.756,33.409 53.514,33.41C52.273,33.41 51.265,34.419 51.266,35.661ZM51.261,27.786C51.262,28.131 51.262,28.508 51.262,28.911C51.263,30.153 52.271,31.16 53.513,31.16C54.755,31.159 55.763,30.15 55.762,28.909C55.762,28.506 55.762,28.128 55.761,27.784C55.761,26.542 54.752,25.534 53.51,25.535C52.268,25.535 51.261,26.544 51.261,27.786ZM50.859,20.789C50.948,21.015 51.014,21.246 51.064,21.496C51.311,22.713 52.5,23.5 53.717,23.253C54.934,23.006 55.721,21.817 55.474,20.6C55.37,20.087 55.232,19.614 55.05,19.15C54.598,17.993 53.292,17.422 52.135,17.874C50.979,18.326 50.407,19.632 50.859,20.789ZM19.512,15.856L19.512,15.864C19.512,15.914 19.513,15.963 19.517,16.013L19.518,16.042L19.523,16.088L19.523,16.094L19.524,16.101C19.574,16.662 19.796,17.067 20.082,17.36C20.494,17.822 21.094,18.114 21.762,18.114C21.762,18.114 24.012,17.959 24.012,15.85L24.012,14.739C24.012,13.497 23.004,12.489 21.762,12.489C20.52,12.489 19.512,13.497 19.512,14.739L19.512,15.85L19.512,15.856ZM46.568,15.31C46.85,15.603 47.114,15.879 47.347,16.122C48.207,17.018 49.633,17.047 50.529,16.187C51.425,15.327 51.454,13.901 50.594,13.005C50.36,12.762 50.096,12.487 49.815,12.194C48.955,11.298 47.529,11.269 46.633,12.129C45.737,12.989 45.708,14.414 46.568,15.31ZM41.132,9.633C41.392,9.901 41.644,10.166 41.886,10.422C42.738,11.325 44.163,11.366 45.066,10.514C45.969,9.662 46.01,8.236 45.158,7.333C44.901,7.062 44.634,6.78 44.358,6.496C43.492,5.605 42.066,5.586 41.176,6.451C40.286,7.317 40.266,8.743 41.132,9.633ZM24.106,8.619C24.162,8.422 24.241,8.231 24.34,8.049C24.938,6.96 24.539,5.591 23.45,4.994C22.361,4.397 20.992,4.796 20.395,5.885C20.131,6.365 19.924,6.873 19.777,7.392C19.438,8.587 20.133,9.832 21.328,10.17C22.523,10.509 23.768,9.813 24.106,8.619ZM36.899,2.219L36.89,2.219L36.059,2.219C34.817,2.219 33.809,3.227 33.809,4.469C33.809,5.711 34.817,6.719 36.059,6.719L36.899,6.719C36.935,6.719 36.97,6.721 37.006,6.723C38.244,6.822 39.328,5.896 39.426,4.658C39.524,3.42 38.599,2.336 37.361,2.238C37.207,2.225 37.053,2.219 36.899,2.219L36.899,2.219ZM28.184,6.719L29.309,6.719C30.55,6.719 31.559,5.711 31.559,4.469C31.559,3.227 30.55,2.219 29.309,2.219L28.184,2.219C26.942,2.219 25.934,3.227 25.934,4.469C25.934,5.711 26.942,6.719 28.184,6.719Z"/>
|
||||
</g>
|
||||
<g transform="matrix(1.37054,0,0,1.37054,-11.3557,-4.11161)">
|
||||
<path d="M47.785,18.431L46.66,18.431C45.418,18.431 44.41,19.439 44.41,20.681C44.41,21.923 45.418,22.931 46.66,22.931L47.785,22.931C49.027,22.931 50.035,21.923 50.035,20.681C50.035,19.439 49.027,18.431 47.785,18.431ZM41.493,18.243C41.35,18.127 41.218,17.99 41.109,17.844C40.368,16.848 38.958,16.64 37.961,17.381C36.965,18.122 36.757,19.533 37.498,20.529C37.83,20.976 38.233,21.395 38.671,21.747C39.638,22.526 41.055,22.373 41.834,21.406C42.613,20.439 42.46,19.022 41.493,18.243ZM40.961,12.576L40.961,11.451C40.961,10.21 39.953,9.201 38.711,9.201C37.47,9.201 36.461,10.21 36.461,11.451L36.461,12.576C36.461,13.818 37.47,14.826 38.711,14.826C39.953,14.826 40.961,13.818 40.961,12.576Z"/>
|
||||
</g>
|
||||
<g transform="matrix(0.937843,0,0,0.937843,-0.188198,11.8804)">
|
||||
<path d="M10.149,67.641L43.438,67.641C50.137,67.641 53.586,64.135 53.586,57.41L53.586,29.058C53.586,24.717 53.028,22.725 50.308,19.954L33.894,3.284C31.282,0.616 29.111,0 25.212,0L10.149,0C3.481,0 0,3.532 0,10.257L0,57.41C0,64.161 3.455,67.641 10.149,67.641ZM10.637,61.519C7.621,61.519 6.122,59.941 6.122,57.029L6.122,10.637C6.122,7.752 7.621,6.122 10.663,6.122L23.984,6.122L23.984,23.261C23.984,27.733 26.167,29.895 30.619,29.895L47.464,29.895L47.464,57.029C47.464,59.941 45.965,61.519 42.929,61.519L10.637,61.519ZM31.198,24.496C29.903,24.496 29.384,23.945 29.384,22.656L29.384,6.973L46.613,24.496L31.198,24.496Z" style="fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.937843,0,0,0.937843,-0.188198,12.4057)">
|
||||
<g transform="matrix(4.7745,0,0,1.46137,-127.467,5.67668)">
|
||||
<path d="M35.687,33.303C35.687,32.284 35.434,31.456 35.122,31.456L29.496,31.456C29.184,31.456 28.931,32.284 28.931,33.303C28.931,34.323 29.184,35.151 29.496,35.151L35.122,35.151C35.434,35.151 35.687,34.323 35.687,33.303Z"/>
|
||||
</g>
|
||||
<g transform="matrix(4.7745,0,0,1.46137,-127.467,-3.16531)">
|
||||
<path d="M35.687,33.303C35.687,32.284 35.434,31.456 35.122,31.456L29.496,31.456C29.184,31.456 28.931,32.284 28.931,33.303C28.931,34.323 29.184,35.151 29.496,35.151L35.122,35.151C35.434,35.151 35.687,34.323 35.687,33.303Z"/>
|
||||
</g>
|
||||
<g transform="matrix(4.7745,0,0,1.46137,-127.467,-12.1487)">
|
||||
<path d="M35.687,33.303C35.687,32.284 35.434,31.456 35.122,31.456L29.496,31.456C29.184,31.456 28.931,32.284 28.931,33.303C28.931,34.323 29.184,35.151 29.496,35.151L35.122,35.151C35.434,35.151 35.687,34.323 35.687,33.303Z"/>
|
||||
</g>
|
||||
<g transform="matrix(1.41967,0,0,1.46137,-30.4087,-21.2388)">
|
||||
<path d="M35.687,33.303C35.687,32.284 34.835,31.456 33.786,31.456L30.832,31.456C29.783,31.456 28.931,32.284 28.931,33.303C28.931,34.323 29.783,35.151 30.832,35.151L33.786,35.151C34.835,35.151 35.687,34.323 35.687,33.303Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.3 KiB |
69
src/components/Dashboard/Management/DocumentPrinters.jsx
Normal file
@ -0,0 +1,69 @@
|
||||
import React, { useRef } from 'react'
|
||||
import { Button, Flex, Space, Dropdown } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ReloadIcon from '../../Icons/ReloadIcon'
|
||||
import useColumnVisibility from '../hooks/useColumnVisibility'
|
||||
import GridIcon from '../../Icons/GridIcon'
|
||||
import ListIcon from '../../Icons/ListIcon'
|
||||
import useViewMode from '../hooks/useViewMode'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
|
||||
const DocumentPrinters = () => {
|
||||
const tableRef = useRef()
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('documentPrinter')
|
||||
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
useColumnVisibility('documentPrinter')
|
||||
|
||||
const actionItems = {
|
||||
items: [
|
||||
{
|
||||
label: 'Reload List',
|
||||
key: 'reloadList',
|
||||
icon: <ReloadIcon />
|
||||
}
|
||||
],
|
||||
onClick: ({ key }) => {
|
||||
if (key === 'reloadList') {
|
||||
tableRef.current?.reload()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large'>
|
||||
<Flex justify={'space-between'}>
|
||||
<Space size='small'>
|
||||
<Dropdown menu={actionItems}>
|
||||
<Button>Actions</Button>
|
||||
</Dropdown>
|
||||
<ColumnViewButton
|
||||
type='documentPrinter'
|
||||
loading={false}
|
||||
collapseState={columnVisibility}
|
||||
updateCollapseState={setColumnVisibility}
|
||||
/>
|
||||
</Space>
|
||||
<Space>
|
||||
<Button
|
||||
icon={viewMode === 'cards' ? <ListIcon /> : <GridIcon />}
|
||||
onClick={() =>
|
||||
setViewMode(viewMode === 'cards' ? 'list' : 'cards')
|
||||
}
|
||||
/>
|
||||
</Space>
|
||||
</Flex>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
type='documentPrinter'
|
||||
cards={viewMode === 'cards'}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default DocumentPrinters
|
||||
@ -0,0 +1,201 @@
|
||||
import React from 'react'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { Space, Flex, Card } from 'antd'
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import loglevel from 'loglevel'
|
||||
import config from '../../../../config.js'
|
||||
import useCollapseState from '../../hooks/useCollapseState.js'
|
||||
import NotesPanel from '../../common/NotesPanel.jsx'
|
||||
import InfoCollapse from '../../common/InfoCollapse.jsx'
|
||||
import ObjectInfo from '../../common/ObjectInfo.jsx'
|
||||
import ViewButton from '../../common/ViewButton.jsx'
|
||||
import InfoCircleIcon from '../../../Icons/InfoCircleIcon.jsx'
|
||||
import NoteIcon from '../../../Icons/NoteIcon.jsx'
|
||||
import AuditLogIcon from '../../../Icons/AuditLogIcon.jsx'
|
||||
import EditObjectForm from '../../common/EditObjectForm.jsx'
|
||||
import EditButtons from '../../common/EditButtons.jsx'
|
||||
import LockIndicator from '../../common/LockIndicator.jsx'
|
||||
import ActionHandler from '../../common/ActionHandler.jsx'
|
||||
import ObjectActions from '../../common/ObjectActions.jsx'
|
||||
import ObjectTable from '../../common/ObjectTable.jsx'
|
||||
import InfoCollapsePlaceholder from '../../common/InfoCollapsePlaceholder.jsx'
|
||||
|
||||
const log = loglevel.getLogger('DocumentPrinterInfo')
|
||||
log.setLevel(config.logLevel)
|
||||
|
||||
const DocumentPrinterInfo = () => {
|
||||
const location = useLocation()
|
||||
const documentPrinterId = new URLSearchParams(location.search).get(
|
||||
'documentPrinterId'
|
||||
)
|
||||
const [collapseState, updateCollapseState] = useCollapseState(
|
||||
'DocumentPrinterInfo',
|
||||
{
|
||||
info: true,
|
||||
notes: true,
|
||||
auditLogs: true
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
<EditObjectForm
|
||||
id={documentPrinterId}
|
||||
type='documentPrinter'
|
||||
style={{ height: '100%' }}
|
||||
>
|
||||
{({
|
||||
loading,
|
||||
isEditing,
|
||||
startEditing,
|
||||
cancelEditing,
|
||||
handleUpdate,
|
||||
formValid,
|
||||
objectData,
|
||||
editLoading,
|
||||
lock,
|
||||
fetchObject
|
||||
}) => {
|
||||
// Define actions for ActionHandler
|
||||
const actions = {
|
||||
reload: () => {
|
||||
fetchObject()
|
||||
return true
|
||||
},
|
||||
edit: () => {
|
||||
startEditing()
|
||||
return false
|
||||
},
|
||||
cancelEdit: () => {
|
||||
cancelEditing()
|
||||
return true
|
||||
},
|
||||
finishEdit: () => {
|
||||
handleUpdate()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ActionHandler actions={actions} loading={loading}>
|
||||
{({ callAction }) => (
|
||||
<Flex
|
||||
gap='large'
|
||||
vertical='true'
|
||||
style={{
|
||||
height: 'calc(var(--unit-100vh) - 155px)',
|
||||
minHeight: 0
|
||||
}}
|
||||
>
|
||||
<Flex justify={'space-between'}>
|
||||
<Space size='middle'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='documentPrinter'
|
||||
id={documentPrinterId}
|
||||
disabled={loading}
|
||||
/>
|
||||
<ViewButton
|
||||
disabled={loading}
|
||||
items={[
|
||||
{
|
||||
key: 'info',
|
||||
label: 'DocumentPrinter Information'
|
||||
},
|
||||
{ key: 'stocks', label: 'DocumentPrinter Stocks' },
|
||||
{ key: 'notes', label: 'Notes' },
|
||||
{ key: 'auditLogs', label: 'Audit Logs' }
|
||||
]}
|
||||
visibleState={collapseState}
|
||||
updateVisibleState={updateCollapseState}
|
||||
/>
|
||||
</Space>
|
||||
<LockIndicator lock={lock} />
|
||||
</Space>
|
||||
<Space>
|
||||
<EditButtons
|
||||
isEditing={isEditing}
|
||||
handleUpdate={() => {
|
||||
callAction('finishEdit')
|
||||
}}
|
||||
cancelEditing={() => {
|
||||
callAction('cancelEdit')
|
||||
}}
|
||||
startEditing={() => {
|
||||
callAction('edit')
|
||||
}}
|
||||
editLoading={editLoading}
|
||||
formValid={formValid}
|
||||
disabled={lock?.locked || loading}
|
||||
loading={editLoading}
|
||||
/>
|
||||
</Space>
|
||||
</Flex>
|
||||
|
||||
<div style={{ height: '100%', overflowY: 'scroll' }}>
|
||||
<Flex vertical gap={'large'}>
|
||||
<InfoCollapse
|
||||
title='Document Printer Information'
|
||||
icon={<InfoCircleIcon />}
|
||||
active={collapseState.info}
|
||||
onToggle={(expanded) =>
|
||||
updateCollapseState('info', expanded)
|
||||
}
|
||||
collapseKey='info'
|
||||
>
|
||||
<ObjectInfo
|
||||
loading={loading}
|
||||
indicator={<LoadingOutlined />}
|
||||
isEditing={isEditing}
|
||||
type='documentPrinter'
|
||||
objectData={objectData}
|
||||
/>
|
||||
</InfoCollapse>
|
||||
|
||||
<InfoCollapse
|
||||
title='Notes'
|
||||
icon={<NoteIcon />}
|
||||
active={collapseState.notes}
|
||||
onToggle={(expanded) =>
|
||||
updateCollapseState('notes', expanded)
|
||||
}
|
||||
collapseKey='notes'
|
||||
>
|
||||
<Card>
|
||||
<NotesPanel
|
||||
_id={documentPrinterId}
|
||||
type='documentPrinter'
|
||||
/>
|
||||
</Card>
|
||||
</InfoCollapse>
|
||||
|
||||
<InfoCollapse
|
||||
title='Audit Logs'
|
||||
icon={<AuditLogIcon />}
|
||||
active={collapseState.auditLogs}
|
||||
onToggle={(expanded) =>
|
||||
updateCollapseState('auditLogs', expanded)
|
||||
}
|
||||
collapseKey='auditLogs'
|
||||
>
|
||||
{loading ? (
|
||||
<InfoCollapsePlaceholder />
|
||||
) : (
|
||||
<ObjectTable
|
||||
type='auditLog'
|
||||
masterFilter={{ 'parent._id': documentPrinterId }}
|
||||
visibleColumns={{ _id: false, 'parent._id': false }}
|
||||
/>
|
||||
)}
|
||||
</InfoCollapse>
|
||||
</Flex>
|
||||
</div>
|
||||
</Flex>
|
||||
)}
|
||||
</ActionHandler>
|
||||
)
|
||||
}}
|
||||
</EditObjectForm>
|
||||
)
|
||||
}
|
||||
|
||||
export default DocumentPrinterInfo
|
||||
98
src/components/Dashboard/Management/DocumentSizes.jsx
Normal file
@ -0,0 +1,98 @@
|
||||
import React, { useState, useRef } from 'react'
|
||||
import { Button, Flex, Space, Modal, Dropdown, message } from 'antd'
|
||||
import NewDocumentSize from './DocumentSizes/NewDocumentSize'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import PlusIcon from '../../Icons/PlusIcon'
|
||||
import ReloadIcon from '../../Icons/ReloadIcon'
|
||||
import useColumnVisibility from '../hooks/useColumnVisibility'
|
||||
import GridIcon from '../../Icons/GridIcon'
|
||||
import ListIcon from '../../Icons/ListIcon'
|
||||
import useViewMode from '../hooks/useViewMode'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
|
||||
const DocumentSizes = () => {
|
||||
const [messageApi, contextHolder] = message.useMessage()
|
||||
const [newDocumentSizeOpen, setNewDocumentSizeOpen] = useState(false)
|
||||
const tableRef = useRef()
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('documentSize')
|
||||
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
useColumnVisibility('documentSize')
|
||||
|
||||
const actionItems = {
|
||||
items: [
|
||||
{
|
||||
label: 'New Document Size',
|
||||
key: 'newDocumentSize',
|
||||
icon: <PlusIcon />
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
label: 'Reload List',
|
||||
key: 'reloadList',
|
||||
icon: <ReloadIcon />
|
||||
}
|
||||
],
|
||||
onClick: ({ key }) => {
|
||||
if (key === 'reloadList') {
|
||||
tableRef.current?.reload()
|
||||
} else if (key === 'newDocumentSize') {
|
||||
setNewDocumentSizeOpen(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large'>
|
||||
{contextHolder}
|
||||
<Flex justify={'space-between'}>
|
||||
<Space size='small'>
|
||||
<Dropdown menu={actionItems}>
|
||||
<Button>Actions</Button>
|
||||
</Dropdown>
|
||||
<ColumnViewButton
|
||||
type='documentSize'
|
||||
loading={false}
|
||||
collapseState={columnVisibility}
|
||||
updateCollapseState={setColumnVisibility}
|
||||
/>
|
||||
</Space>
|
||||
<Space>
|
||||
<Button
|
||||
icon={viewMode === 'cards' ? <ListIcon /> : <GridIcon />}
|
||||
onClick={() =>
|
||||
setViewMode(viewMode === 'cards' ? 'list' : 'cards')
|
||||
}
|
||||
/>
|
||||
</Space>
|
||||
</Flex>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
type='documentSize'
|
||||
cards={viewMode === 'cards'}
|
||||
/>
|
||||
</Flex>
|
||||
<Modal
|
||||
open={newDocumentSizeOpen}
|
||||
onCancel={() => setNewDocumentSizeOpen(false)}
|
||||
footer={null}
|
||||
destroyOnHidden={true}
|
||||
width={700}
|
||||
>
|
||||
<NewDocumentSize
|
||||
onOk={() => {
|
||||
setNewDocumentSizeOpen(false)
|
||||
messageApi.success('New note type created successfully.')
|
||||
tableRef.current?.reload()
|
||||
}}
|
||||
reset={!newDocumentSizeOpen}
|
||||
/>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default DocumentSizes
|
||||
@ -0,0 +1,195 @@
|
||||
import React from 'react'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { Space, Flex, Card } from 'antd'
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import loglevel from 'loglevel'
|
||||
import config from '../../../../config.js'
|
||||
import useCollapseState from '../../hooks/useCollapseState.js'
|
||||
import NotesPanel from '../../common/NotesPanel.jsx'
|
||||
import InfoCollapse from '../../common/InfoCollapse.jsx'
|
||||
import ObjectInfo from '../../common/ObjectInfo.jsx'
|
||||
import ViewButton from '../../common/ViewButton.jsx'
|
||||
import InfoCircleIcon from '../../../Icons/InfoCircleIcon.jsx'
|
||||
import NoteIcon from '../../../Icons/NoteIcon.jsx'
|
||||
import AuditLogIcon from '../../../Icons/AuditLogIcon.jsx'
|
||||
import EditObjectForm from '../../common/EditObjectForm.jsx'
|
||||
import EditButtons from '../../common/EditButtons.jsx'
|
||||
import LockIndicator from '../../common/LockIndicator.jsx'
|
||||
import ActionHandler from '../../common/ActionHandler.jsx'
|
||||
import ObjectActions from '../../common/ObjectActions.jsx'
|
||||
import ObjectTable from '../../common/ObjectTable.jsx'
|
||||
import InfoCollapsePlaceholder from '../../common/InfoCollapsePlaceholder.jsx'
|
||||
|
||||
const log = loglevel.getLogger('DocumentSizeInfo')
|
||||
log.setLevel(config.logLevel)
|
||||
|
||||
const DocumentSizeInfo = () => {
|
||||
const location = useLocation()
|
||||
const documentSizeId = new URLSearchParams(location.search).get(
|
||||
'documentSizeId'
|
||||
)
|
||||
const [collapseState, updateCollapseState] = useCollapseState(
|
||||
'DocumentSizeInfo',
|
||||
{
|
||||
info: true,
|
||||
notes: true,
|
||||
auditLogs: true
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
<EditObjectForm
|
||||
id={documentSizeId}
|
||||
type='documentSize'
|
||||
style={{ height: '100%' }}
|
||||
>
|
||||
{({
|
||||
loading,
|
||||
isEditing,
|
||||
startEditing,
|
||||
cancelEditing,
|
||||
handleUpdate,
|
||||
formValid,
|
||||
objectData,
|
||||
editLoading,
|
||||
lock,
|
||||
fetchObject
|
||||
}) => {
|
||||
// Define actions for ActionHandler
|
||||
const actions = {
|
||||
reload: () => {
|
||||
fetchObject()
|
||||
return true
|
||||
},
|
||||
edit: () => {
|
||||
startEditing()
|
||||
return false
|
||||
},
|
||||
cancelEdit: () => {
|
||||
cancelEditing()
|
||||
return true
|
||||
},
|
||||
finishEdit: () => {
|
||||
handleUpdate()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ActionHandler actions={actions} loading={loading}>
|
||||
{({ callAction }) => (
|
||||
<Flex
|
||||
gap='large'
|
||||
vertical='true'
|
||||
style={{
|
||||
height: 'calc(var(--unit-100vh) - 155px)',
|
||||
minHeight: 0
|
||||
}}
|
||||
>
|
||||
<Flex justify={'space-between'}>
|
||||
<Space size='middle'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='documentSize'
|
||||
id={documentSizeId}
|
||||
disabled={loading}
|
||||
/>
|
||||
<ViewButton
|
||||
disabled={loading}
|
||||
items={[
|
||||
{ key: 'info', label: 'DocumentSize Information' },
|
||||
{ key: 'stocks', label: 'DocumentSize Stocks' },
|
||||
{ key: 'notes', label: 'Notes' },
|
||||
{ key: 'auditLogs', label: 'Audit Logs' }
|
||||
]}
|
||||
visibleState={collapseState}
|
||||
updateVisibleState={updateCollapseState}
|
||||
/>
|
||||
</Space>
|
||||
<LockIndicator lock={lock} />
|
||||
</Space>
|
||||
<Space>
|
||||
<EditButtons
|
||||
isEditing={isEditing}
|
||||
handleUpdate={() => {
|
||||
callAction('finishEdit')
|
||||
}}
|
||||
cancelEditing={() => {
|
||||
callAction('cancelEdit')
|
||||
}}
|
||||
startEditing={() => {
|
||||
callAction('edit')
|
||||
}}
|
||||
editLoading={editLoading}
|
||||
formValid={formValid}
|
||||
disabled={lock?.locked || loading}
|
||||
loading={editLoading}
|
||||
/>
|
||||
</Space>
|
||||
</Flex>
|
||||
|
||||
<div style={{ height: '100%', overflowY: 'scroll' }}>
|
||||
<Flex vertical gap={'large'}>
|
||||
<InfoCollapse
|
||||
title='Document Size Information'
|
||||
icon={<InfoCircleIcon />}
|
||||
active={collapseState.info}
|
||||
onToggle={(expanded) =>
|
||||
updateCollapseState('info', expanded)
|
||||
}
|
||||
collapseKey='info'
|
||||
>
|
||||
<ObjectInfo
|
||||
loading={loading}
|
||||
indicator={<LoadingOutlined />}
|
||||
isEditing={isEditing}
|
||||
type='documentSize'
|
||||
objectData={objectData}
|
||||
/>
|
||||
</InfoCollapse>
|
||||
|
||||
<InfoCollapse
|
||||
title='Notes'
|
||||
icon={<NoteIcon />}
|
||||
active={collapseState.notes}
|
||||
onToggle={(expanded) =>
|
||||
updateCollapseState('notes', expanded)
|
||||
}
|
||||
collapseKey='notes'
|
||||
>
|
||||
<Card>
|
||||
<NotesPanel _id={documentSizeId} type='documentSize' />
|
||||
</Card>
|
||||
</InfoCollapse>
|
||||
|
||||
<InfoCollapse
|
||||
title='Audit Logs'
|
||||
icon={<AuditLogIcon />}
|
||||
active={collapseState.auditLogs}
|
||||
onToggle={(expanded) =>
|
||||
updateCollapseState('auditLogs', expanded)
|
||||
}
|
||||
collapseKey='auditLogs'
|
||||
>
|
||||
{loading ? (
|
||||
<InfoCollapsePlaceholder />
|
||||
) : (
|
||||
<ObjectTable
|
||||
type='auditLog'
|
||||
masterFilter={{ 'parent._id': documentSizeId }}
|
||||
visibleColumns={{ _id: false, 'parent._id': false }}
|
||||
/>
|
||||
)}
|
||||
</InfoCollapse>
|
||||
</Flex>
|
||||
</div>
|
||||
</Flex>
|
||||
)}
|
||||
</ActionHandler>
|
||||
)
|
||||
}}
|
||||
</EditObjectForm>
|
||||
)
|
||||
}
|
||||
|
||||
export default DocumentSizeInfo
|
||||
@ -0,0 +1,103 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { useState } from 'react'
|
||||
import { useMediaQuery } from 'react-responsive'
|
||||
import { Typography, Flex, Steps, Divider } from 'antd'
|
||||
|
||||
import ObjectInfo from '../../common/ObjectInfo'
|
||||
import NewObjectForm from '../../common/NewObjectForm'
|
||||
import NewObjectButtons from '../../common/NewObjectButtons'
|
||||
|
||||
const { Title } = Typography
|
||||
|
||||
const NewDocumentSize = ({ onOk }) => {
|
||||
const [currentStep, setCurrentStep] = useState(0)
|
||||
|
||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
||||
|
||||
return (
|
||||
<NewObjectForm type={'documentSize'}>
|
||||
{({ handleSubmit, submitLoading, objectData, formValid }) => {
|
||||
const steps = [
|
||||
{
|
||||
title: 'Required',
|
||||
key: 'required',
|
||||
content: (
|
||||
<ObjectInfo
|
||||
type='documentSize'
|
||||
column={1}
|
||||
bordered={false}
|
||||
isEditing={true}
|
||||
required={true}
|
||||
objectData={objectData}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: 'Summary',
|
||||
key: 'summary',
|
||||
content: (
|
||||
<ObjectInfo
|
||||
type='documentSize'
|
||||
column={1}
|
||||
bordered={false}
|
||||
visibleProperties={{
|
||||
_id: false,
|
||||
createdAt: false,
|
||||
updatedAt: false
|
||||
}}
|
||||
isEditing={false}
|
||||
objectData={objectData}
|
||||
/>
|
||||
)
|
||||
}
|
||||
]
|
||||
return (
|
||||
<Flex gap='middle'>
|
||||
{!isMobile && (
|
||||
<div style={{ minWidth: '160px' }}>
|
||||
<Steps
|
||||
current={currentStep}
|
||||
items={steps}
|
||||
direction='vertical'
|
||||
style={{ width: 'fit-content' }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!isMobile && (
|
||||
<Divider type='vertical' style={{ height: 'unset' }} />
|
||||
)}
|
||||
|
||||
<Flex vertical gap='middle' style={{ flexGrow: 1 }}>
|
||||
<Title level={2} style={{ margin: 0 }}>
|
||||
New Document Size
|
||||
</Title>
|
||||
<div style={{ minHeight: '260px', marginBottom: 8 }}>
|
||||
{steps[currentStep].content}
|
||||
</div>
|
||||
<NewObjectButtons
|
||||
currentStep={currentStep}
|
||||
totalSteps={steps.length}
|
||||
onPrevious={() => setCurrentStep((prev) => prev - 1)}
|
||||
onNext={() => setCurrentStep((prev) => prev + 1)}
|
||||
onSubmit={() => {
|
||||
handleSubmit()
|
||||
onOk()
|
||||
}}
|
||||
formValid={formValid}
|
||||
submitLoading={submitLoading}
|
||||
/>
|
||||
</Flex>
|
||||
</Flex>
|
||||
)
|
||||
}}
|
||||
</NewObjectForm>
|
||||
)
|
||||
}
|
||||
|
||||
NewDocumentSize.propTypes = {
|
||||
onOk: PropTypes.func.isRequired,
|
||||
reset: PropTypes.bool
|
||||
}
|
||||
|
||||
export default NewDocumentSize
|
||||
98
src/components/Dashboard/Management/DocumentTemplates.jsx
Normal file
@ -0,0 +1,98 @@
|
||||
import React, { useState, useRef } from 'react'
|
||||
import { Button, Flex, Space, Modal, Dropdown, message } from 'antd'
|
||||
import NewDocumentTemplate from './DocumentTemplates/NewDocumentTemplate'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import PlusIcon from '../../Icons/PlusIcon'
|
||||
import ReloadIcon from '../../Icons/ReloadIcon'
|
||||
import useColumnVisibility from '../hooks/useColumnVisibility'
|
||||
import GridIcon from '../../Icons/GridIcon'
|
||||
import ListIcon from '../../Icons/ListIcon'
|
||||
import useViewMode from '../hooks/useViewMode'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
|
||||
const DocumentTemplates = () => {
|
||||
const [messageApi, contextHolder] = message.useMessage()
|
||||
const [newDocumentTemplateOpen, setNewDocumentTemplateOpen] = useState(false)
|
||||
const tableRef = useRef()
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('documentTemplate')
|
||||
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
useColumnVisibility('documentTemplate')
|
||||
|
||||
const actionItems = {
|
||||
items: [
|
||||
{
|
||||
label: 'New Document Template',
|
||||
key: 'newDocumentTemplate',
|
||||
icon: <PlusIcon />
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
label: 'Reload List',
|
||||
key: 'reloadList',
|
||||
icon: <ReloadIcon />
|
||||
}
|
||||
],
|
||||
onClick: ({ key }) => {
|
||||
if (key === 'reloadList') {
|
||||
tableRef.current?.reload()
|
||||
} else if (key === 'newDocumentTemplate') {
|
||||
setNewDocumentTemplateOpen(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large'>
|
||||
{contextHolder}
|
||||
<Flex justify={'space-between'}>
|
||||
<Space size='small'>
|
||||
<Dropdown menu={actionItems}>
|
||||
<Button>Actions</Button>
|
||||
</Dropdown>
|
||||
<ColumnViewButton
|
||||
type='documentTemplate'
|
||||
loading={false}
|
||||
collapseState={columnVisibility}
|
||||
updateCollapseState={setColumnVisibility}
|
||||
/>
|
||||
</Space>
|
||||
<Space>
|
||||
<Button
|
||||
icon={viewMode === 'cards' ? <ListIcon /> : <GridIcon />}
|
||||
onClick={() =>
|
||||
setViewMode(viewMode === 'cards' ? 'list' : 'cards')
|
||||
}
|
||||
/>
|
||||
</Space>
|
||||
</Flex>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
type='documentTemplate'
|
||||
cards={viewMode === 'cards'}
|
||||
/>
|
||||
</Flex>
|
||||
<Modal
|
||||
open={newDocumentTemplateOpen}
|
||||
onCancel={() => setNewDocumentTemplateOpen(false)}
|
||||
footer={null}
|
||||
destroyOnHidden={true}
|
||||
width={700}
|
||||
>
|
||||
<NewDocumentTemplate
|
||||
onOk={() => {
|
||||
setNewDocumentTemplateOpen(false)
|
||||
messageApi.success('New note type created successfully.')
|
||||
tableRef.current?.reload()
|
||||
}}
|
||||
reset={!newDocumentTemplateOpen}
|
||||
/>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default DocumentTemplates
|
||||
@ -0,0 +1,171 @@
|
||||
import React, { useState, useRef } from 'react'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { Space, Flex, Card } from 'antd'
|
||||
import loglevel from 'loglevel'
|
||||
import config from '../../../../config.js'
|
||||
import useCollapseState from '../../hooks/useCollapseState.js'
|
||||
import NotesPanel from '../../common/NotesPanel.jsx'
|
||||
import InfoCollapse from '../../common/InfoCollapse.jsx'
|
||||
import ViewButton from '../../common/ViewButton.jsx'
|
||||
import NoteIcon from '../../../Icons/NoteIcon.jsx'
|
||||
import EditObjectForm from '../../common/EditObjectForm.jsx'
|
||||
import EditButtons from '../../common/EditButtons.jsx'
|
||||
import LockIndicator from '../../common/LockIndicator.jsx'
|
||||
import ActionHandler from '../../common/ActionHandler.jsx'
|
||||
import ObjectActions from '../../common/ObjectActions.jsx'
|
||||
|
||||
import TemplateEditor from '../../common/TemplateEditor.jsx'
|
||||
|
||||
const log = loglevel.getLogger('DocumentTemplateDesign')
|
||||
log.setLevel(config.logLevel)
|
||||
|
||||
const DocumentTemplateDesign = () => {
|
||||
const location = useLocation()
|
||||
const editFormRef = useRef(null)
|
||||
const actionHandlerRef = useRef(null)
|
||||
const documentTemplateId = new URLSearchParams(location.search).get(
|
||||
'documentTemplateId'
|
||||
)
|
||||
const [collapseState, updateCollapseState] = useCollapseState(
|
||||
'DocumentTemplateDesign',
|
||||
{
|
||||
preview: true,
|
||||
editor: true,
|
||||
notes: true,
|
||||
auditLogs: true
|
||||
}
|
||||
)
|
||||
|
||||
const [editFormState, setEditFormState] = useState({
|
||||
isEditing: false,
|
||||
editLoading: false,
|
||||
formValid: false,
|
||||
locked: false,
|
||||
loading: false
|
||||
})
|
||||
|
||||
const actions = {
|
||||
reload: () => {
|
||||
editFormRef?.current.handleFetchObject()
|
||||
return true
|
||||
},
|
||||
edit: () => {
|
||||
editFormRef?.current.startEditing()
|
||||
return false
|
||||
},
|
||||
cancelEdit: () => {
|
||||
editFormRef?.current.cancelEditing()
|
||||
return true
|
||||
},
|
||||
finishEdit: () => {
|
||||
editFormRef?.current.handleUpdate()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex
|
||||
gap='large'
|
||||
vertical='true'
|
||||
style={{
|
||||
height: 'calc(var(--unit-100vh) - 155px)',
|
||||
minHeight: 0
|
||||
}}
|
||||
>
|
||||
<Flex justify={'space-between'}>
|
||||
<Space size='middle'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='documentTemplate'
|
||||
id={documentTemplateId}
|
||||
disabled={editFormState.loading}
|
||||
visibleActions={{ edit: false }}
|
||||
/>
|
||||
<ViewButton
|
||||
disabled={editFormState.loading}
|
||||
items={[
|
||||
{
|
||||
key: 'preview',
|
||||
label: 'Preview'
|
||||
},
|
||||
{
|
||||
key: 'editor',
|
||||
label: 'Editor'
|
||||
},
|
||||
{ key: 'notes', label: 'Notes' },
|
||||
{ key: 'auditLogs', label: 'Audit Logs' }
|
||||
]}
|
||||
visibleState={collapseState}
|
||||
updateVisibleState={updateCollapseState}
|
||||
/>
|
||||
</Space>
|
||||
<LockIndicator lock={editFormState.lock} />
|
||||
</Space>
|
||||
<Space>
|
||||
<EditButtons
|
||||
isEditing={editFormState.isEditing}
|
||||
handleUpdate={() => {
|
||||
actionHandlerRef.current.callAction('finishEdit')
|
||||
}}
|
||||
cancelEditing={() => {
|
||||
actionHandlerRef.current.callAction('cancelEdit')
|
||||
}}
|
||||
startEditing={() => {
|
||||
actionHandlerRef.current.callAction('edit')
|
||||
}}
|
||||
editLoading={editFormState.editLoading}
|
||||
formValid={editFormState.formValid}
|
||||
disabled={editFormState.lock?.locked || editFormState.loading}
|
||||
loading={editFormState.editLoading}
|
||||
/>
|
||||
</Space>
|
||||
</Flex>
|
||||
|
||||
<div style={{ height: '100%', overflowY: 'scroll' }}>
|
||||
<Flex vertical gap={'large'}>
|
||||
<ActionHandler
|
||||
actions={actions}
|
||||
loading={editFormState.loading}
|
||||
ref={actionHandlerRef}
|
||||
>
|
||||
<EditObjectForm
|
||||
id={documentTemplateId}
|
||||
type='documentTemplate'
|
||||
style={{ height: '100%' }}
|
||||
ref={editFormRef}
|
||||
onStateChange={(state) => {
|
||||
console.log('Got edit form state change', state)
|
||||
setEditFormState((prev) => ({ ...prev, ...state }))
|
||||
}}
|
||||
>
|
||||
{({ loading, isEditing, objectData }) => {
|
||||
return (
|
||||
<TemplateEditor
|
||||
objectData={objectData}
|
||||
loading={loading}
|
||||
style={{ height: '72vh' }}
|
||||
collapseState={collapseState}
|
||||
isEditing={isEditing}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
</EditObjectForm>
|
||||
</ActionHandler>
|
||||
<InfoCollapse
|
||||
title='Notes'
|
||||
icon={<NoteIcon />}
|
||||
active={collapseState.notes}
|
||||
onToggle={(expanded) => updateCollapseState('notes', expanded)}
|
||||
collapseKey='notes'
|
||||
>
|
||||
<Card>
|
||||
<NotesPanel _id={documentTemplateId} type='documentTemplate' />
|
||||
</Card>
|
||||
</InfoCollapse>
|
||||
</Flex>
|
||||
</div>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
export default DocumentTemplateDesign
|
||||
@ -0,0 +1,202 @@
|
||||
import React, { useRef, useState } from 'react'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { Space, Flex, Card } from 'antd'
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import loglevel from 'loglevel'
|
||||
import config from '../../../../config.js'
|
||||
import useCollapseState from '../../hooks/useCollapseState.js'
|
||||
import NotesPanel from '../../common/NotesPanel.jsx'
|
||||
import InfoCollapse from '../../common/InfoCollapse.jsx'
|
||||
import ObjectInfo from '../../common/ObjectInfo.jsx'
|
||||
import ViewButton from '../../common/ViewButton.jsx'
|
||||
import InfoCircleIcon from '../../../Icons/InfoCircleIcon.jsx'
|
||||
import NoteIcon from '../../../Icons/NoteIcon.jsx'
|
||||
import AuditLogIcon from '../../../Icons/AuditLogIcon.jsx'
|
||||
import EditObjectForm from '../../common/EditObjectForm.jsx'
|
||||
import EditButtons from '../../common/EditButtons.jsx'
|
||||
import LockIndicator from '../../common/LockIndicator.jsx'
|
||||
import ActionHandler from '../../common/ActionHandler.jsx'
|
||||
import ObjectActions from '../../common/ObjectActions.jsx'
|
||||
import ObjectTable from '../../common/ObjectTable.jsx'
|
||||
import InfoCollapsePlaceholder from '../../common/InfoCollapsePlaceholder.jsx'
|
||||
|
||||
const log = loglevel.getLogger('DocumentTemplateInfo')
|
||||
log.setLevel(config.logLevel)
|
||||
|
||||
const DocumentTemplateInfo = () => {
|
||||
const location = useLocation()
|
||||
const editFormRef = useRef(null)
|
||||
const actionHandlerRef = useRef(null)
|
||||
const documentTemplateId = new URLSearchParams(location.search).get(
|
||||
'documentTemplateId'
|
||||
)
|
||||
const [collapseState, updateCollapseState] = useCollapseState(
|
||||
'DocumentTemplateInfo',
|
||||
{
|
||||
info: true,
|
||||
stocks: true,
|
||||
notes: true,
|
||||
auditLogs: true
|
||||
}
|
||||
)
|
||||
|
||||
const [editFormState, setEditFormState] = useState({
|
||||
isEditing: false,
|
||||
editLoading: false,
|
||||
formValid: false,
|
||||
locked: false,
|
||||
loading: false
|
||||
})
|
||||
|
||||
const actions = {
|
||||
reload: () => {
|
||||
editFormRef?.current.handleFetchObject()
|
||||
return true
|
||||
},
|
||||
edit: () => {
|
||||
editFormRef?.current.startEditing()
|
||||
return false
|
||||
},
|
||||
cancelEdit: () => {
|
||||
editFormRef?.current.cancelEditing()
|
||||
return true
|
||||
},
|
||||
finishEdit: () => {
|
||||
editFormRef?.current.handleUpdate()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex
|
||||
gap='large'
|
||||
vertical='true'
|
||||
style={{
|
||||
height: 'calc(var(--unit-100vh) - 155px)',
|
||||
minHeight: 0
|
||||
}}
|
||||
>
|
||||
<Flex justify={'space-between'}>
|
||||
<Space size='middle'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='documentTemplate'
|
||||
id={documentTemplateId}
|
||||
disabled={editFormState.loading}
|
||||
/>
|
||||
<ViewButton
|
||||
disabled={editFormState.loading}
|
||||
items={[
|
||||
{ key: 'info', label: 'DocumentTemplate Information' },
|
||||
{ key: 'notes', label: 'Notes' },
|
||||
{ key: 'auditLogs', label: 'Audit Logs' }
|
||||
]}
|
||||
visibleState={collapseState}
|
||||
updateVisibleState={updateCollapseState}
|
||||
/>
|
||||
</Space>
|
||||
<LockIndicator lock={editFormState.lock} />
|
||||
</Space>
|
||||
<Space>
|
||||
<EditButtons
|
||||
isEditing={editFormState.isEditing}
|
||||
handleUpdate={() => {
|
||||
actionHandlerRef.current.callAction('finishEdit')
|
||||
}}
|
||||
cancelEditing={() => {
|
||||
actionHandlerRef.current.callAction('cancelEdit')
|
||||
}}
|
||||
startEditing={() => {
|
||||
actionHandlerRef.current.callAction('edit')
|
||||
}}
|
||||
editLoading={editFormState.editLoading}
|
||||
formValid={editFormState.formValid}
|
||||
disabled={editFormState.lock?.locked || editFormState.loading}
|
||||
loading={editFormState.editLoading}
|
||||
/>
|
||||
</Space>
|
||||
</Flex>
|
||||
|
||||
<div style={{ height: '100%', overflowY: 'scroll' }}>
|
||||
<Flex vertical gap={'large'}>
|
||||
<ActionHandler
|
||||
actions={actions}
|
||||
loading={editFormState.loading}
|
||||
ref={actionHandlerRef}
|
||||
>
|
||||
<InfoCollapse
|
||||
title='DocumentTemplate Information'
|
||||
icon={<InfoCircleIcon />}
|
||||
active={collapseState.info}
|
||||
onToggle={(expanded) => updateCollapseState('info', expanded)}
|
||||
collapseKey='info'
|
||||
>
|
||||
<EditObjectForm
|
||||
id={documentTemplateId}
|
||||
type='documentTemplate'
|
||||
style={{ height: '100%' }}
|
||||
ref={editFormRef}
|
||||
onStateChange={(state) => {
|
||||
console.log('Got edit form state change', state)
|
||||
setEditFormState((prev) => ({ ...prev, ...state }))
|
||||
}}
|
||||
>
|
||||
{({ loading, isEditing, objectData }) => {
|
||||
return (
|
||||
<ObjectInfo
|
||||
loading={loading}
|
||||
indicator={<LoadingOutlined />}
|
||||
isEditing={isEditing}
|
||||
type='documentTemplate'
|
||||
objectData={objectData}
|
||||
visibleProperties={{
|
||||
content: false,
|
||||
testObject: false
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
</EditObjectForm>
|
||||
</InfoCollapse>
|
||||
</ActionHandler>
|
||||
|
||||
<InfoCollapse
|
||||
title='Notes'
|
||||
icon={<NoteIcon />}
|
||||
active={collapseState.notes}
|
||||
onToggle={(expanded) => updateCollapseState('notes', expanded)}
|
||||
collapseKey='notes'
|
||||
>
|
||||
<Card>
|
||||
<NotesPanel _id={documentTemplateId} type='documentTemplate' />
|
||||
</Card>
|
||||
</InfoCollapse>
|
||||
|
||||
<InfoCollapse
|
||||
title='Audit Logs'
|
||||
icon={<AuditLogIcon />}
|
||||
active={collapseState.auditLogs}
|
||||
onToggle={(expanded) =>
|
||||
updateCollapseState('auditLogs', expanded)
|
||||
}
|
||||
collapseKey='auditLogs'
|
||||
>
|
||||
{editFormState.loading ? (
|
||||
<InfoCollapsePlaceholder />
|
||||
) : (
|
||||
<ObjectTable
|
||||
type='auditLog'
|
||||
masterFilter={{ 'parent._id': documentTemplateId }}
|
||||
visibleColumns={{ _id: false, 'parent._id': false }}
|
||||
/>
|
||||
)}
|
||||
</InfoCollapse>
|
||||
</Flex>
|
||||
</div>
|
||||
</Flex>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default DocumentTemplateInfo
|
||||
@ -0,0 +1,121 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { useState } from 'react'
|
||||
import { useMediaQuery } from 'react-responsive'
|
||||
import { Typography, Flex, Steps, Divider } from 'antd'
|
||||
|
||||
import ObjectInfo from '../../common/ObjectInfo'
|
||||
import NewObjectForm from '../../common/NewObjectForm'
|
||||
import NewObjectButtons from '../../common/NewObjectButtons'
|
||||
|
||||
const { Title } = Typography
|
||||
|
||||
const NewDocumentTemplate = ({ onOk }) => {
|
||||
const [currentStep, setCurrentStep] = useState(0)
|
||||
|
||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
||||
|
||||
return (
|
||||
<NewObjectForm
|
||||
type={'documentTemplate'}
|
||||
defaultValues={{ active: true, global: false }}
|
||||
>
|
||||
{({ handleSubmit, submitLoading, objectData, formValid }) => {
|
||||
const steps = [
|
||||
{
|
||||
title: 'Required',
|
||||
key: 'required',
|
||||
content: (
|
||||
<ObjectInfo
|
||||
type='documentTemplate'
|
||||
column={1}
|
||||
bordered={false}
|
||||
isEditing={true}
|
||||
required={true}
|
||||
objectData={objectData}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: 'Optional',
|
||||
key: 'optional',
|
||||
content: (
|
||||
<ObjectInfo
|
||||
type='documentTemplate'
|
||||
column={1}
|
||||
bordered={false}
|
||||
isEditing={true}
|
||||
required={false}
|
||||
visibleProperties={{ content: false, testObject: false }}
|
||||
objectData={objectData}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: 'Summary',
|
||||
key: 'summary',
|
||||
content: (
|
||||
<ObjectInfo
|
||||
type='documentTemplate'
|
||||
column={1}
|
||||
bordered={false}
|
||||
visibleProperties={{
|
||||
_id: false,
|
||||
createdAt: false,
|
||||
updatedAt: false
|
||||
}}
|
||||
isEditing={false}
|
||||
objectData={objectData}
|
||||
/>
|
||||
)
|
||||
}
|
||||
]
|
||||
return (
|
||||
<Flex gap='middle'>
|
||||
{!isMobile && (
|
||||
<div style={{ minWidth: '160px' }}>
|
||||
<Steps
|
||||
current={currentStep}
|
||||
items={steps}
|
||||
direction='vertical'
|
||||
style={{ width: 'fit-content' }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!isMobile && (
|
||||
<Divider type='vertical' style={{ height: 'unset' }} />
|
||||
)}
|
||||
|
||||
<Flex vertical gap='middle' style={{ flexGrow: 1 }}>
|
||||
<Title level={2} style={{ margin: 0 }}>
|
||||
New Document Template
|
||||
</Title>
|
||||
<div style={{ minHeight: '260px', marginBottom: 8 }}>
|
||||
{steps[currentStep].content}
|
||||
</div>
|
||||
<NewObjectButtons
|
||||
currentStep={currentStep}
|
||||
totalSteps={steps.length}
|
||||
onPrevious={() => setCurrentStep((prev) => prev - 1)}
|
||||
onNext={() => setCurrentStep((prev) => prev + 1)}
|
||||
onSubmit={() => {
|
||||
handleSubmit()
|
||||
onOk()
|
||||
}}
|
||||
formValid={formValid}
|
||||
submitLoading={submitLoading}
|
||||
/>
|
||||
</Flex>
|
||||
</Flex>
|
||||
)
|
||||
}}
|
||||
</NewObjectForm>
|
||||
)
|
||||
}
|
||||
|
||||
NewDocumentTemplate.propTypes = {
|
||||
onOk: PropTypes.func.isRequired,
|
||||
reset: PropTypes.bool
|
||||
}
|
||||
|
||||
export default NewDocumentTemplate
|
||||
211
src/components/Dashboard/common/TemplateEditor.jsx
Normal file
@ -0,0 +1,211 @@
|
||||
import React, { useState, useContext, useEffect, useRef } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Flex, Alert, Card, Spin, Splitter, Button, Modal, Input } from 'antd'
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import PlusIcon from '../../Icons/PlusIcon.jsx'
|
||||
import MinusIcon from '../../Icons/MinusIcon.jsx'
|
||||
import ExclamationOctagonIcon from '../../Icons/ExclamationOctagonIcon.jsx'
|
||||
import CheckCircleIcon from '../../Icons/CheckCircleIcon.jsx'
|
||||
import ObjectProperty from '../common/ObjectProperty.jsx'
|
||||
import { ApiServerContext } from '../context/ApiServerContext.js'
|
||||
import InfoCircleIcon from '../../Icons/InfoCircleIcon.jsx'
|
||||
|
||||
const TemplateEditor = ({
|
||||
objectData,
|
||||
loading,
|
||||
collapseState,
|
||||
isEditing,
|
||||
style
|
||||
}) => {
|
||||
const iframeRef = useRef(null)
|
||||
const { fetchTemplatePreview } = useContext(ApiServerContext)
|
||||
const [testObjectOpen, setTestObjectOpen] = useState(false)
|
||||
const [previewMessage, setPreviewMessage] = useState('No issues found.')
|
||||
const [previewError, setPreviewError] = useState(false)
|
||||
const [previewContent, setPreviewContent] = useState('')
|
||||
const [reloadLoading, setReloadLoading] = useState(false)
|
||||
const [previewScale, setPreviewScale] = useState(1)
|
||||
|
||||
const updatePreviewContent = (html) => {
|
||||
if (iframeRef.current) {
|
||||
// Save current scroll position
|
||||
const scrollY = iframeRef.current.contentWindow.scrollY
|
||||
const scrollX = iframeRef.current.contentWindow.scrollX
|
||||
|
||||
// Update srcDoc
|
||||
setPreviewContent(html)
|
||||
|
||||
// Restore scroll position after iframe loads new content
|
||||
const handleLoad = () => {
|
||||
iframeRef.current.contentWindow.scrollTo(scrollX, scrollY)
|
||||
iframeRef.current.removeEventListener('load', handleLoad)
|
||||
}
|
||||
iframeRef.current.addEventListener('load', handleLoad)
|
||||
}
|
||||
}
|
||||
|
||||
function reloadPreview(content, testObject = {}, scale = 1) {
|
||||
fetchTemplatePreview(
|
||||
objectData._id,
|
||||
content,
|
||||
testObject,
|
||||
scale,
|
||||
(result) => {
|
||||
setReloadLoading(false)
|
||||
if (result?.error) {
|
||||
setPreviewError(true)
|
||||
setPreviewMessage(result.error)
|
||||
} else {
|
||||
setPreviewError(false)
|
||||
updatePreviewContent(result.html)
|
||||
setPreviewMessage('No issues found.')
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// Move useEffect to component level and use state to track objectData changes
|
||||
useEffect(() => {
|
||||
if (objectData) {
|
||||
console.log('PreviewScale', previewScale)
|
||||
reloadPreview(objectData.content, objectData.testObject, previewScale)
|
||||
}
|
||||
}, [objectData, previewScale])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Splitter className={'farmcontrol-splitter'}>
|
||||
{collapseState.preview == true && (
|
||||
<Splitter.Panel style={{ height: '100%' }}>
|
||||
<Spin
|
||||
spinning={loading || reloadLoading}
|
||||
indicator={<LoadingOutlined />}
|
||||
>
|
||||
<Card style={style} styles={{ body: { height: '100%' } }}>
|
||||
<Flex vertical gap={'middle'} style={{ height: '100%' }}>
|
||||
<Flex gap={'small'}>
|
||||
{objectData?.objectType ? (
|
||||
<ObjectProperty
|
||||
objectType={objectData?.objectType}
|
||||
name={'testObject'}
|
||||
isEditing={true}
|
||||
objectData={objectData}
|
||||
disabled={!isEditing || objectData?.global}
|
||||
type={'object'}
|
||||
/>
|
||||
) : (
|
||||
<div style={{ flexGrow: 1 }}>
|
||||
<Input disabled={true} />
|
||||
</div>
|
||||
)}
|
||||
<Button
|
||||
icon={<InfoCircleIcon />}
|
||||
onClick={() => {
|
||||
setTestObjectOpen(true)
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
icon={<PlusIcon />}
|
||||
onClick={() => {
|
||||
setPreviewScale((prev) => prev + 0.1)
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
icon={<MinusIcon />}
|
||||
onClick={() => {
|
||||
setPreviewScale((prev) => prev - 0.1)
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
|
||||
<iframe
|
||||
ref={iframeRef}
|
||||
srcDoc={previewContent}
|
||||
frameBorder='0'
|
||||
style={{
|
||||
width: '100%',
|
||||
flexGrow: 1,
|
||||
border: '1px solid #85858541',
|
||||
overflow: 'auto'
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</Card>
|
||||
</Spin>
|
||||
</Splitter.Panel>
|
||||
)}
|
||||
{collapseState.editor == true && (
|
||||
<Splitter.Panel>
|
||||
<Spin spinning={loading} indicator={<LoadingOutlined />}>
|
||||
<Card style={style} styles={{ body: { height: '100%' } }}>
|
||||
<Flex vertical gap={'middle'} style={{ height: '100%' }}>
|
||||
<Alert
|
||||
message={previewMessage}
|
||||
showIcon
|
||||
style={{ padding: '4px 8px' }}
|
||||
icon={
|
||||
previewError ? (
|
||||
<ExclamationOctagonIcon />
|
||||
) : (
|
||||
<CheckCircleIcon />
|
||||
)
|
||||
}
|
||||
type={previewError ? 'error' : 'success'}
|
||||
/>
|
||||
|
||||
<div
|
||||
style={{
|
||||
overflowY: 'scroll',
|
||||
height: '100%',
|
||||
flex: '1 1 auto'
|
||||
}}
|
||||
>
|
||||
<ObjectProperty
|
||||
name={'content'}
|
||||
height='100%'
|
||||
type='codeBlock'
|
||||
language={'xml'}
|
||||
objectData={objectData}
|
||||
isEditing={isEditing}
|
||||
/>
|
||||
</div>
|
||||
</Flex>
|
||||
</Card>
|
||||
</Spin>
|
||||
</Splitter.Panel>
|
||||
)}
|
||||
</Splitter>
|
||||
<Modal
|
||||
open={testObjectOpen}
|
||||
closeIcon={null}
|
||||
footer={
|
||||
<Button
|
||||
onClick={() => {
|
||||
setTestObjectOpen(false)
|
||||
}}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<ObjectProperty
|
||||
type={'codeBlock'}
|
||||
name='testObject'
|
||||
language='json'
|
||||
objectData={objectData}
|
||||
isEditing={true}
|
||||
/>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
TemplateEditor.propTypes = {
|
||||
loading: PropTypes.bool,
|
||||
objectData: PropTypes.object,
|
||||
collapseState: PropTypes.object,
|
||||
isEditing: PropTypes.bool,
|
||||
style: PropTypes.object
|
||||
}
|
||||
|
||||
export default TemplateEditor
|
||||
7
src/components/Icons/DesignIcon.jsx
Normal file
@ -0,0 +1,7 @@
|
||||
import React from 'react'
|
||||
import Icon from '@ant-design/icons'
|
||||
import { ReactComponent as CustomIconSvg } from '../../assets/icons/designicon.min.svg'
|
||||
|
||||
const DesignIcon = (props) => <Icon component={CustomIconSvg} {...props} />
|
||||
|
||||
export default DesignIcon
|
||||
7
src/components/Icons/DocumentIcon.jsx
Normal file
@ -0,0 +1,7 @@
|
||||
import React from 'react'
|
||||
import Icon from '@ant-design/icons'
|
||||
import { ReactComponent as CustomIconSvg } from '../../assets/icons/documenticon.min.svg'
|
||||
|
||||
const DocumentIcon = (props) => <Icon component={CustomIconSvg} {...props} />
|
||||
|
||||
export default DocumentIcon
|
||||
9
src/components/Icons/DocumentPrinterIcon.jsx
Normal file
@ -0,0 +1,9 @@
|
||||
import React from 'react'
|
||||
import Icon from '@ant-design/icons'
|
||||
import { ReactComponent as CustomIconSvg } from '../../assets/icons/documentprintericon.min.svg'
|
||||
|
||||
const DocumentPrinterIcon = (props) => (
|
||||
<Icon component={CustomIconSvg} {...props} />
|
||||
)
|
||||
|
||||
export default DocumentPrinterIcon
|
||||
9
src/components/Icons/DocumentSizeIcon.jsx
Normal file
@ -0,0 +1,9 @@
|
||||
import React from 'react'
|
||||
import Icon from '@ant-design/icons'
|
||||
import { ReactComponent as CustomIconSvg } from '../../assets/icons/documentsizeicon.min.svg'
|
||||
|
||||
const DocumentSizeIcon = (props) => (
|
||||
<Icon component={CustomIconSvg} {...props} />
|
||||
)
|
||||
|
||||
export default DocumentSizeIcon
|
||||
9
src/components/Icons/DocumentTemplateIcon.jsx
Normal file
@ -0,0 +1,9 @@
|
||||
import React from 'react'
|
||||
import Icon from '@ant-design/icons'
|
||||
import { ReactComponent as CustomIconSvg } from '../../assets/icons/documenttemplateicon.min.svg'
|
||||
|
||||
const DocumentTemplateIcon = (props) => (
|
||||
<Icon component={CustomIconSvg} {...props} />
|
||||
)
|
||||
|
||||
export default DocumentTemplateIcon
|
||||