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.
This commit is contained in:
Tom Butcher 2025-08-18 00:53:14 +01:00
parent 9fd2b8ffa6
commit c73b6fb33d
27 changed files with 1616 additions and 0 deletions

Binary file not shown.

View 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

View 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

Binary file not shown.

View 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

View 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

Binary file not shown.

View 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

View 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

Binary file not shown.

View 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

View 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

View 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

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View 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

View 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

View 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

View 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

View 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