diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 96b1019306..135888e420 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,7 @@ jobs: ports: - 46380:6379 fedora: - image: fcrepo/fcrepo:5.1.1 + image: fcrepo/fcrepo:5.1.1-multiplatform ports: - 48085:8080 volumes: @@ -38,7 +38,7 @@ jobs: - name: Get Container ID of fedora service id: get_container_id run: | - CONTAINER_ID=$(docker ps --format "{{.ID}}" -f "ancestor=fcrepo/fcrepo:5.1.1") + CONTAINER_ID=$(docker ps --format "{{.ID}}" -f "ancestor=fcrepo/fcrepo:5.1.1-multiplatform") echo "CONTAINER_ID=$CONTAINER_ID" >> $GITHUB_ENV - name: Restart fedora now that the repository has been checked out so config files are available run: docker restart ${{ env.CONTAINER_ID }} @@ -86,11 +86,11 @@ jobs: restore-keys: v1-npm-deps- - run: npm --prefix static/js/vue-cdr-access install - - run: npm --prefix static/js/admin/vue-permissions-editor install + - run: npm --prefix static/js/admin/vue-cdr-admin install - run: npm install -g jest-cli@29.0.3 - run: npm --prefix static/js/vue-cdr-access run test - - run: npm --prefix static/js/admin/vue-permissions-editor run test + - run: npm --prefix static/js/admin/vue-cdr-admin run test - name: Report to CodeClimate uses: paambaati/codeclimate-action@v3.0.0 @@ -103,7 +103,7 @@ jobs: ${{github.workspace}}/**/target/site/jacoco/jacoco.xml:jacoco ${{github.workspace}}/**/target/site/jacoco-it/jacoco.xml:jacoco ${{github.workspace}}/static/js/vue-cdr-access/coverage/lcov.info:lcov - ${{github.workspace}}/static/js/admin/vue-permissions-editor/coverage/lcov.info:lcov + ${{github.workspace}}/static/js/admin/vue-cdr-admin/coverage/lcov.info:lcov - name: View fedora service logs if: always() diff --git a/.gitignore b/.gitignore index 56198fc786..3968dba200 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ static/js/cdr-access.js static/css/cdr_access.css static/css/cdr_vue_modal_styles.css static/js/vue-access-index.js +static/js/vue-admin-index.js static/js/vue-permissions-index.js static/js/vue-cdr-access/.env static/css/cdr-ui.css diff --git a/Makefile b/Makefile index d2e0f8caf6..e062968d2f 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ build-admin-concat: static/css/admin/fontawesome/all.min.css \ static/css/structure_browse.css \ static/css/cdr_vue_modal_styles.css \ - static/js/admin/vue-permissions-editor/dist/assets/index.css \ + static/js/admin/vue-cdr-admin/dist/assets/index.css \ > static/css/cdr_admin.css ifneq ($(VERSION), "") @@ -44,11 +44,11 @@ ifneq ($(VERSION), "") endif build-admin-npm: - # Build vue permissions application files - npm --prefix static/js/admin/vue-permissions-editor ci - npm --prefix static/js/admin/vue-permissions-editor run build + # Build vue admin application files + npm --prefix static/js/admin/vue-cdr-admin ci + npm --prefix static/js/admin/vue-cdr-admin run build - cp static/js/admin/vue-permissions-editor/dist/assets/vue-permissions-index.js static/js/vue-permissions-index.js + cp static/js/admin/vue-cdr-admin/dist/assets/vue-admin-index.js static/js/vue-admin-index.js build-access-concat: # Make sure file is empty diff --git a/auth-api/src/main/java/edu/unc/lib/boxc/auth/api/services/DatastreamPermissionUtil.java b/auth-api/src/main/java/edu/unc/lib/boxc/auth/api/services/DatastreamPermissionUtil.java index bdc5d1aafc..44aa219d96 100644 --- a/auth-api/src/main/java/edu/unc/lib/boxc/auth/api/services/DatastreamPermissionUtil.java +++ b/auth-api/src/main/java/edu/unc/lib/boxc/auth/api/services/DatastreamPermissionUtil.java @@ -31,8 +31,6 @@ public class DatastreamPermissionUtil { DS_PERMISSION_MAP.put(DatastreamType.ORIGINAL_FILE, Permission.viewOriginal); DS_PERMISSION_MAP.put(DatastreamType.TECHNICAL_METADATA, Permission.viewHidden); DS_PERMISSION_MAP.put(DatastreamType.TECHNICAL_METADATA_HISTORY, Permission.viewHidden); - DS_PERMISSION_MAP.put(DatastreamType.THUMBNAIL_SMALL, Permission.viewAccessCopies); - DS_PERMISSION_MAP.put(DatastreamType.THUMBNAIL_LARGE, Permission.viewAccessCopies); } private DatastreamPermissionUtil() { diff --git a/docker-compose.yml b/docker-compose.yml index c54da4f291..06ea2ba4e4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.7' services: fedora: - image: fcrepo/fcrepo:5.1.1 + image: fcrepo/fcrepo:5.1.1-multiplatform ports: - "48085:8080" volumes: @@ -27,8 +27,8 @@ services: ports: - "48983:8983" volumes: - - ./etc/solr-config:/solr_config/config + - ./etc/solr-config:/var/solr/data/access/conf command: - solr-precreate - access - - /solr_config/config \ No newline at end of file + - /var/solr/data/access/conf \ No newline at end of file diff --git a/etc/solr-config/access/conf/schema.xml b/etc/solr-config/access/conf/schema.xml index db4d4ab8dc..9bb6f9b5b4 100644 --- a/etc/solr-config/access/conf/schema.xml +++ b/etc/solr-config/access/conf/schema.xml @@ -225,7 +225,7 @@ - + diff --git a/indexing-solr/src/main/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilter.java b/indexing-solr/src/main/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilter.java index e2b2772c3c..9b2440d3bf 100644 --- a/indexing-solr/src/main/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilter.java +++ b/indexing-solr/src/main/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilter.java @@ -55,7 +55,7 @@ public class SetDatastreamFilter implements IndexDocumentFilter { private DerivativeService derivativeService; private TechnicalMetadataService technicalMetadataService; private Jp2InfoService jp2InfoService; - private static final List THUMBNAIL_DS_TYPES = Arrays.asList(DatastreamType.THUMBNAIL_SMALL, DatastreamType.THUMBNAIL_LARGE); + // Check for hours, minutes, seconds. Plus a check for optional milliseconds separated from seconds // by a "." or a ":" via a non-capturing block followed by a capture group for the milliseconds. private final Pattern TIMING_REGEX = Pattern.compile("(\\d+):(\\d+):(\\d+)(?:[.:](\\d+))?"); @@ -87,7 +87,7 @@ public void filter(DocumentIndexingPackage dip) throws IndexingException { } if (contentObj instanceof WorkObject) { - addThumbnailDerivatives((WorkObject) contentObj, datastreams); + addThumbnailDerivative((WorkObject) contentObj, datastreams); } // Add in metadata datastreams @@ -288,6 +288,20 @@ private boolean needsExtent(String name, String mimetype) { || mimetype.startsWith("audio")); } + /** + * Used to selectively add the JP2 thumbnail datastream + * + * @param workObject the work object with the thumbnail relation + * @param datastreams work object's datastreams to add thumbnail streams to + */ + private void addThumbnailDerivative(WorkObject workObject, List datastreams) { + FileObject thumbnailObject = workObject.getThumbnailObject(); + + if (thumbnailObject != null) { + addDerivatives(datastreams, thumbnailObject.getPid(), true, List.of(JP2_ACCESS_COPY)); + } + } + private String getFirstChecksum(Resource resc) { Statement prop = resc.getProperty(Premis.hasMessageDigest); if (prop == null) { @@ -334,7 +348,8 @@ private long getFilesize(FileObject fileObject, List datastreams) th } private void addDerivatives(List dsList, PID pid, boolean ownedByOtherObject, List types) { - derivativeService.getDerivatives(pid).forEach(deriv -> { + var derivatives = derivativeService.getDerivatives(pid); + derivatives.forEach(deriv -> { DatastreamType type = deriv.getType(); // only add derivatives of types listed if ((types != null) && !types.contains(type)) { @@ -352,33 +367,6 @@ private void addDerivatives(List dsList, PID pid, boolean ownedByOth }); } - /** - * Used to selectively add only thumbnail datastreams - * - * @param workObject the work object with the thumbnail relation - * @param datastreams work object's datastreams to add thumbnail streams to - */ - private void addThumbnailDerivatives(WorkObject workObject, List datastreams) { - FileObject thumbnailObject = workObject.getThumbnailObject(); - - if (thumbnailObject != null) { - var updatedDatastreams = clearPreviousThumbnailDatastreams(datastreams); - addDerivatives(updatedDatastreams, thumbnailObject.getPid(), true, THUMBNAIL_DS_TYPES); - } - } - - /** - * There may be thumbnail streams from the primary object, so we'll clear those - * before adding the assigned thumbnail datastreams - * - * @param datastreams full list of datastreams to index for the work object - * @return modified list of datastreams without thumbnail datastreams - */ - private List clearPreviousThumbnailDatastreams(List datastreams) { - datastreams.removeIf(ds -> THUMBNAIL_DS_TYPES.contains(DatastreamType.getByIdentifier(ds.getName()))); - return datastreams; - } - private DatastreamImpl createDatastream(DerivativeService.Derivative derivative, String owner, String extent) { DatastreamType type = derivative.getType(); String name = type.getId(); diff --git a/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilterTest.java b/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilterTest.java index 8e84ece0ae..ca99dc58ca 100644 --- a/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilterTest.java +++ b/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/filter/SetDatastreamFilterTest.java @@ -45,15 +45,13 @@ import java.util.stream.Collectors; import static edu.unc.lib.boxc.indexing.solr.test.MockRepositoryObjectHelpers.makeFileObject; +import static edu.unc.lib.boxc.model.api.DatastreamType.AUDIO_ACCESS_COPY; import static edu.unc.lib.boxc.model.api.DatastreamType.JP2_ACCESS_COPY; import static edu.unc.lib.boxc.model.api.DatastreamType.ORIGINAL_FILE; import static edu.unc.lib.boxc.model.api.DatastreamType.TECHNICAL_METADATA; -import static edu.unc.lib.boxc.model.api.DatastreamType.THUMBNAIL_LARGE; -import static edu.unc.lib.boxc.model.api.DatastreamType.THUMBNAIL_SMALL; import static edu.unc.lib.boxc.model.fcrepo.ids.DatastreamPids.getOriginalFilePid; import static org.apache.jena.rdf.model.ResourceFactory.createResource; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -83,11 +81,8 @@ public class SetDatastreamFilterTest { private static final String FILE2_DIGEST = "urn:sha1:afbf62faf8a82d00969e0d4d965d62a45bb8c69b"; private static final long FILE2_SIZE = 7231l; - private static final String FILE3_MIMETYPE = "image/png"; - private static final String FILE3_NAME = "image.png"; - private static final String FILE3_DIGEST = "urn:sha1:280f5922b6487c39d6d01a5a8e93bfa07b8f1740"; - private static final long FILE3_SIZE = 17136l; - private static final String FILE3_EXTENT = "375x250"; + private static final String PNG_MIMETYPE = "image/png"; + private static final String IMAGE_EXTENT = "375x250"; private static final String FILE_MP3_MIMETYPE = "audio/mpeg"; private static final String FILE_MP3_NAME = "audio.mp3"; @@ -123,6 +118,9 @@ public class SetDatastreamFilterTest { private static final String PREMIS_DIGEST = "urn:sha1:da39a3ee5e6b4b0d3255bfef95601890afd80709"; private static final long PREMIS_SIZE = 893l; + private static final long JP2_SIZE = 11; + private static final long AUDIO_SIZE = 11; + private AutoCloseable closeable; @TempDir @@ -201,12 +199,7 @@ public void fileObjectMultipleBinariesTest() throws Exception { fileResource(TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST)); when(binObj2.getBinaryStream()).thenReturn(getClass().getResourceAsStream("/datastream/techmd.xml")); - BinaryObject binObj3 = mock(BinaryObject.class); - when(binObj3.getPid()).thenReturn(PIDs.get(pid.getId() + "/" + THUMBNAIL_LARGE.getId())); - when(binObj3.getResource()).thenReturn( - fileResource(THUMBNAIL_LARGE.getId(), FILE3_SIZE, FILE3_MIMETYPE, FILE3_NAME, FILE3_DIGEST)); - - when(fileObj.getBinaryObjects()).thenReturn(Arrays.asList(binObj, binObj2, binObj3)); + when(fileObj.getBinaryObjects()).thenReturn(Arrays.asList(binObj, binObj2)); dip.setContentObject(fileObj); filter.filter(dip); @@ -215,17 +208,15 @@ public void fileObjectMultipleBinariesTest() throws Exception { FILE_SIZE, FILE_MIMETYPE, FILE_NAME, FILE_DIGEST, null, null); assertContainsDatastream(idb.getDatastream(), TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST, null, null); - assertContainsDatastream(idb.getDatastream(), THUMBNAIL_LARGE.getId(), - FILE3_SIZE, FILE3_MIMETYPE, FILE3_NAME, FILE3_DIGEST, null, null); assertEquals(FILE_SIZE, (long) idb.getFilesizeSort()); - assertEquals(FILE_SIZE + FILE2_SIZE + FILE3_SIZE, (long) idb.getFilesizeTotal()); + assertEquals(FILE_SIZE + FILE2_SIZE, (long) idb.getFilesizeTotal()); } @Test public void fileObjectImageBinaryTest() throws Exception { when(binObj.getResource()).thenReturn( - fileResource(ORIGINAL_FILE.getId(), FILE_SIZE, FILE3_MIMETYPE, "test.png", FILE_DIGEST)); + fileResource(ORIGINAL_FILE.getId(), FILE_SIZE, PNG_MIMETYPE, "test.png", FILE_DIGEST)); BinaryObject binObj2 = mock(BinaryObject.class); when(binObj2.getPid()).thenReturn(DatastreamPids.getTechnicalMetadataPid(pid)); @@ -233,32 +224,26 @@ public void fileObjectImageBinaryTest() throws Exception { fileResource(TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST)); when(binObj2.getBinaryStream()).thenReturn(getClass().getResourceAsStream("/datastream/techmd.xml")); - BinaryObject binObj3 = mock(BinaryObject.class); - when(binObj3.getPid()).thenReturn(PIDs.get(pid.getId() + "/" + JP2_ACCESS_COPY.getId())); - when(binObj3.getResource()).thenReturn( - fileResource(THUMBNAIL_LARGE.getId(), FILE3_SIZE, JP2_ACCESS_COPY.getMimetype(), - JP2_ACCESS_COPY.getDefaultFilename(), FILE3_DIGEST)); + List derivs = makeJP2Derivative(); + var pid = PIDs.get(PID_STRING); + when(derivativeService.getDerivatives(pid)).thenReturn(derivs); - BinaryObject binObj4 = mock(BinaryObject.class); - when(binObj4.getPid()).thenReturn(PIDs.get(pid.getId() + "/" + THUMBNAIL_LARGE.getId())); - when(binObj4.getResource()).thenReturn( - fileResource(THUMBNAIL_LARGE.getId(), FILE3_SIZE, FILE3_MIMETYPE, FILE3_NAME, FILE3_DIGEST)); - when(fileObj.getBinaryObjects()).thenReturn(Arrays.asList(binObj, binObj2, binObj3, binObj4)); + when(fileObj.getBinaryObjects()).thenReturn(Arrays.asList(binObj, binObj2)); dip.setContentObject(fileObj); filter.filter(dip); assertContainsDatastream(idb.getDatastream(), ORIGINAL_FILE.getId(), - FILE_SIZE, FILE3_MIMETYPE, "test.png", FILE_DIGEST, null, FILE3_EXTENT); + FILE_SIZE, PNG_MIMETYPE, "test.png", FILE_DIGEST, null, IMAGE_EXTENT); assertContainsDatastream(idb.getDatastream(), TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST, null, null); - assertContainsDatastream(idb.getDatastream(), THUMBNAIL_LARGE.getId(), - FILE3_SIZE, FILE3_MIMETYPE, FILE3_NAME, FILE3_DIGEST, null, null); + assertContainsDatastream(idb.getDatastream(), JP2_ACCESS_COPY.getId(), + JP2_SIZE, JP2_ACCESS_COPY.getMimetype(), "access.jp2", null, null, null); assertEquals(FILE_SIZE, (long) idb.getFilesizeSort()); // JP2 and thumbnail set to same size - assertEquals(FILE_SIZE + FILE2_SIZE + (FILE3_SIZE * 2), (long) idb.getFilesizeTotal()); + assertEquals(FILE_SIZE + FILE2_SIZE + JP2_SIZE, (long) idb.getFilesizeTotal()); } @Test @@ -272,6 +257,8 @@ public void fileObjectAudioOnlyBinaryTest() throws Exception { fileResource(TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST)); when(binObj2.getBinaryStream()).thenReturn(getClass().getResourceAsStream("/datastream/techmd_mp3.xml")); when(fileObj.getBinaryObjects()).thenReturn(Arrays.asList(binObj, binObj2)); + List derivs = makeAudioDerivative(); + when(derivativeService.getDerivatives(pid)).thenReturn(derivs); dip.setContentObject(fileObj); filter.filter(dip); @@ -280,6 +267,8 @@ public void fileObjectAudioOnlyBinaryTest() throws Exception { FILE_MP3_SIZE, FILE_MP3_MIMETYPE, FILE_MP3_NAME, FILE_MP3_DIGEST, null, FILE_MP3_EXTENT); assertContainsDatastream(idb.getDatastream(), TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST, null, null); + assertContainsDatastream(idb.getDatastream(), AUDIO_ACCESS_COPY.getId(), + AUDIO_SIZE, AUDIO_ACCESS_COPY.getMimetype(), "access.m4a", null, null, null); } @Test @@ -314,6 +303,8 @@ public void fileObjectAudioOnlyBinaryWithDotMillisecondsSeperatorTest() throws E fileResource(TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST)); when(binObj2.getBinaryStream()).thenReturn(getClass().getResourceAsStream("/datastream/techmd_dot_separated_milliseconds.xml")); when(fileObj.getBinaryObjects()).thenReturn(Arrays.asList(binObj, binObj2)); + List derivs = makeAudioDerivative(); + when(derivativeService.getDerivatives(pid)).thenReturn(derivs); dip.setContentObject(fileObj); filter.filter(dip); @@ -322,6 +313,8 @@ public void fileObjectAudioOnlyBinaryWithDotMillisecondsSeperatorTest() throws E FILE_MP3_SIZE, FILE_MP3_MIMETYPE, FILE_MP3_NAME, FILE_MP3_DIGEST, null, FILE_MP3_EXTENT); assertContainsDatastream(idb.getDatastream(), TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST, null, null); + assertContainsDatastream(idb.getDatastream(), AUDIO_ACCESS_COPY.getId(), + AUDIO_SIZE, AUDIO_ACCESS_COPY.getMimetype(), "access.m4a", null, null, null); } @Test @@ -465,7 +458,7 @@ public void fileObjectVideoNoHeightWidthBinaryTest() throws Exception { @Test public void fileObjectImageBinaryNoDimensionsTest() throws Exception { when(binObj.getResource()).thenReturn( - fileResource(ORIGINAL_FILE.getId(), FILE_SIZE, FILE3_MIMETYPE, "test.png", FILE_DIGEST)); + fileResource(ORIGINAL_FILE.getId(), FILE_SIZE, PNG_MIMETYPE, "test.png", FILE_DIGEST)); BinaryObject binObj2 = mock(BinaryObject.class); when(binObj2.getPid()).thenReturn(DatastreamPids.getTechnicalMetadataPid(pid)); @@ -479,7 +472,7 @@ public void fileObjectImageBinaryNoDimensionsTest() throws Exception { filter.filter(dip); assertContainsDatastream(idb.getDatastream(), ORIGINAL_FILE.getId(), - FILE_SIZE, FILE3_MIMETYPE, "test.png", FILE_DIGEST, null, null); + FILE_SIZE, PNG_MIMETYPE, "test.png", FILE_DIGEST, null, null); assertContainsDatastream(idb.getDatastream(), TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST, null, null); @@ -491,7 +484,7 @@ public void fileObjectImageBinaryNoDimensionsTest() throws Exception { @Test public void fileObjectImageBinaryWithJp2DimensionsTest() throws Exception { when(binObj.getResource()).thenReturn( - fileResource(ORIGINAL_FILE.getId(), FILE_SIZE, FILE3_MIMETYPE, "test.png", FILE_DIGEST)); + fileResource(ORIGINAL_FILE.getId(), FILE_SIZE, PNG_MIMETYPE, "test.png", FILE_DIGEST)); BinaryObject binObj2 = mock(BinaryObject.class); when(binObj2.getPid()).thenReturn(DatastreamPids.getTechnicalMetadataPid(pid)); @@ -504,18 +497,7 @@ public void fileObjectImageBinaryWithJp2DimensionsTest() throws Exception { when(fileObj.getBinaryObjects()).thenReturn(Arrays.asList(binObj, binObj2)); dip.setContentObject(fileObj); - File smallFile = derivDir.resolve("small.png").toFile(); - FileUtils.write(smallFile, "content", "UTF-8"); - - File largeFile = derivDir.resolve("large.png").toFile(); - FileUtils.write(largeFile, "large content", "UTF-8"); - - File jp2File = derivDir.resolve("access.jp2").toFile(); - FileUtils.write(jp2File, "jp2 content", "UTF-8"); - - List derivs = Arrays.asList(new Derivative(THUMBNAIL_SMALL, smallFile), - new Derivative(THUMBNAIL_LARGE, largeFile), - new Derivative(JP2_ACCESS_COPY, jp2File)); + List derivs = makeJP2Derivative(); when(derivativeService.getDerivatives(filePid)).thenReturn(derivs); var mockJp2InfoService = mock(Jp2InfoService.class); @@ -525,11 +507,11 @@ public void fileObjectImageBinaryWithJp2DimensionsTest() throws Exception { filter.filter(dip); assertContainsDatastream(idb.getDatastream(), ORIGINAL_FILE.getId(), - FILE_SIZE, FILE3_MIMETYPE, "test.png", FILE_DIGEST, null, FILE3_EXTENT); + FILE_SIZE, PNG_MIMETYPE, "test.png", FILE_DIGEST, null, IMAGE_EXTENT); assertContainsDatastream(idb.getDatastream(), TECHNICAL_METADATA.getId(), FILE2_SIZE, FILE2_MIMETYPE, FILE2_NAME, FILE2_DIGEST, null, null); assertContainsDatastream(idb.getDatastream(), JP2_ACCESS_COPY.getId(), - 11, JP2_ACCESS_COPY.getMimetype(), "access.jp2", null, null, "1000x600"); + JP2_SIZE, JP2_ACCESS_COPY.getMimetype(), "access.jp2", null, null, "1000x600"); assertEquals(FILE_SIZE, (long) idb.getFilesizeSort()); } @@ -604,7 +586,7 @@ public void workObjectTest() throws Exception { } @Test - public void workObjectWithoutPrimaryObjectTest() throws Exception { + public void workObjectWithoutPrimaryObjectTest() { WorkObject workObj = mock(WorkObject.class); dip.setContentObject(workObj); @@ -625,7 +607,8 @@ public void workObjectWithThumbnailNoPrimaryObjectTest() throws Exception { PID filePid = PIDs.get(fileId); when(fileObj.getPid()).thenReturn(filePid); when(binObj.getPid()).thenReturn(getOriginalFilePid(filePid)); - setUpDerivatives(filePid); + var derivs = makeJP2Derivative(); + when(derivativeService.getDerivatives(filePid)).thenReturn(derivs); dip.setContentObject(workObj); filter.filter(dip); @@ -633,7 +616,9 @@ public void workObjectWithThumbnailNoPrimaryObjectTest() throws Exception { assertNotNull(idb.getDatastream()); assertNull(idb.getFilesizeSort()); assertNotNull(idb.getFilesizeTotal()); - assertThumbnailDatastreams(fileId); + + assertContainsDatastream(idb.getDatastream(), JP2_ACCESS_COPY.getId(), + JP2_SIZE, JP2_ACCESS_COPY.getMimetype(), "access.jp2", null, fileId, null); } @Test @@ -649,7 +634,6 @@ public void workObjectTestWithPrimaryAndThumbnailObjects() throws Exception { PID filePid = PIDs.get(fileId); when(fileObj.getPid()).thenReturn(filePid); when(binObj.getPid()).thenReturn(getOriginalFilePid(filePid)); - setUpDerivatives(filePid); // set up thumbnail file object FileObject thumbnailObj = mock(FileObject.class); @@ -657,13 +641,13 @@ public void workObjectTestWithPrimaryAndThumbnailObjects() throws Exception { String thumbnailId = "066ed112-f548-479e-ab4b-bf1aad40d678"; PID thumbnailPid = PIDs.get(thumbnailId); when(thumbnailObj.getPid()).thenReturn(thumbnailPid); - setUpDerivatives(thumbnailPid); + var derivs = makeJP2Derivative(); + when(derivativeService.getDerivatives(thumbnailPid)).thenReturn(derivs); filter.filter(dip); assertContainsDatastream(idb.getDatastream(), ORIGINAL_FILE.getId(), FILE_SIZE, FILE_MIMETYPE, FILE_NAME, FILE_DIGEST, fileId, null); - assertThumbnailDatastreams(thumbnailId); assertContainsMetadataDatastreams(idb.getDatastream()); // Sort size is based off primary object's size @@ -671,10 +655,8 @@ public void workObjectTestWithPrimaryAndThumbnailObjects() throws Exception { // Work has no datastreams of its own assertEquals(FILE2_SIZE + MODS_SIZE + PREMIS_SIZE, (long) idb.getFilesizeTotal()); - assertDoesNotContainDatastream(idb.getDatastream(), THUMBNAIL_SMALL.getId(), - 7l, THUMBNAIL_SMALL.getMimetype(), "small.png", null, fileId, null); - assertDoesNotContainDatastream(idb.getDatastream(), THUMBNAIL_LARGE.getId(), - 13l, THUMBNAIL_LARGE.getMimetype(), "large.png", null, fileId, null); + assertContainsDatastream(idb.getDatastream(), JP2_ACCESS_COPY.getId(), + JP2_SIZE, JP2_ACCESS_COPY.getMimetype(), "access.jp2", null, thumbnailId, null); } @Test @@ -691,28 +673,40 @@ public void folderObjectWithMetadataTest() throws Exception { assertEquals(FILE2_SIZE + MODS_SIZE + PREMIS_SIZE, (long) idb.getFilesizeTotal()); } + @Test + public void folderObjectWithJP2Test() throws Exception { + FolderObject folderObj = mock(FolderObject.class); + when(folderObj.getPid()).thenReturn(pid); + + List derivs = makeJP2Derivative(); + when(derivativeService.getDerivatives(pid)).thenReturn(derivs); + + dip.setContentObject(folderObj); + + filter.filter(dip); + + assertContainsDatastream(idb.getDatastream(), JP2_ACCESS_COPY.getId(), + JP2_SIZE, JP2_ACCESS_COPY.getMimetype(), "access.jp2", null, null, null); + } + @Test public void fileObjectWithDerivativeTest() throws Exception { when(fileObj.getPid()).thenReturn(pid); - when(fileObj.getBinaryObjects()).thenReturn(Arrays.asList(binObj)); + when(fileObj.getBinaryObjects()).thenReturn(List.of(binObj)); dip.setContentObject(fileObj); - File derivFile = derivDir.resolve("deriv.png").toFile(); - FileUtils.write(derivFile, "content", "UTF-8"); - long derivSize = 7l; - - List derivs = Arrays.asList(new Derivative(THUMBNAIL_SMALL, derivFile)); + List derivs = makeJP2Derivative(); when(derivativeService.getDerivatives(pid)).thenReturn(derivs); filter.filter(dip); assertContainsDatastream(idb.getDatastream(), ORIGINAL_FILE.getId(), FILE_SIZE, FILE_MIMETYPE, FILE_NAME, FILE_DIGEST, null, null); - assertContainsDatastream(idb.getDatastream(), THUMBNAIL_SMALL.getId(), - derivSize, THUMBNAIL_SMALL.getMimetype(), derivFile.getName(), null, null, null); + assertContainsDatastream(idb.getDatastream(), JP2_ACCESS_COPY.getId(), + JP2_SIZE, JP2_ACCESS_COPY.getMimetype(), "access.jp2", null, null, null); assertEquals(FILE_SIZE, (long) idb.getFilesizeSort()); - assertEquals(FILE_SIZE + derivSize, (long) idb.getFilesizeTotal()); + assertEquals(FILE_SIZE + JP2_SIZE, (long) idb.getFilesizeTotal()); } @Test @@ -751,17 +745,6 @@ private void assertContainsDatastream(List values, String name, long fil assertTrue(values.contains(joined), "Did not contain datastream " + name); } - private void assertDoesNotContainDatastream(List values, String name, long filesize, String mimetype, - String filename, String digest, String owner, String extent) { - String extension = filename.substring(filename.lastIndexOf('.') + 1); - List components = Arrays.asList( - name, mimetype, filename, extension, filesize, digest, owner, extent); - String joined = components.stream() - .map(c -> c == null ? "" : c.toString()) - .collect(Collectors.joining("|")); - assertFalse(values.contains(joined), "Contains datastream " + name); - } - private void addMetadataDatastreams(ContentObject obj) throws Exception { BinaryObject fitsBin = mock(BinaryObject.class); when(fitsBin.getPid()).thenReturn(DatastreamPids.getTechnicalMetadataPid(pid)); @@ -789,22 +772,17 @@ private void assertContainsMetadataDatastreams(List values) { PREMIS_SIZE, PREMIS_MIMETYPE, PREMIS_NAME, PREMIS_DIGEST, null, null); } - private void setUpDerivatives(PID filePid) throws IOException { - File smallFile = derivDir.resolve("small.png").toFile(); - FileUtils.write(smallFile, "content", "UTF-8"); - - File largeFile = derivDir.resolve("large.png").toFile(); - FileUtils.write(largeFile, "large content", "UTF-8"); + private List makeJP2Derivative() throws IOException { + File jp2File = derivDir.resolve("access.jp2").toFile(); + FileUtils.write(jp2File, "jp2 content", "UTF-8"); - List derivs = Arrays.asList(new Derivative(THUMBNAIL_SMALL, smallFile), - new Derivative(THUMBNAIL_LARGE, largeFile)); - when(derivativeService.getDerivatives(filePid)).thenReturn(derivs); + return List.of(new Derivative(JP2_ACCESS_COPY, jp2File)); } - private void assertThumbnailDatastreams(String thumbnailId) { - assertContainsDatastream(idb.getDatastream(), THUMBNAIL_SMALL.getId(), - 7l, THUMBNAIL_SMALL.getMimetype(), "small.png", null, thumbnailId, null); - assertContainsDatastream(idb.getDatastream(), THUMBNAIL_LARGE.getId(), - 13l, THUMBNAIL_LARGE.getMimetype(), "large.png", null, thumbnailId, null); + private List makeAudioDerivative() throws IOException { + File m4aFile = derivDir.resolve("access.m4a").toFile(); + FileUtils.write(m4aFile, "m4a content", "UTF-8"); + + return List.of(new Derivative(AUDIO_ACCESS_COPY, m4aFile)); } } diff --git a/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/test/TestCorpus.java b/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/test/TestCorpus.java index 91a7a099c9..a82ec3e103 100644 --- a/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/test/TestCorpus.java +++ b/indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/test/TestCorpus.java @@ -78,6 +78,9 @@ public List populate() { newDoc.addField("ancestorIds", makeAncestorIds(pid1, pid2)); newDoc.addField("ancestorPath", makeAncestorPath(pid1)); newDoc.addField("resourceType", "Collection"); + List collectionDatastream = List.of( + DatastreamType.JP2_ACCESS_COPY.getId() + "|image/jp2|bunny.jp2|jp2|||" + pid2.getId() + "|1200x1200"); + newDoc.addField(SearchFieldKey.DATASTREAM.getSolrField(), collectionDatastream); docs.add(newDoc); newDoc = new SolrInputDocument(); @@ -115,8 +118,8 @@ public List populate() { newDoc.addField("ancestorPath", makeAncestorPath(pid1, pid2, pid6)); newDoc.addField("resourceType", ResourceType.File.name()); List imgDatastreams = Arrays.asList( - ORIGINAL_FILE.getId() + "|image/png|file.png|png|766|urn:sha1:checksum|1200x1200", - DatastreamType.JP2_ACCESS_COPY.getId() + "|image/jp2|bunny.jp2|jp2|||1200x1200"); + ORIGINAL_FILE.getId() + "|image/png|file.png|png|766|urn:sha1:checksum||1200x1200", + DatastreamType.JP2_ACCESS_COPY.getId() + "|image/jp2|bunny.jp2|jp2|||" + pid6File.getId() + "|1200x1200"); newDoc.addField(SearchFieldKey.DATASTREAM.getSolrField(), imgDatastreams); newDoc.addField(SearchFieldKey.FILE_FORMAT_CATEGORY.getSolrField(), ContentCategory.image.getDisplayName()); newDoc.addField(SearchFieldKey.FILE_FORMAT_TYPE.getSolrField(), "png"); diff --git a/integration/src/test/java/edu/unc/lib/boxc/integration/factories/ContentObjectFactory.java b/integration/src/test/java/edu/unc/lib/boxc/integration/factories/ContentObjectFactory.java index 8ee8e90108..4ce2fb2d07 100644 --- a/integration/src/test/java/edu/unc/lib/boxc/integration/factories/ContentObjectFactory.java +++ b/integration/src/test/java/edu/unc/lib/boxc/integration/factories/ContentObjectFactory.java @@ -62,7 +62,7 @@ public Map validateOptions(Map options) { } protected void addThumbnail(ContentObject object) throws IOException { - var derivativePath = derivativeService.getDerivativePath(object.getPid(), DatastreamType.THUMBNAIL_LARGE); + var derivativePath = derivativeService.getDerivativePath(object.getPid(), DatastreamType.JP2_ACCESS_COPY); FileUtils.write(derivativePath.toFile(), "image", "UTF-8"); } diff --git a/it_config/allowed_external_paths.txt b/it_config/allowed_external_paths.txt index c3cad514a5..13697b76ee 100644 --- a/it_config/allowed_external_paths.txt +++ b/it_config/allowed_external_paths.txt @@ -1 +1 @@ -file:/tmp/boxc_test_storage/ \ No newline at end of file +file:/tmp/boxc_test_storage/ diff --git a/model-api/src/main/java/edu/unc/lib/boxc/model/api/DatastreamType.java b/model-api/src/main/java/edu/unc/lib/boxc/model/api/DatastreamType.java index 93cc0195b9..d7088b81b3 100644 --- a/model-api/src/main/java/edu/unc/lib/boxc/model/api/DatastreamType.java +++ b/model-api/src/main/java/edu/unc/lib/boxc/model/api/DatastreamType.java @@ -21,9 +21,7 @@ public enum DatastreamType { MD_EVENTS("event_log", "application/n-triples", "nt", METADATA_CONTAINER, INTERNAL), ORIGINAL_FILE("original_file", null, null, DATA_FILE_FILESET, INTERNAL), TECHNICAL_METADATA("techmd_fits", "text/xml", "xml", DATA_FILE_FILESET, INTERNAL), - TECHNICAL_METADATA_HISTORY("techmd_fits_history", "text/xml", "xml", DATA_FILE_FILESET, INTERNAL), - THUMBNAIL_SMALL("thumbnail_small", "image/png", "png", null, EXTERNAL), - THUMBNAIL_LARGE("thumbnail_large", "image/png", "png", null, EXTERNAL); + TECHNICAL_METADATA_HISTORY("techmd_fits_history", "text/xml", "xml", DATA_FILE_FILESET, INTERNAL); private final String id; private final String mimetype; diff --git a/model-fcrepo/src/test/java/edu/unc/lib/boxc/model/fcrepo/services/DerivativeServiceTest.java b/model-fcrepo/src/test/java/edu/unc/lib/boxc/model/fcrepo/services/DerivativeServiceTest.java index 75672ef760..eede5b690a 100644 --- a/model-fcrepo/src/test/java/edu/unc/lib/boxc/model/fcrepo/services/DerivativeServiceTest.java +++ b/model-fcrepo/src/test/java/edu/unc/lib/boxc/model/fcrepo/services/DerivativeServiceTest.java @@ -1,27 +1,26 @@ package edu.unc.lib.boxc.model.fcrepo.services; -import static edu.unc.lib.boxc.model.api.DatastreamType.JP2_ACCESS_COPY; -import static edu.unc.lib.boxc.model.api.DatastreamType.ORIGINAL_FILE; -import static edu.unc.lib.boxc.model.api.DatastreamType.THUMBNAIL_SMALL; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; +import edu.unc.lib.boxc.model.api.DatastreamType; +import edu.unc.lib.boxc.model.api.ids.PID; +import edu.unc.lib.boxc.model.fcrepo.ids.PIDs; +import edu.unc.lib.boxc.model.fcrepo.services.DerivativeService.Derivative; +import org.apache.commons.io.FileUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; -import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; - -import edu.unc.lib.boxc.model.api.DatastreamType; -import edu.unc.lib.boxc.model.api.ids.PID; -import edu.unc.lib.boxc.model.fcrepo.ids.PIDs; -import edu.unc.lib.boxc.model.fcrepo.services.DerivativeService; -import edu.unc.lib.boxc.model.fcrepo.services.DerivativeService.Derivative; +import static edu.unc.lib.boxc.model.api.DatastreamType.AUDIO_ACCESS_COPY; +import static edu.unc.lib.boxc.model.api.DatastreamType.FULLTEXT_EXTRACTION; +import static edu.unc.lib.boxc.model.api.DatastreamType.JP2_ACCESS_COPY; +import static edu.unc.lib.boxc.model.api.DatastreamType.ORIGINAL_FILE; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; /** * @@ -56,48 +55,52 @@ public void init() throws Exception { @Test public void testGetDerivative() throws Exception { - File originalDerivFile = createDerivative(pid, THUMBNAIL_SMALL); + File originalDerivFile = createDerivative(pid, JP2_ACCESS_COPY); - Derivative deriv = derivativeService.getDerivative(pid, THUMBNAIL_SMALL); + Derivative deriv = derivativeService.getDerivative(pid, JP2_ACCESS_COPY); assertEquals(originalDerivFile, deriv.getFile()); - assertEquals(THUMBNAIL_SMALL, deriv.getType()); + assertEquals(JP2_ACCESS_COPY, deriv.getType()); } @Test public void testGetDerivativeNotExist() throws Exception { - Derivative deriv = derivativeService.getDerivative(pid, THUMBNAIL_SMALL); + Derivative deriv = derivativeService.getDerivative(pid, JP2_ACCESS_COPY); assertNull(deriv); } @Test public void testGetDerivatives() throws Exception { - File originalDerivFile1 = createDerivative(pid, THUMBNAIL_SMALL); + File originalDerivFile1 = createDerivative(pid, FULLTEXT_EXTRACTION); File originalDerivFil21 = createDerivative(pid, JP2_ACCESS_COPY); + File originalDerivFile3 = createDerivative(pid, AUDIO_ACCESS_COPY); List derivs = derivativeService.getDerivatives(pid); - assertEquals(2, derivs.size()); + assertEquals(3, derivs.size()); - Derivative thumbDeriv = findDerivative(derivs, THUMBNAIL_SMALL); + Derivative textDeriv = findDerivative(derivs, FULLTEXT_EXTRACTION); Derivative jp2Deriv = findDerivative(derivs, JP2_ACCESS_COPY); + Derivative audioDeriv = findDerivative(derivs, AUDIO_ACCESS_COPY); - assertNotNull(thumbDeriv); + assertNotNull(textDeriv); assertNotNull(jp2Deriv); + assertNotNull(audioDeriv); - assertEquals(originalDerivFile1, thumbDeriv.getFile()); + assertEquals(originalDerivFile1, textDeriv.getFile()); assertEquals(originalDerivFil21, jp2Deriv.getFile()); + assertEquals(originalDerivFile3, audioDeriv.getFile()); } @Test public void testGetDerivativesIgnoreNonDerivatives() throws Exception { - File originalDerivFile1 = createDerivative(pid, THUMBNAIL_SMALL); + File originalDerivFile1 = createDerivative(pid, JP2_ACCESS_COPY); createDerivative(pid, ORIGINAL_FILE); List derivs = derivativeService.getDerivatives(pid); assertEquals(1, derivs.size()); - Derivative thumbDeriv = findDerivative(derivs, THUMBNAIL_SMALL); + Derivative thumbDeriv = findDerivative(derivs, JP2_ACCESS_COPY); assertEquals(originalDerivFile1, thumbDeriv.getFile()); } diff --git a/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ImportThumbnailRequest.java b/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ImportThumbnailRequest.java new file mode 100644 index 0000000000..ccf35de18d --- /dev/null +++ b/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ImportThumbnailRequest.java @@ -0,0 +1,52 @@ +package edu.unc.lib.boxc.operations.jms.thumbnails; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import edu.unc.lib.boxc.auth.api.models.AgentPrincipals; +import edu.unc.lib.boxc.auth.fcrepo.models.AgentPrincipalsImpl; + +import java.nio.file.Path; + +/** + * Request object for importing an image as thumbnail for a collection, folder, or admin unit + * + * @author snluong + */ +public class ImportThumbnailRequest { + @JsonDeserialize(as = AgentPrincipalsImpl.class) + private AgentPrincipals agent; + private String mimetype; + private Path storagePath; + private String pidString; + + public String getPidString() { + return pidString; + } + + public void setPidString(String pidString) { + this.pidString = pidString; + } + + public AgentPrincipals getAgent() { + return agent; + } + + public void setAgent(AgentPrincipals agent) { + this.agent = agent; + } + + public String getMimetype() { + return mimetype; + } + + public void setMimetype(String mimetype) { + this.mimetype = mimetype; + } + + public Path getStoragePath() { + return storagePath; + } + + public void setStoragePath(Path storagePath) { + this.storagePath = storagePath; + } +} diff --git a/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ImportThumbnailRequestSerializationHelper.java b/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ImportThumbnailRequestSerializationHelper.java new file mode 100644 index 0000000000..a7712a2e5a --- /dev/null +++ b/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ImportThumbnailRequestSerializationHelper.java @@ -0,0 +1,46 @@ +package edu.unc.lib.boxc.operations.jms.thumbnails; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.ObjectWriter; + +import java.io.IOException; + +/** + * Helper methods for serializing and deserializing import thumbnail requests + * + * @author snluong + */ +public class ImportThumbnailRequestSerializationHelper { + private static final ObjectWriter REQUEST_WRITER; + private static final ObjectReader REQUEST_READER; + static { + ObjectMapper mapper = new ObjectMapper(); + REQUEST_WRITER = mapper.writerFor(ImportThumbnailRequest.class); + REQUEST_READER = mapper.readerFor(ImportThumbnailRequest.class); + } + + private ImportThumbnailRequestSerializationHelper() { + } + + /** + * Transform request into a JSON string + * @param request + * @return + * @throws IOException + */ + public static String toJson(ImportThumbnailRequest request) throws IOException { + return REQUEST_WRITER.writeValueAsString(request); + } + + /** + * Transform JSON string to an ImportThumbnailRequest + * @param json + * @return + * @throws IOException + */ + public static ImportThumbnailRequest toRequest(String json) throws IOException { + return REQUEST_READER.readValue(json); + } +} + diff --git a/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSender.java b/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSender.java index 80862ea0fc..43ff7cf568 100644 --- a/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSender.java +++ b/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSender.java @@ -16,6 +16,8 @@ public class ThumbnailRequestSender extends MessageSender { private static final Logger log = LoggerFactory.getLogger(ThumbnailRequestSender.class); private static final ObjectWriter MAPPER = new ObjectMapper().writerFor(ThumbnailRequest.class); + private static final ObjectWriter IMPORT_MAPPER = new ObjectMapper().writerFor(ImportThumbnailRequest.class); + private String importDestinationName; /** * Send a ThumbnailRequest to the configured JMS queue @@ -28,4 +30,30 @@ public void sendToQueue(ThumbnailRequest request) throws IOException { log.info("Job to {} thumbnail has been queued for {} with file {}", request.getAction(), request.getAgent().getUsername(), request.getFilePidString()); } + + /** + * Send an ImportThumbnailRequest to the appropriate JMS queue + * @param request + * @throws IOException + */ + public void sendToImportQueue(ImportThumbnailRequest request) throws IOException { + String messageBody = IMPORT_MAPPER.writeValueAsString(request); + sendImportMessage(messageBody); + log.info("Job to import thumbnail has been queued for {} with object {}", + request.getAgent().getUsername(), request.getPidString()); + } + + public void sendImportMessage(String msgStr) { + jmsTemplate.send(importDestinationName, (session -> { + // Committing the session to flush changes in long-running threads + if (session.getTransacted()) { + session.commit(); + } + return session.createTextMessage(msgStr); + })); + } + + public void setImportDestinationName(String importDestinationName) { + this.importDestinationName = importDestinationName; + } } diff --git a/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/viewSettings/ViewSettingRequest.java b/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/viewSettings/ViewSettingRequest.java index 34ec5cbdf5..77605f10cf 100644 --- a/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/viewSettings/ViewSettingRequest.java +++ b/operations-jms/src/main/java/edu/unc/lib/boxc/operations/jms/viewSettings/ViewSettingRequest.java @@ -6,7 +6,7 @@ import edu.unc.lib.boxc.auth.fcrepo.models.AgentPrincipalsImpl; /** - * Request object for updating the view settings of the UV + * Request object for updating the view settings of Clover * @author sharonluong */ public class ViewSettingRequest { diff --git a/operations-jms/src/test/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSenderTest.java b/operations-jms/src/test/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSenderTest.java index 77aea3793a..93edaa2c6a 100644 --- a/operations-jms/src/test/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSenderTest.java +++ b/operations-jms/src/test/java/edu/unc/lib/boxc/operations/jms/thumbnails/ThumbnailRequestSenderTest.java @@ -8,13 +8,16 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.mockito.Mock; import org.springframework.jms.core.JmsTemplate; import java.io.IOException; +import java.nio.file.Path; import java.util.UUID; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.MockitoAnnotations.openMocks; @@ -24,15 +27,19 @@ public class ThumbnailRequestSenderTest { @Mock private JmsTemplate jmsTemplate; + @TempDir + private Path storagePath; private ThumbnailRequestSender thumbnailRequestSender; private AutoCloseable closeable; private final AgentPrincipals agent = new AgentPrincipalsImpl("user", new AccessGroupSetImpl("agroup")); + private String importQueue = "import.queue"; @BeforeEach public void setup() { closeable = openMocks(this); thumbnailRequestSender = new ThumbnailRequestSender(); thumbnailRequestSender.setJmsTemplate(jmsTemplate); + thumbnailRequestSender.setImportDestinationName(importQueue); } @AfterEach @@ -52,6 +59,19 @@ public void sendToQueueTest() throws IOException { verify(jmsTemplate).send(any()); } + @Test + public void sendToImportQueueTest() throws IOException { + var pidString = makePid().toString(); + var request = new ImportThumbnailRequest(); + request.setAgent(agent); + request.setPidString(pidString); + request.setStoragePath(storagePath); + request.setMimetype("image/jpeg"); + + thumbnailRequestSender.sendToImportQueue(request); + verify(jmsTemplate).send(eq(importQueue), any()); + } + public static PID makePid() { return PIDs.get(UUID.randomUUID().toString()); } diff --git a/pom.xml b/pom.xml index b3da161ff3..c2017d42b0 100644 --- a/pom.xml +++ b/pom.xml @@ -96,7 +96,7 @@ 4.5.13 1.26.0 1.17.1 - 2.7 + 2.17.0 1.6 3.8.1 1.5 @@ -1063,4 +1063,4 @@ - \ No newline at end of file + diff --git a/search-solr/src/main/java/edu/unc/lib/boxc/search/solr/filters/HasValuesFilter.java b/search-solr/src/main/java/edu/unc/lib/boxc/search/solr/filters/HasValuesFilter.java new file mode 100644 index 0000000000..9c2623ad38 --- /dev/null +++ b/search-solr/src/main/java/edu/unc/lib/boxc/search/solr/filters/HasValuesFilter.java @@ -0,0 +1,34 @@ +package edu.unc.lib.boxc.search.solr.filters; + +import edu.unc.lib.boxc.search.api.SearchFieldKey; +import edu.unc.lib.boxc.search.api.filters.QueryFilter; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Filter which restricts results to entries which contain populated values for the given key with + * the specified field search value + * + * @author lfarrell + */ +public class HasValuesFilter implements QueryFilter { + private final SearchFieldKey fieldKey; + private final List fieldValues; + + protected HasValuesFilter(SearchFieldKey fieldKey, List fieldValues) { + this.fieldKey = fieldKey; + this.fieldValues = fieldValues; + } + + @Override + public String toFilterString() { + return fieldValues.stream().map(v -> getFieldKey().getSolrField() + ":" + v) + .collect(Collectors.joining(" OR ")); + } + + @Override + public SearchFieldKey getFieldKey() { + return fieldKey; + } +} diff --git a/search-solr/src/main/java/edu/unc/lib/boxc/search/solr/filters/IIIFv3ViewableFilter.java b/search-solr/src/main/java/edu/unc/lib/boxc/search/solr/filters/IIIFv3ViewableFilter.java index ac163a752a..686e16de47 100644 --- a/search-solr/src/main/java/edu/unc/lib/boxc/search/solr/filters/IIIFv3ViewableFilter.java +++ b/search-solr/src/main/java/edu/unc/lib/boxc/search/solr/filters/IIIFv3ViewableFilter.java @@ -23,7 +23,8 @@ public String toFilterString() { var fileTypeFilter = getFileTypes().stream().map( type -> fileTypeField + ":" + type) .collect(Collectors.joining(" OR ", "(", ")")); var datastreamFilter = SearchFieldKey.DATASTREAM.getSolrField() + ":" + DatastreamType.JP2_ACCESS_COPY.getId() + "|*"; - return "(" + fileTypeFilter + ") OR (" + datastreamFilter + ")"; + var datastreamFilterAudio = SearchFieldKey.DATASTREAM.getSolrField() + ":" + DatastreamType.AUDIO_ACCESS_COPY.getId() + "|*"; + return "(" + fileTypeFilter + ") OR (" + datastreamFilter + ") OR (" + datastreamFilterAudio + ")"; } @Override diff --git a/search-solr/src/main/java/edu/unc/lib/boxc/search/solr/filters/QueryFilterFactory.java b/search-solr/src/main/java/edu/unc/lib/boxc/search/solr/filters/QueryFilterFactory.java index 9eb72f0840..9e43348691 100644 --- a/search-solr/src/main/java/edu/unc/lib/boxc/search/solr/filters/QueryFilterFactory.java +++ b/search-solr/src/main/java/edu/unc/lib/boxc/search/solr/filters/QueryFilterFactory.java @@ -49,4 +49,14 @@ public static QueryFilter createFilter(SearchFieldKey fieldKey) { public static QueryFilter createIIIFv3ViewableFilter(List fileTypes) { return new IIIFv3ViewableFilter(fileTypes); } + + /** + * + * @param fieldKey searchField + * @param fieldValues list of values to search for + * @return new QueryFilter instance with the provided file type + */ + public static QueryFilter createHasValuesFilter(SearchFieldKey fieldKey, List fieldValues) { + return new HasValuesFilter(fieldKey, fieldValues); + } } diff --git a/search-solr/src/test/java/edu/unc/lib/boxc/search/solr/filters/QueryFilterFactoryTest.java b/search-solr/src/test/java/edu/unc/lib/boxc/search/solr/filters/QueryFilterFactoryTest.java index c3d8d1709b..f71714ad97 100644 --- a/search-solr/src/test/java/edu/unc/lib/boxc/search/solr/filters/QueryFilterFactoryTest.java +++ b/search-solr/src/test/java/edu/unc/lib/boxc/search/solr/filters/QueryFilterFactoryTest.java @@ -6,8 +6,9 @@ import org.junit.jupiter.api.Test; import java.util.HashSet; +import java.util.List; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; /** * @author lfarrell @@ -15,22 +16,28 @@ public class QueryFilterFactoryTest { @Test public void NamedDatastreamFilterTest() { - var filter = QueryFilterFactory.createFilter(SearchFieldKey.DATASTREAM, DatastreamType.THUMBNAIL_LARGE); - assertTrue(filter instanceof NamedDatastreamFilter); + var filter = QueryFilterFactory.createFilter(SearchFieldKey.DATASTREAM, DatastreamType.JP2_ACCESS_COPY); + assertInstanceOf(NamedDatastreamFilter.class, filter); } @Test public void MultipleDirectlyOwnedDatastreamsFilterTest() { var datastreamTypes = new HashSet(); - datastreamTypes.add(DatastreamType.THUMBNAIL_LARGE); - datastreamTypes.add(DatastreamType.THUMBNAIL_SMALL); + datastreamTypes.add(DatastreamType.JP2_ACCESS_COPY); + datastreamTypes.add(DatastreamType.FULLTEXT_EXTRACTION); var filter = QueryFilterFactory.createFilter(SearchFieldKey.DATASTREAM, datastreamTypes); - assertTrue(filter instanceof MultipleDirectlyOwnedDatastreamsFilter); + assertInstanceOf(MultipleDirectlyOwnedDatastreamsFilter.class, filter); } @Test public void HasPopulatedFieldFilterTest() { var filter = QueryFilterFactory.createFilter(SearchFieldKey.STREAMING_TYPE); - assertTrue(filter instanceof HasPopulatedFieldFilter); + assertInstanceOf(HasPopulatedFieldFilter.class, filter); + } + + @Test + public void HasValuesFilterTest() { + var filter = QueryFilterFactory.createHasValuesFilter(SearchFieldKey.FILE_FORMAT_TYPE, List.of("application/pdf")); + assertInstanceOf(HasValuesFilter.class, filter); } } diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/NonBinaryEnhancementProcessor.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/NonBinaryEnhancementProcessor.java deleted file mode 100644 index 255cba281e..0000000000 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/NonBinaryEnhancementProcessor.java +++ /dev/null @@ -1,51 +0,0 @@ -package edu.unc.lib.boxc.services.camel; - -import static edu.unc.lib.boxc.model.api.ids.RepositoryPathConstants.HASHED_PATH_DEPTH; -import static edu.unc.lib.boxc.model.api.ids.RepositoryPathConstants.HASHED_PATH_SIZE; -import static edu.unc.lib.boxc.model.fcrepo.ids.RepositoryPaths.idToPath; -import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryMimeType; -import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryPath; -import static org.fcrepo.camel.FcrepoHeaders.FCREPO_URI; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.apache.camel.Exchange; -import org.apache.camel.Message; -import org.apache.camel.Processor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import edu.unc.lib.boxc.model.fcrepo.ids.PIDs; - -/** - * Processor to add headers to create display thumbnails for non-file objects - * - * @author lfarrell - */ -public class NonBinaryEnhancementProcessor implements Processor { - private static final Logger log = LoggerFactory.getLogger(NonBinaryEnhancementProcessor.class); - - private String sourceImagesDir; - - @Override - public void process(final Exchange exchange) throws Exception { - final Message in = exchange.getIn(); - - String uri = (String) in.getHeader(FCREPO_URI); - String uuid = PIDs.get(uri).getUUID(); - String objBasePath = idToPath(uuid, HASHED_PATH_DEPTH, HASHED_PATH_SIZE); - - Path imgFile = Paths.get(sourceImagesDir, objBasePath, uuid); - - if (Files.isRegularFile(imgFile)) { - in.setHeader(CdrBinaryPath, imgFile.toAbsolutePath().toString()); - in.setHeader(CdrBinaryMimeType, "image/*"); - } - } - - public void setSourceImagesDir(String sourceImagesDir) { - this.sourceImagesDir = sourceImagesDir; - } -} diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouter.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouter.java index 95b29c8548..094eb48f31 100644 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouter.java +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouter.java @@ -1,18 +1,16 @@ package edu.unc.lib.boxc.services.camel.destroyDerivatives; -import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrObjectType; -import static org.slf4j.LoggerFactory.getLogger; - +import edu.unc.lib.boxc.services.camel.fulltext.FulltextProcessor; +import edu.unc.lib.boxc.services.camel.images.ImageDerivativeProcessor; import edu.unc.lib.boxc.services.camel.audio.AudioDerivativeProcessor; + import org.apache.camel.BeanInject; import org.apache.camel.LoggingLevel; import org.apache.camel.PropertyInject; import org.apache.camel.builder.RouteBuilder; import org.slf4j.Logger; -import edu.unc.lib.boxc.model.api.rdf.Cdr; -import edu.unc.lib.boxc.services.camel.fulltext.FulltextProcessor; -import edu.unc.lib.boxc.services.camel.images.ImageDerivativeProcessor; +import static org.slf4j.LoggerFactory.getLogger; /** * Router to process requests to destroy derivatives for an object @@ -26,15 +24,6 @@ public class DestroyDerivativesRouter extends RouteBuilder { @BeanInject(value = "destroyedMsgProcessor") private DestroyedMsgProcessor destroyedMsgProcessor; - @BeanInject(value = "destroyCollectionSrcImgProcessor") - private DestroyDerivativesProcessor destroyCollectionSrcImgProcessor; - - @BeanInject(value = "destroySmallThumbnailProcessor") - private DestroyDerivativesProcessor destroySmallThumbnailProcessor; - - @BeanInject(value = "destroyLargeThumbnailProcessor") - private DestroyDerivativesProcessor destroyLargeThumbnailProcessor; - @BeanInject(value = "destroyAccessCopyProcessor") private DestroyDerivativesProcessor destroyAccessCopyProcessor; @@ -80,28 +69,9 @@ public void configure() throws Exception { from("direct:image.derivatives.destroy") .routeId("CdrDestroyImage") .startupOrder(202) - .log(LoggingLevel.DEBUG, log, "Destroying derivative thumbnails") - .bean(destroySmallThumbnailProcessor) - .bean(destroyLargeThumbnailProcessor) - .choice() - .when(simple("${headers['" + CdrObjectType + "']} == '" + Cdr.FileObject.getURI() + "'")) - .to("direct:image.access.destroy") - .when(simple("${headers['CollectionThumb']} != null")) - .to("direct:image.collection.destroy") - .end(); - - from("direct:image.access.destroy") - .routeId("CdrDestroyAccessCopy") - .startupOrder(201) - .log(LoggingLevel.DEBUG, log, "Destroying access copy") + .log(LoggingLevel.DEBUG, log, "Destroying access copy derivatives") .bean(destroyAccessCopyProcessor); - from("direct:image.collection.destroy") - .routeId("CdrDestroyCollectionUpload") - .startupOrder(200) - .log(LoggingLevel.DEBUG, log, "Destroying collection image upload") - .bean(destroyCollectionSrcImgProcessor); - from("direct:audio.derivatives.destroy") .routeId("CdrDestroyAudio") .startupOrder(199) @@ -113,18 +83,6 @@ public void setDestroyedMsgProcessor(DestroyedMsgProcessor destroyedMsgProcessor this.destroyedMsgProcessor = destroyedMsgProcessor; } - public void setDestroyCollectionSrcImgProcessor(DestroyDerivativesProcessor destroyCollectionSrcImgProcessor) { - this.destroyCollectionSrcImgProcessor = destroyCollectionSrcImgProcessor; - } - - public void setDestroySmallThumbnailProcessor(DestroyDerivativesProcessor destroySmallThumbnailProcessor) { - this.destroySmallThumbnailProcessor = destroySmallThumbnailProcessor; - } - - public void setDestroyLargeThumbnailProcessor(DestroyDerivativesProcessor destroyLargeThumbnailProcessor) { - this.destroyLargeThumbnailProcessor = destroyLargeThumbnailProcessor; - } - public void setDestroyAccessCopyProcessor(DestroyDerivativesProcessor destroyAccessCopyProcessor) { this.destroyAccessCopyProcessor = destroyAccessCopyProcessor; } diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyedMsgProcessor.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyedMsgProcessor.java index 85dd4fa15b..b466bd1391 100644 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyedMsgProcessor.java +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyedMsgProcessor.java @@ -32,12 +32,8 @@ * */ public class DestroyedMsgProcessor implements Processor { - private final String srcBasePath; private static final Logger log = LoggerFactory.getLogger(DestroyedMsgProcessor.class); - - public DestroyedMsgProcessor(String srcBasePath) { - this.srcBasePath = srcBasePath; - } + private String jp2BasePath; @Override public void process(Exchange exchange) throws Exception { @@ -56,14 +52,13 @@ public void process(Exchange exchange) throws Exception { String pidId = content.getChildTextTrim("pidId", JDOMNamespaceUtil.CDR_MESSAGE_NS); String binaryPath = content.getChildTextTrim("contentUri", JDOMNamespaceUtil.CDR_MESSAGE_NS); - if (objType.equals(Cdr.Collection.getURI()) || objType.equals(Cdr.AdminUnit.getURI())) { + if (!objType.equals(Cdr.FileObject.getURI())) { String uuid = PIDs.get(pidId).getId(); String binarySubPath = idToPath(uuid, HASHED_PATH_DEPTH, HASHED_PATH_SIZE); - Path srcPath = Paths.get(srcBasePath, binarySubPath, uuid); + Path jp2Path = Paths.get(jp2BasePath, binarySubPath, uuid + ".jp2"); - if (Files.exists(srcPath)) { - mimeType = "image/*"; - in.setHeader("CollectionThumb", true); + if (Files.exists(jp2Path)) { + mimeType = "image/jp2"; } } @@ -79,4 +74,8 @@ public void process(Exchange exchange) throws Exception { in.setHeader(CdrBinaryPath, binaryPath); in.setHeader(CdrObjectType, objType); } + + public void setJp2BasePath(String jp2BasePath) { + this.jp2BasePath = jp2BasePath; + } } diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouter.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouter.java index 60edf7acb8..c35449159f 100644 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouter.java +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouter.java @@ -17,7 +17,6 @@ import edu.unc.lib.boxc.model.api.rdf.Cdr; import edu.unc.lib.boxc.services.camel.BinaryEnhancementProcessor; import edu.unc.lib.boxc.services.camel.BinaryMetadataProcessor; -import edu.unc.lib.boxc.services.camel.NonBinaryEnhancementProcessor; /** * Router which queues and triggers enhancement services. @@ -35,14 +34,10 @@ public class EnhancementRouter extends RouteBuilder { @BeanInject(value = "binaryMetadataProcessor") private BinaryMetadataProcessor mdProcessor; - @BeanInject(value = "nonBinaryEnhancementProcessor") - private NonBinaryEnhancementProcessor nbProcessor; - @PropertyInject(value = "cdr.enhancement.processingThreads") private Integer enhancementThreads; - private static final String DEFAULT_ENHANCEMENTS = "thumbnails,imageAccessCopy,extractFulltext,audioAccessCopy"; - private static final String THUMBNAIL_ENHANCEMENTS = "thumbnails"; + private static final String DEFAULT_ENHANCEMENTS = "imageAccessCopy,extractFulltext,audioAccessCopy"; @Override public void configure() throws Exception { @@ -68,9 +63,7 @@ public void configure() throws Exception { + " || ${headers[org.fcrepo.jms.resourceType]} contains '" + Cdr.ContentRoot.getURI() + "'" )) .log(DEBUG, log, "Processing enhancements for non-binary ${headers[CamelFcrepoUri]}") - .process(nbProcessor) - .setHeader(CdrEnhancementSet, constant(THUMBNAIL_ENHANCEMENTS)) - .to("{{cdr.enhancement.perform.camel}}") + .to("direct:solrIndexing") .otherwise() .log(DEBUG, log, "Ignoring resource ${headers[CamelFcrepoUri]}") .end(); @@ -88,17 +81,11 @@ public void configure() throws Exception { from("{{cdr.enhancement.perform.camel}}") .routeId("PerformEnhancementsQueue") .startupOrder(107) - .choice() - .when(simple("${headers[" + CdrBinaryPath + "]} == null")) - .log(INFO, log, "Indexing queued resource without binary path ${headers[CamelFcrepoUri]}") - .to("direct:solrIndexing") - .otherwise() - .log(INFO, log, "Processing queued enhancements ${headers[CdrEnhancementSet]}" + - "for ${headers[CamelFcrepoUri]}") - .multicast() - // trigger enhancements sequentially followed by indexing - .to("direct:process.enhancements", "direct:solrIndexing") - .end(); + .log(INFO, log, "Processing queued enhancements ${headers[CdrEnhancementSet]}" + + "for ${headers[CamelFcrepoUri]}") + .multicast() + // trigger enhancements sequentially followed by indexing + .to("direct:process.enhancements", "direct:solrIndexing"); // Expands enhancement requests into individual services from("direct:process.enhancements") diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageDerivativeProcessor.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageDerivativeProcessor.java index f49052e2e8..2b5d916b04 100644 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageDerivativeProcessor.java +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageDerivativeProcessor.java @@ -1,14 +1,13 @@ package edu.unc.lib.boxc.services.camel.images; -import java.util.regex.Pattern; - +import edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.Processor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders; +import java.util.regex.Pattern; /** * Processor which validates and prepares image objects for producing derivatives diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouter.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouter.java index c9b4ca057a..3ac5c266dc 100644 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouter.java +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouter.java @@ -21,11 +21,8 @@ public class ImageEnhancementsRouter extends RouteBuilder { private static final Logger log = getLogger(ImageEnhancementsRouter.class); - @BeanInject(value = "addSmallThumbnailProcessor") - private AddDerivativeProcessor addSmallThumbnailProcessor; - - @BeanInject(value = "addLargeThumbnailProcessor") - private AddDerivativeProcessor addLargeThumbProcessor; + private static final int CACHE_INVALIDATE_THREADS = 5; + private static final int CACHE_INVALIDATE_REQUESTS_PER_SEC = 10; @BeanInject(value = "addAccessCopyProcessor") private AddDerivativeProcessor addAccessCopyProcessor; @@ -50,52 +47,6 @@ public void configure() throws Exception { .backOffMultiplier("{{error.backOffMultiplier}}") .retryAttemptedLogLevel(LoggingLevel.WARN); - from("direct:process.enhancement.thumbnails") - .routeId("ProcessThumbnails") - .startupOrder(23) - .log(LoggingLevel.INFO, log, "Thumbs ${headers[CdrBinaryPath]} with ${headers[CdrMimeType]}") - .filter().method(imageDerivProcessor, "allowedImageType") - .log(LoggingLevel.INFO, log, "Generating thumbnails for ${headers[org.fcrepo.jms.identifier]}" - + " of type ${headers[CdrMimeType]}") - .bean(imageDerivProcessor) - // Generate an random identifier to avoid derivative collisions - .setBody(exchange -> uuidGenerator.generateUuid()) - .multicast() - .shareUnitOfWork() - .to("direct:small.thumbnail", "direct:large.thumbnail"); - - from("direct:small.thumbnail") - .routeId("SmallThumbnail") - .startupOrder(22) - .log(LoggingLevel.INFO, log, "Creating/Updating Small Thumbnail for ${headers[CdrImagePath]}") - .filter().method(addSmallThumbnailProcessor, "needsRun") - .setHeader(CdrFcrepoHeaders.CdrTempPath, simple("${properties:services.tempDirectory}/${body}-small")) - .doTry() - .recipientList(simple("exec:/bin/sh?args=${properties:cdr.enhancement.bin}/convertScaleStage.sh " - + "${headers[CdrImagePath]} png 64 64 ${headers[CdrTempPath]}")) - .bean(addSmallThumbnailProcessor) - .endDoTry() - .doFinally() - // Ensure temp files get cleaned up in case of failure - .bean(addSmallThumbnailProcessor, "cleanupTempFile") - .end(); - - - from("direct:large.thumbnail") - .routeId("LargeThumbnail") - .startupOrder(21) - .log(LoggingLevel.INFO, log, "Creating/Updating Large Thumbnail for ${headers[CdrImagePath]}") - .filter().method(addLargeThumbProcessor, "needsRun") - .setHeader(CdrFcrepoHeaders.CdrTempPath, simple("${properties:services.tempDirectory}/${body}-large")) - .doTry() - .recipientList(simple("exec:/bin/sh?args=${properties:cdr.enhancement.bin}/convertScaleStage.sh " - + "${headers[CdrImagePath]} png 128 128 ${headers[CdrTempPath]}")) - .bean(addLargeThumbProcessor) - .endDoTry() - .doFinally() - .bean(addLargeThumbProcessor, "cleanupTempFile") - .end(); - from("direct:process.enhancement.imageAccessCopy") .routeId("AccessCopy") .startupOrder(20) @@ -111,7 +62,12 @@ public void configure() throws Exception { .recipientList(simple("exec:/bin/sh?args=${properties:cdr.enhancement.bin}/convertJp2.sh " + "${headers[CdrImagePath]} ${headers[CdrMimeType]} ${headers[CdrTempPath]}")) .bean(addAccessCopyProcessor) - .bean(imageCacheInvalidationProcessor) + // Process cache invalidation asynchronously with a limited number of threads + .threads(CACHE_INVALIDATE_THREADS) + // Limit the max number of requests per second + .throttle(CACHE_INVALIDATE_REQUESTS_PER_SEC) + .bean(imageCacheInvalidationProcessor) + .end() .endDoTry() .doFinally() .bean(addAccessCopyProcessor, "cleanupTempFile") diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/thumbnails/ImportThumbnailRequestProcessor.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/thumbnails/ImportThumbnailRequestProcessor.java new file mode 100644 index 0000000000..40e0b6b9ed --- /dev/null +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/thumbnails/ImportThumbnailRequestProcessor.java @@ -0,0 +1,56 @@ +package edu.unc.lib.boxc.services.camel.thumbnails; + +import edu.unc.lib.boxc.model.fcrepo.ids.PIDs; +import edu.unc.lib.boxc.operations.jms.thumbnails.ImportThumbnailRequestSerializationHelper; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryMimeType; +import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryPath; +import static org.fcrepo.camel.FcrepoHeaders.FCREPO_URI; + +/** + * Processing requests to import images to use as a thumbnail for a non-work Repository object + * + * @author snluong + */ +public class ImportThumbnailRequestProcessor implements Processor { + private static final Logger log = LoggerFactory.getLogger(ImportThumbnailRequestProcessor.class); + @Override + public void process(Exchange exchange) throws IOException { + var in = exchange.getIn(); + var request = ImportThumbnailRequestSerializationHelper.toRequest(in.getBody(String.class)); + var mimetype = request.getMimetype(); + var storagePath = request.getStoragePath(); + var pidString = request.getPidString(); + var repoPath = PIDs.get(pidString).getRepositoryPath(); + + in.setHeader(CdrBinaryPath, storagePath.toString()); + in.setHeader(CdrBinaryMimeType, mimetype); + in.setHeader(FCREPO_URI, repoPath); + } + + /** + * Deletes the temporarily stored uploaded thumbnail file + * @param exchange + * @throws IOException + */ + public void cleanupTempThumbnailFile(Exchange exchange) throws IOException { + final Message in = exchange.getIn(); + String tempValue = (String) in.getHeader(CdrBinaryPath); + Path tempPath = Paths.get(tempValue); + + boolean deleted = Files.deleteIfExists(tempPath); + if (deleted) { + log.debug("Cleaned up leftover temp file {}", tempPath); + } + } +} diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouter.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouter.java index 130de4fb2c..723f6e4555 100644 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouter.java +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouter.java @@ -8,7 +8,9 @@ import static org.slf4j.LoggerFactory.getLogger; /** - * Router for processing assigning thumbnails for works + * Router for processing thumbnails: + * Importing thumbnails for collections, folders, and admin units + * Assigning thumbnails for works * * @author snluong */ @@ -16,12 +18,28 @@ public class ThumbnailRouter extends RouteBuilder { private static final Logger log = getLogger(ThumbnailRouter.class); @BeanInject(value = "thumbnailRequestProcessor") private ThumbnailRequestProcessor thumbnailRequestProcessor; + @BeanInject(value = "importThumbnailRequestProcessor") + private ImportThumbnailRequestProcessor importThumbnailRequestProcessor; @Override public void configure() throws Exception { from("{{cdr.thumbnails.stream.camel}}") - .routeId("DcrThumbnails") - .log(DEBUG, log, "Received thumbnail request") - .bean(thumbnailRequestProcessor); + .routeId("DcrThumbnails") + .log(DEBUG, log, + "Received thumbnail request: assigning thumbnail for ${headers[CamelFcrepoUri]}") + .bean(thumbnailRequestProcessor); + + from("{{cdr.import.thumbnails.stream.camel}}") + .routeId("DcrImportThumbnails") + .process(importThumbnailRequestProcessor) + .log(DEBUG, log, + "Received thumbnail request: importing thumbnail for ${headers[CamelFcrepoUri]}") + .doTry() + // trigger JP2 generation sequentially followed by indexing + .to("direct:process.enhancement.imageAccessCopy", "direct:solrIndexing") + .endDoTry() + .doFinally() + .bean(importThumbnailRequestProcessor, "cleanupTempThumbnailFile") + .end(); } } diff --git a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/viewSettings/ViewSettingRouter.java b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/viewSettings/ViewSettingRouter.java index 2cadb72aa2..656df013c9 100644 --- a/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/viewSettings/ViewSettingRouter.java +++ b/services-camel-app/src/main/java/edu/unc/lib/boxc/services/camel/viewSettings/ViewSettingRouter.java @@ -9,7 +9,7 @@ import static org.slf4j.LoggerFactory.getLogger; /** - * Router for processing requests to update view setting of UV + * Router for processing requests to update view setting of Clover * * @author snluong */ diff --git a/services-camel-app/src/main/webapp/WEB-INF/service-context.xml b/services-camel-app/src/main/webapp/WEB-INF/service-context.xml index 47df9ca010..5af213c7c4 100644 --- a/services-camel-app/src/main/webapp/WEB-INF/service-context.xml +++ b/services-camel-app/src/main/webapp/WEB-INF/service-context.xml @@ -98,6 +98,8 @@ + + @@ -193,10 +195,6 @@ - - - - @@ -210,16 +208,6 @@ - - - - - - - - - - @@ -244,7 +232,7 @@ - + @@ -252,16 +240,6 @@ - - - - - - - - - - @@ -530,6 +508,9 @@ + + + diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/NonBinaryEnhancementProcessorTest.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/NonBinaryEnhancementProcessorTest.java deleted file mode 100644 index 42be4aa503..0000000000 --- a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/NonBinaryEnhancementProcessorTest.java +++ /dev/null @@ -1,92 +0,0 @@ -package edu.unc.lib.boxc.services.camel; - -import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryMimeType; -import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryPath; -import static org.fcrepo.camel.FcrepoHeaders.FCREPO_URI; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; - -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.apache.camel.Exchange; -import org.apache.camel.Message; -import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; -import org.mockito.Mock; - -import edu.unc.lib.boxc.model.fcrepo.test.TestHelper; - -/** - * @author lfarrell - */ -public class NonBinaryEnhancementProcessorTest { - private NonBinaryEnhancementProcessor processor; - private AutoCloseable closeable; - - @TempDir - public Path tmpFolder; - - private static final String FEDORA_BASE = "http://example.com/rest/"; - - private static final String RESC_ID = "de75d811-9e0f-4b1f-8631-2060ab3580cc"; - private static final String RESC_URI = FEDORA_BASE + "content/de/75/d8/11/" + RESC_ID; - - @Mock - private Exchange exchange; - @Mock - private Message message; - private File imgFile; - private String dataDir; - - @BeforeEach - public void init() throws Exception { - closeable = openMocks(this); - dataDir = tmpFolder.toString(); - - TestHelper.setContentBase(FEDORA_BASE); - processor = new NonBinaryEnhancementProcessor(); - processor.setSourceImagesDir(dataDir); - - when(exchange.getIn()).thenReturn(message); - when(message.getHeader(FCREPO_URI)).thenReturn(RESC_URI); - } - - @AfterEach - void closeService() throws Exception { - closeable.close(); - } - - @Test - public void testCollectionWithImage() throws Exception { - String derivativeFinalPath = "de/75/d8/11/" + RESC_ID; - Path uploadedFilePath = Paths.get(dataDir, derivativeFinalPath); - Files.createDirectories(uploadedFilePath.getParent()); - - imgFile = new File(uploadedFilePath.toString()); - FileUtils.writeStringToFile(imgFile, "image file", StandardCharsets.UTF_8); - - processor.process(exchange); - - verify(message).setHeader(CdrBinaryMimeType, "image/*"); - verify(message).setHeader(CdrBinaryPath, imgFile.getAbsolutePath()); - } - - @Test - public void testCollectionWithoutImage() throws Exception { - imgFile = new File(dataDir + "/1234"); - - processor.process(exchange); - - verify(message, never()).setHeader(CdrBinaryMimeType, "image/*"); - verify(message, never()).setHeader(CdrBinaryPath, imgFile.getAbsolutePath()); - } -} diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesProcessorTest.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesProcessorTest.java index e5ba3ce9ca..d171194432 100644 --- a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesProcessorTest.java +++ b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesProcessorTest.java @@ -2,7 +2,6 @@ import static edu.unc.lib.boxc.model.api.DatastreamType.FULLTEXT_EXTRACTION; import static edu.unc.lib.boxc.model.api.DatastreamType.JP2_ACCESS_COPY; -import static edu.unc.lib.boxc.model.api.DatastreamType.THUMBNAIL_LARGE; import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryMimeType; import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryPidId; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -97,60 +96,6 @@ public void deleteFulltextTest() throws Exception { assertTrue(derivativeTypeBaseDir.exists()); } - @Test - public void deleteThumbnailTest() throws Exception { - derivativeTypeDir = THUMBNAIL_LARGE.getId(); - derivativeFinalDir = Files.createDirectories(tmpFolder.resolve(derivativeTypeDir + "/de/75/d8/11")).toFile(); - file = new File(derivativeFinalDir, pathId + ".png"); - - FileUtils.writeStringToFile(file, "fake image", StandardCharsets.UTF_8); - - derivativeTypeBaseDir = new File(derivativeDirBase, derivativeTypeDir); - processor = new DestroyDerivativesProcessor("png", derivativeTypeBaseDir.getAbsolutePath()); - - when(message.getHeader(eq(CdrBinaryMimeType))) - .thenReturn("image/png"); - - processor.process(exchange); - - // Deleted file - assertFalse(file.exists()); - // Deleted parent dirs - assertFalse(new File(derivativeTypeBaseDir, "de").exists()); - // Didn't delete root derivative type dir - assertTrue(derivativeTypeBaseDir.exists()); - } - - @Test - public void deleteCollectionSrcImgTest() throws Exception { - String srcDirBase = "srcDir"; - File srcDir = Files.createDirectories(tmpFolder.resolve(srcDirBase + "/de/75/d8/11")).toFile(); - File srcFile = new File(srcDir, pathId); - FileUtils.writeStringToFile(srcFile, "fake image src", StandardCharsets.UTF_8); - - derivativeTypeBaseDir = new File(derivativeDirBase, srcDirBase); - - processor = new DestroyDerivativesProcessor("", derivativeTypeBaseDir.getAbsolutePath()); - - when(message.getHeader(eq(CdrBinaryMimeType))) - .thenReturn("image/*"); - - when(message.getHeader(eq("CollectionThumb"))) - .thenReturn(true); - - assertTrue(srcFile.exists()); - assertTrue(srcDir.exists()); - - processor.process(exchange); - - // Make sure src image is removed - assertFalse(srcFile.exists()); - assertFalse(srcDir.exists()); - - // Didn't delete root derivative type dir - assertTrue(derivativeTypeBaseDir.exists()); - } - @Test public void deleteJp2Test() throws Exception { derivativeTypeDir = JP2_ACCESS_COPY.getId(); diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterIT.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterIT.java index e84e00a267..76ad705c3b 100644 --- a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterIT.java +++ b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterIT.java @@ -40,11 +40,13 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.mockito.Mock; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.File; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -90,13 +92,10 @@ public class DestroyDerivativesRouterIT extends CamelSpringTestSupport { @Mock private MemberOrderRequestSender memberOrderRequestSender; - private DestroyedMsgProcessor destroyedMsgProcessor; - - private DestroyDerivativesProcessor destroyCollectionSrcImgProcessor; + @TempDir + public Path tmpFolder; - private DestroyDerivativesProcessor destroySmallThumbnailProcessor; - - private DestroyDerivativesProcessor destroyLargeThumbnailProcessor; + private DestroyedMsgProcessor destroyedMsgProcessor; private DestroyDerivativesProcessor destroyAccessCopyProcessor; @@ -147,9 +146,6 @@ public void init() { indexingMessageSender = applicationContext.getBean(IndexingMessageSender.class); binaryDestroyedMessageSender = applicationContext.getBean("binaryDestroyedMessageSender", MessageSender.class); destroyedMsgProcessor = applicationContext.getBean(DestroyedMsgProcessor.class); - destroyCollectionSrcImgProcessor = applicationContext.getBean("destroyCollectionSrcImgProcessor", DestroyDerivativesProcessor.class); - destroySmallThumbnailProcessor = applicationContext.getBean("destroySmallThumbnailProcessor", DestroyDerivativesProcessor.class); - destroyLargeThumbnailProcessor = applicationContext.getBean("destroyLargeThumbnailProcessor", DestroyDerivativesProcessor.class); destroyAccessCopyProcessor = applicationContext.getBean("destroyAccessCopyProcessor", DestroyDerivativesProcessor.class); destroyFulltextProcessor = applicationContext.getBean("destroyFulltextProcessor", DestroyDerivativesProcessor.class); destroyAudioProcessor = applicationContext.getBean("destroyAudioProcessor", DestroyDerivativesProcessor.class); @@ -168,6 +164,7 @@ public void init() { .model); collection = repoObjectFactory.createCollectionObject(null); + destroyedMsgProcessor.setJp2BasePath(tmpFolder.toString()); contentRoot.addMember(adminUnit); adminUnit.addMember(collection); @@ -198,9 +195,6 @@ public void destroyImageTest() throws Exception { initializeDestroyJob(Collections.singletonList(fileObj.getPid())); destroyJob.run(); - verify(destroySmallThumbnailProcessor).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor, never()).process(any(Exchange.class)); verify(destroyAccessCopyProcessor).process(any(Exchange.class)); verify(destroyFulltextProcessor, never()).process(any(Exchange.class)); verify(destroyAudioProcessor, never()).process(any(Exchange.class)); @@ -213,23 +207,21 @@ public void destroyCollectionImageTest() throws Exception { treeIndexer.indexAll(baseAddress); - // Create collection thumbnail + // Create collection thumbnail jp2 PID collPid = collectionWithImg.getPid(); String uuid = collPid.getId(); String binarySubPath = idToPath(uuid, HASHED_PATH_DEPTH, HASHED_PATH_SIZE); - Path existingFileDirs = Files.createDirectories(new File("target/" + binarySubPath).toPath()); - File existingFile = new File(existingFileDirs.toString(), uuid); - FileUtils.writeStringToFile(existingFile, "thumbnail", "UTF-8"); + var derivativeFinalDir = Files.createDirectories(tmpFolder.resolve( binarySubPath)).toFile(); + var file = new File(derivativeFinalDir, uuid + ".jp2"); + FileUtils.writeStringToFile(file, "fake jp2", StandardCharsets.UTF_8); - markForDeletion(collPid); + new MarkForDeletionJob(collPid, "", agent, repoObjLoader, + sparqlUpdateService, aclService, premisLoggerFactory).run(); initializeDestroyJob(Collections.singletonList(collPid)); destroyJob.run(); - verify(destroySmallThumbnailProcessor).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor).process(any(Exchange.class)); - verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); + verify(destroyAccessCopyProcessor).process(any(Exchange.class)); verify(destroyFulltextProcessor, never()).process(any(Exchange.class)); verify(destroyAudioProcessor, never()).process(any(Exchange.class)); } @@ -245,9 +237,6 @@ public void destroyCollectionNoImageTest() throws Exception { initializeDestroyJob(Collections.singletonList(collectionWithImg.getPid())); destroyJob.run(); - verify(destroySmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor, never()).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor, never()).process(any(Exchange.class)); verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); verify(destroyFulltextProcessor, never()).process(any(Exchange.class)); verify(destroyAudioProcessor, never()).process(any(Exchange.class)); @@ -266,9 +255,6 @@ public void destroyTextTest() throws Exception { initializeDestroyJob(Collections.singletonList(fileObj.getPid())); destroyJob.run(); - verify(destroySmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor, never()).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor, never()).process(any(Exchange.class)); verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); verify(destroyFulltextProcessor).process(any(Exchange.class)); verify(destroyAudioProcessor, never()).process(any(Exchange.class)); @@ -286,9 +272,6 @@ public void invalidTypeTest() throws Exception { initializeDestroyJob(Collections.singletonList(fileObj.getPid())); destroyJob.run(); - verify(destroySmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor, never()).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor, never()).process(any(Exchange.class)); verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); verify(destroyFulltextProcessor, never()).process(any(Exchange.class)); verify(destroyAudioProcessor, never()).process(any(Exchange.class)); @@ -306,9 +289,6 @@ public void destroyAudioTest() throws Exception { initializeDestroyJob(Collections.singletonList(fileObj.getPid())); destroyJob.run(); - verify(destroySmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor, never()).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor, never()).process(any(Exchange.class)); verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); verify(destroyFulltextProcessor, never()).process(any(Exchange.class)); verify(destroyAudioProcessor).process(any(Exchange.class)); diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterTest.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterTest.java index 5166e31e4b..14986ef3bb 100644 --- a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterTest.java +++ b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/destroyDerivatives/DestroyDerivativesRouterTest.java @@ -16,7 +16,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.nio.file.Files; import java.nio.file.Path; import java.util.concurrent.TimeUnit; @@ -30,7 +29,6 @@ public class DestroyDerivativesRouterTest extends CamelTestSupport { private static final String DESTROY_DERIVATIVES_ROUTE = "CdrDestroyDerivatives"; private static final String DESTROY_FULLTEXT_ROUTE = "CdrDestroyFullText"; private static final String DESTROY_IMAGE_ROUTE = "CdrDestroyImage"; - private static final String DESTROY_ACCESS_COPY_ROUTE = "CdrDestroyAccessCopy"; private static final String TEST_ID = "dee2614c-8a4b-4ac2-baf2-4b4afc11af87"; @Produce("direct:start") @@ -41,12 +39,6 @@ public class DestroyDerivativesRouterTest extends CamelTestSupport { @Mock private DestroyDerivativesProcessor destroyCollectionSrcImgProcessor; - @Mock - private DestroyDerivativesProcessor destroySmallThumbnailProcessor; - - @Mock - private DestroyDerivativesProcessor destroyLargeThumbnailProcessor; - @Mock private DestroyDerivativesProcessor destroyAccessCopyProcessor; @@ -61,12 +53,9 @@ public class DestroyDerivativesRouterTest extends CamelTestSupport { @Override protected RouteBuilder createRouteBuilder() throws Exception { - destroyedMsgProcessor = new DestroyedMsgProcessor(tmpFolder.toAbsolutePath().toString()); + destroyedMsgProcessor = new DestroyedMsgProcessor(); var router = new DestroyDerivativesRouter(); router.setDestroyedMsgProcessor(destroyedMsgProcessor); - router.setDestroyCollectionSrcImgProcessor(destroyCollectionSrcImgProcessor); - router.setDestroySmallThumbnailProcessor(destroySmallThumbnailProcessor); - router.setDestroyLargeThumbnailProcessor(destroyLargeThumbnailProcessor); router.setDestroyAccessCopyProcessor(destroyAccessCopyProcessor); router.setDestroyFulltextProcessor(destroyFulltextProcessor); router.setDestroyAudioProcessor(destroyAudioProcessor); @@ -141,9 +130,7 @@ public void destroyTextDerivative() throws Exception { template.sendBody(body); verify(destroyFulltextProcessor).process(any(Exchange.class)); - verify(destroySmallThumbnailProcessor, never()).process(any(Exchange.class)); verify(destroyCollectionSrcImgProcessor, never()).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor, never()).process(any(Exchange.class)); verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); verify(destroyAudioProcessor, never()).process(any(Exchange.class)); } @@ -156,21 +143,13 @@ public void destroyImageThumbnailDerivative() throws Exception { var body = createMessage(Cdr.FileObject, "image/png", TEST_ID, contentPath); template.sendBody(body); - verify(destroySmallThumbnailProcessor).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor, never()).process(any(Exchange.class)); - verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); + verify(destroyAccessCopyProcessor).process(any(Exchange.class)); verify(destroyFulltextProcessor, never()).process(any(Exchange.class)); verify(destroyAudioProcessor, never()).process(any(Exchange.class)); } @Test public void destroyImageThumbnailDerivativeCollection() throws Exception { - // Create the thumbnail file for the collection - var thumbPath = tmpFolder.resolve("de/e2/61/4c").resolve(TEST_ID); - Files.createDirectories(thumbPath.getParent()); - Files.createFile(thumbPath); - AdviceWith.adviceWith(context, DESTROY_DERIVATIVES_ROUTE, a -> { a.replaceFromWith("direct:start"); }); @@ -179,10 +158,7 @@ public void destroyImageThumbnailDerivativeCollection() throws Exception { var body = createMessage(Cdr.Collection, "image/*", TEST_ID, contentPath); template.sendBody(body); - verify(destroySmallThumbnailProcessor).process(any(Exchange.class)); - verify(destroyLargeThumbnailProcessor).process(any(Exchange.class)); - verify(destroyCollectionSrcImgProcessor).process(any(Exchange.class)); - verify(destroyAccessCopyProcessor, never()).process(any(Exchange.class)); + verify(destroyAccessCopyProcessor).process(any(Exchange.class)); verify(destroyFulltextProcessor, never()).process(any(Exchange.class)); verify(destroyAudioProcessor, never()).process(any(Exchange.class)); } @@ -206,7 +182,7 @@ public void destroyImageThumbnailNoDerivativeCollection() throws Exception { @Test public void destroyImageAccessDerivative() throws Exception { - createContext(DESTROY_ACCESS_COPY_ROUTE); + createContext(DESTROY_IMAGE_ROUTE); Path contentPath = tmpFolder.resolve("content"); var body = createMessage(Cdr.FileObject, "image/png", TEST_ID, contentPath); diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouterIT.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouterIT.java index 6f2db4c9c7..61ec00fed4 100644 --- a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouterIT.java +++ b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/enhancements/EnhancementRouterIT.java @@ -15,7 +15,6 @@ import edu.unc.lib.boxc.operations.impl.edit.UpdateDescriptionService; import edu.unc.lib.boxc.operations.impl.edit.UpdateDescriptionService.UpdateDescriptionRequest; import edu.unc.lib.boxc.persist.impl.storage.StorageLocationTestHelper; -import edu.unc.lib.boxc.services.camel.NonBinaryEnhancementProcessor; import edu.unc.lib.boxc.services.camel.fulltext.FulltextProcessor; import edu.unc.lib.boxc.services.camel.images.AddDerivativeProcessor; import edu.unc.lib.boxc.services.camel.solr.SolrIngestProcessor; @@ -84,10 +83,6 @@ public class EnhancementRouterIT extends CamelSpringTestSupport { @Produce("{{cdr.enhancement.stream.camel}}") private ProducerTemplate template; - private AddDerivativeProcessor addSmallThumbnailProcessor; - - private AddDerivativeProcessor addLargeThumbnailProcessor; - private AddDerivativeProcessor addAccessCopyProcessor; private SolrIngestProcessor solrIngestProcessor; @@ -103,7 +98,6 @@ public class EnhancementRouterIT extends CamelSpringTestSupport { private File tempDir; - private NonBinaryEnhancementProcessor nbh; @Override protected AbstractApplicationContext createApplicationContext() { @@ -121,27 +115,17 @@ public void init() throws Exception { storageLocationTestHelper = applicationContext.getBean(StorageLocationTestHelper.class); fcrepoClient = applicationContext.getBean(FcrepoClient.class); cdrEnhancements = applicationContext.getBean(CamelContext.class); - addSmallThumbnailProcessor = applicationContext.getBean("addSmallThumbnailProcessor", AddDerivativeProcessor.class); - addLargeThumbnailProcessor = applicationContext.getBean("addLargeThumbnailProcessor", AddDerivativeProcessor.class); addAccessCopyProcessor = applicationContext.getBean("addAccessCopyProcessor", AddDerivativeProcessor.class); solrIngestProcessor = applicationContext.getBean("solrIngestProcessor", SolrIngestProcessor.class); fulltextProcessor = applicationContext.getBean("fulltextProcessor", FulltextProcessor.class); addAudioAccessCopyProcessor = applicationContext.getBean("addAudioAccessCopyProcessor", AddDerivativeProcessor.class); updateDescriptionService = applicationContext.getBean(UpdateDescriptionService.class); - nbh = applicationContext.getBean(NonBinaryEnhancementProcessor.class); - when(addSmallThumbnailProcessor.needsRun(any(Exchange.class))).thenReturn(true); - when(addLargeThumbnailProcessor.needsRun(any(Exchange.class))).thenReturn(true); when(addAccessCopyProcessor.needsRun(any(Exchange.class))).thenReturn(true); when(addAudioAccessCopyProcessor.needsRun(any(Exchange.class))).thenReturn(true); TestHelper.setContentBase(baseAddress); tempDir = Files.createDirectory(tmpFolder.resolve("target")).toFile(); - nbh.setSourceImagesDir(tempDir.getAbsolutePath()); - - File thumbScriptFile = new File("target/convertScaleStage.sh"); - FileUtils.writeStringToFile(thumbScriptFile, "exit 0", "utf-8"); - thumbScriptFile.deleteOnExit(); File jp2ScriptFile = new File("target/convertJp2.sh"); FileUtils.writeStringToFile(jp2ScriptFile, "exit 0", "utf-8"); @@ -174,9 +158,6 @@ public void nonBinaryWithSourceImages() throws Exception { Cdr.Collection.getURI(), Container.getURI()); template.sendBodyAndHeaders("", headers); - verify(addSmallThumbnailProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); - verify(addAccessCopyProcessor, never()).process(any(Exchange.class)); verify(solrIngestProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); verify(addAudioAccessCopyProcessor, never()).process(any(Exchange.class)); } @@ -189,8 +170,6 @@ public void nonBinaryNoSourceImages() throws Exception { template.sendBodyAndHeaders("", headers); verify(solrIngestProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); - verify(addSmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor, never()).process(any(Exchange.class)); verify(addAudioAccessCopyProcessor, never()).process(any(Exchange.class)); } @@ -204,7 +183,7 @@ public void testBinaryImageFile() throws Exception { // Separate exchanges when multicasting NotifyBuilder notify1 = new NotifyBuilder(cdrEnhancements) - .whenCompleted(12) + .whenCompleted(7) .create(); final Map headers = createEvent(binObj.getPid(), Binary.getURI()); @@ -213,8 +192,6 @@ public void testBinaryImageFile() throws Exception { boolean result1 = notify1.matches(5L, TimeUnit.SECONDS); assertTrue(result1, "Enhancement route not satisfied"); - verify(addSmallThumbnailProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); verify(addAccessCopyProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); // Indexing triggered for binary parent verify(solrIngestProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); @@ -243,8 +220,6 @@ public void testBinaryMetadataFile() throws Exception { assertTrue(result, "Processing message did not match expectations"); - verify(addSmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor, never()).process(any(Exchange.class)); verify(addAccessCopyProcessor, never()).process(any(Exchange.class)); verify(solrIngestProcessor, never()).process(any(Exchange.class)); verify(addAudioAccessCopyProcessor, never()).process(any(Exchange.class)); @@ -270,8 +245,7 @@ public void testInvalidFile() throws Exception { assertTrue(result, "Processing message did not match expectations"); - verify(addSmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(fulltextProcessor, never()).process(any(Exchange.class)); + verify(fulltextProcessor, never()).process(any(Exchange.class)); verify(solrIngestProcessor, never()).process(any(Exchange.class)); verify(addAudioAccessCopyProcessor, never()).process(any(Exchange.class)); } @@ -319,8 +293,6 @@ public void testDepositManifestFileMetadata() throws Exception { assertTrue(result, "Processing message did not match expectations"); - verify(addSmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor, never()).process(any(Exchange.class)); verify(addAccessCopyProcessor, never()).process(any(Exchange.class)); verify(solrIngestProcessor, never()).process(any(Exchange.class)); verify(addAudioAccessCopyProcessor, never()).process(any(Exchange.class)); @@ -344,8 +316,6 @@ public void testAudioFile() throws Exception { boolean result = notify.matches(5L, TimeUnit.SECONDS); - verify(addSmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor, never()).process(any(Exchange.class)); verify(addAccessCopyProcessor, never()).process(any(Exchange.class)); verify(addAudioAccessCopyProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); verify(solrIngestProcessor, timeout(ALLOW_WAIT)).process(any(Exchange.class)); diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouterTest.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouterTest.java index d9d8d0a62f..3d45798f4a 100644 --- a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouterTest.java +++ b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/images/ImageEnhancementsRouterTest.java @@ -1,6 +1,5 @@ package edu.unc.lib.boxc.services.camel.images; -import edu.unc.lib.boxc.fcrepo.FcrepoJmsConstants; import org.apache.camel.BeanInject; import org.apache.camel.CamelExecutionException; import org.apache.camel.EndpointInject; @@ -44,15 +43,16 @@ import static org.mockito.Mockito.when; public class ImageEnhancementsRouterTest extends CamelSpringTestSupport { + private static final String EVENT_NS = "http://fedora.info/definitions/v4/event#"; + private static final String EVENT_TYPE = "org.fcrepo.jms.eventType"; + private static final String IDENTIFIER = "org.fcrepo.jms.identifier"; + private static final String RESOURCE_TYPE = "org.fcrepo.jms.resourceType"; private static final long timestamp = 1428360320168L; private static final String userID = "bypassAdmin"; private static final String userAgent = "curl/7.37.1"; private static final String fileID = "343b3da4-8876-42f5-8821-7aabb65e0f19"; - private final String eventTypes = FcrepoJmsConstants.EVENT_NS + "ResourceCreation"; - private final String thumbnailRoute = "ProcessThumbnails"; + private final String eventTypes = EVENT_NS + "ResourceCreation"; private final String accessCopyRoute = "AccessCopy"; - private final String smallThumbRoute = "SmallThumbnail"; - private final String largeThumbRoute = "LargeThumbnail"; @PropertyInject(value = "fcrepo.baseUrl") private static String baseUri; @@ -63,12 +63,6 @@ public class ImageEnhancementsRouterTest extends CamelSpringTestSupport { @Produce("direct:process.binary.original") protected ProducerTemplate template; - @BeanInject(value = "addSmallThumbnailProcessor") - private AddDerivativeProcessor addSmallThumbnailProcessor; - - @BeanInject(value = "addLargeThumbnailProcessor") - private AddDerivativeProcessor addLargeThumbnailProcessor; - @BeanInject(value = "addAccessCopyProcessor") private AddDerivativeProcessor addAccessCopyProcessor; @@ -85,260 +79,6 @@ public void cleanup() throws IOException { FileUtils.deleteDirectory(new File("target/34")); } - @Test - public void testThumbnailMulticast() throws Exception { - createContext(thumbnailRoute); - - var smallEndpoint = getMockEndpoint("mock:direct:small.thumbnail"); - smallEndpoint.expectedMessageCount(1); - var largeEndpoint = getMockEndpoint("mock:direct:large.thumbnail"); - largeEndpoint.expectedMessageCount(1); - template.sendBodyAndHeaders("", createEvent(fileID, eventTypes, "false")); - - smallEndpoint.assertIsSatisfied(); - largeEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbMulticastFilter() throws Exception { - createContext(thumbnailRoute); - - var smallEndpoint = getMockEndpoint("mock:direct:small.thumbnail"); - smallEndpoint.expectedMessageCount(0); - var largeEndpoint = getMockEndpoint("mock:direct:large.thumbnail"); - largeEndpoint.expectedMessageCount(0); - - Map headers = createEvent(fileID, eventTypes, "false"); - headers.put(CdrBinaryMimeType, "plain/text"); - - template.sendBodyAndHeaders("", headers); - - smallEndpoint.assertIsSatisfied(); - largeEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbDisallowedImageType() throws Exception { - createContext(thumbnailRoute); - - var smallEndpoint = getMockEndpoint("mock:direct:small.thumbnail"); - smallEndpoint.expectedMessageCount(0); - var largeEndpoint = getMockEndpoint("mock:direct:large.thumbnail"); - largeEndpoint.expectedMessageCount(0); - - Map headers = createEvent(fileID, eventTypes, "false"); - headers.put(CdrBinaryMimeType, "image/vnd.fpx"); - - template.sendBodyAndHeaders("", headers); - - smallEndpoint.assertIsSatisfied(); - largeEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbSmallRouteNoForceNoFileExists() throws Exception { - when(addSmallThumbnailProcessor.needsRun(any())).thenReturn(true); - createContext(smallThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - - Map headers = createEvent(fileID, eventTypes, "false"); - template.sendBodyAndHeaders("", headers); - - verify(addSmallThumbnailProcessor).process(any(Exchange.class)); - verify(addSmallThumbnailProcessor).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbSmallRouteScriptFails() throws Exception { - when(addSmallThumbnailProcessor.needsRun(any())).thenReturn(true); - createContext(smallThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - shEndpoint.whenAnyExchangeReceived(new Processor() { - @Override - public void process(Exchange exchange) throws Exception { - throw new IllegalStateException("Failing run of exec"); - } - }); - - Map headers = createEvent(fileID, eventTypes, "false"); - try { - template.sendBodyAndHeaders("", headers); - fail("Exception expected to be thrown"); - } catch (CamelExecutionException e) { - assertTrue(e.getCause() instanceof IllegalStateException); - } - - verify(addSmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addSmallThumbnailProcessor).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbSmallRouteForceNoFileExists() throws Exception { - when(addSmallThumbnailProcessor.needsRun(any())).thenReturn(true); - createContext(smallThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - - Map headers = createEvent(fileID, eventTypes, "true"); - template.sendBodyAndHeaders("", headers); - - verify(addSmallThumbnailProcessor).process(any(Exchange.class)); - verify(addSmallThumbnailProcessor).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbSmallRouteNoForceFileExists() throws Exception { - String derivativePath = idToPath(fileID, HASHED_PATH_DEPTH, HASHED_PATH_SIZE); - File existingFile = new File("target/" + derivativePath + "/" + fileID + ".png"); - FileUtils.writeStringToFile(existingFile, "extracted text", "utf-8"); - - createContext(smallThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(0); - - Map headers = createEvent(fileID, eventTypes, "false"); - template.sendBodyAndHeaders("", headers); - - verify(addSmallThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addSmallThumbnailProcessor, never()).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbSmallRouteForceFileExists() throws Exception { - when(addSmallThumbnailProcessor.needsRun(any())).thenReturn(true); - String derivativePath = idToPath(fileID, HASHED_PATH_DEPTH, HASHED_PATH_SIZE); - File existingFile = new File("target/" + derivativePath + "/" + fileID + ".png"); - FileUtils.writeStringToFile(existingFile, "extracted text", "utf-8"); - - createContext(smallThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - - Map headers = createEvent(fileID, eventTypes, "true"); - template.sendBodyAndHeaders("", headers); - - verify(addSmallThumbnailProcessor).process(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbLargeRouteNoForceNoFileExists() throws Exception { - when(addLargeThumbnailProcessor.needsRun(any())).thenReturn(true); - createContext(largeThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - - Map headers = createEvent(fileID, eventTypes, "false"); - - template.sendBodyAndHeaders("", headers); - - doNothing().when(addLargeThumbnailProcessor).process(any(Exchange.class)); - - verify(addLargeThumbnailProcessor).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbLargeRouteScriptFails() throws Exception { - when(addLargeThumbnailProcessor.needsRun(any())).thenReturn(true); - createContext(largeThumbRoute); - - MockEndpoint shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - shEndpoint.whenAnyExchangeReceived(new Processor() { - @Override - public void process(Exchange exchange) throws Exception { - throw new IllegalStateException("Failing run of exec"); - } - }); - - Map headers = createEvent(fileID, eventTypes, "false"); - try { - template.sendBodyAndHeaders("", headers); - fail("Exception expected to be thrown"); - } catch (CamelExecutionException e) { - assertTrue(e.getCause() instanceof IllegalStateException); - } - - verify(addLargeThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbLargeRouteForceNoFileExists() throws Exception { - when(addLargeThumbnailProcessor.needsRun(any())).thenReturn(true); - createContext(largeThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - - Map headers = createEvent(fileID, eventTypes, "true"); - - template.sendBodyAndHeaders("", headers); - - doNothing().when(addLargeThumbnailProcessor).process(any(Exchange.class)); - - verify(addLargeThumbnailProcessor).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbLargeRouteNoForceFileExists() throws Exception { - String derivativePath = idToPath(fileID, HASHED_PATH_DEPTH, HASHED_PATH_SIZE); - File existingFile = new File("target/" + derivativePath + "/" + fileID + ".png"); - FileUtils.writeStringToFile(existingFile, "extracted text", "utf-8"); - createContext(largeThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(0); - - Map headers = createEvent(fileID, eventTypes, "false"); - - template.sendBodyAndHeaders("", headers); - - doNothing().when(addLargeThumbnailProcessor).process(any(Exchange.class)); - - verify(addLargeThumbnailProcessor, never()).process(any(Exchange.class)); - verify(addLargeThumbnailProcessor, never()).cleanupTempFile(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - - @Test - public void testThumbLargeRouteForceFileExists() throws Exception { - when(addLargeThumbnailProcessor.needsRun(any())).thenReturn(true); - String derivativePath = idToPath(fileID, HASHED_PATH_DEPTH, HASHED_PATH_SIZE); - File existingFile = new File("target/" + derivativePath + "/" + fileID + ".png"); - FileUtils.writeStringToFile(existingFile, "extracted text", "utf-8"); - createContext(largeThumbRoute); - - var shEndpoint = getMockEndpoint("mock:exec:/bin/sh"); - shEndpoint.expectedMessageCount(1); - - Map headers = createEvent(fileID, eventTypes, "true"); - - template.sendBodyAndHeaders("", headers); - - doThrow(Exception.class).when(addLargeThumbnailProcessor).process(any(Exchange.class)); - - verify(addLargeThumbnailProcessor).process(any(Exchange.class)); - shEndpoint.assertIsSatisfied(); - } - @Test public void testAccessCopyRouteNoForceNoFileExists() throws Exception { when(addAccessCopyProcessor.needsRun(any())).thenReturn(true); @@ -508,9 +248,9 @@ private static Map createEvent(final String identifier, final St headers.put(FCREPO_AGENT, Arrays.asList(userID, userAgent)); headers.put(FCREPO_EVENT_TYPE, eventTypes); headers.put(FCREPO_BASE_URL, baseUri); - headers.put(FcrepoJmsConstants.EVENT_TYPE, "ResourceCreation"); - headers.put(FcrepoJmsConstants.IDENTIFIER, "original_file"); - headers.put(FcrepoJmsConstants.RESOURCE_TYPE, Binary.getURI()); + headers.put(EVENT_TYPE, "ResourceCreation"); + headers.put(IDENTIFIER, "original_file"); + headers.put(RESOURCE_TYPE, Binary.getURI()); headers.put(CdrBinaryMimeType, "image/png"); headers.put("force", force); diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/thumbnails/ImportThumbnailProcessorTest.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/thumbnails/ImportThumbnailProcessorTest.java new file mode 100644 index 0000000000..4ccb3e3c30 --- /dev/null +++ b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/thumbnails/ImportThumbnailProcessorTest.java @@ -0,0 +1,85 @@ +package edu.unc.lib.boxc.services.camel.thumbnails; + +import edu.unc.lib.boxc.auth.api.models.AgentPrincipals; +import edu.unc.lib.boxc.auth.fcrepo.models.AccessGroupSetImpl; +import edu.unc.lib.boxc.auth.fcrepo.models.AgentPrincipalsImpl; +import edu.unc.lib.boxc.model.api.ids.PID; +import edu.unc.lib.boxc.operations.jms.thumbnails.ImportThumbnailRequest; +import edu.unc.lib.boxc.operations.jms.thumbnails.ImportThumbnailRequestSerializationHelper; +import edu.unc.lib.boxc.services.camel.TestHelper; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryMimeType; +import static edu.unc.lib.boxc.services.camel.util.CdrFcrepoHeaders.CdrBinaryPath; +import static org.fcrepo.camel.FcrepoHeaders.FCREPO_URI; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.openMocks; + +public class ImportThumbnailProcessorTest { + private ImportThumbnailRequestProcessor processor; + + @TempDir + private Path path; + private Path tempThumbnailPath; + private final AgentPrincipals agent = new AgentPrincipalsImpl("user", new AccessGroupSetImpl("agroup")); + private Exchange exchange; + private Message message; + private String mimetype = "image/jpeg"; + private PID pid; + private AutoCloseable closeable; + + @BeforeEach + public void init() throws IOException { + closeable = openMocks(this); + processor = new ImportThumbnailRequestProcessor(); + pid = TestHelper.makePid(); + tempThumbnailPath = path.resolve(pid.getId() + ".png"); + + var request = new ImportThumbnailRequest(); + request.setMimetype(mimetype); + request.setAgent(agent); + request.setStoragePath(path); + request.setPidString(pid.getId()); + + exchange = TestHelper.mockExchange(ImportThumbnailRequestSerializationHelper.toJson(request)); + message = exchange.getIn(); + } + + @AfterEach + void closeService() throws Exception { + closeable.close(); + } + + @Test + public void testImportThumbnail() throws IOException { + processor.process(exchange); + + verify(message).setHeader(FCREPO_URI, pid.getRepositoryPath()); + verify(message).setHeader(CdrBinaryMimeType, mimetype); + verify(message).setHeader(CdrBinaryPath, path.toString()); + } + + @Test + public void cleanupTempThumbnailFileTest() throws Exception { + Files.write(tempThumbnailPath, List.of("fake image")); + assertTrue(Files.exists(tempThumbnailPath)); + when(message.getHeader(eq(CdrBinaryPath))) + .thenReturn(tempThumbnailPath.toString()); + processor.cleanupTempThumbnailFile(exchange); + assertFalse(Files.exists(tempThumbnailPath)); + } +} diff --git a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouterTest.java b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouterTest.java index d798ee1d49..219116cf5d 100644 --- a/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouterTest.java +++ b/services-camel-app/src/test/java/edu/unc/lib/boxc/services/camel/thumbnails/ThumbnailRouterTest.java @@ -3,10 +3,13 @@ import edu.unc.lib.boxc.auth.api.models.AgentPrincipals; import edu.unc.lib.boxc.auth.fcrepo.models.AccessGroupSetImpl; import edu.unc.lib.boxc.auth.fcrepo.models.AgentPrincipalsImpl; -import edu.unc.lib.boxc.services.camel.TestHelper; +import edu.unc.lib.boxc.operations.jms.thumbnails.ImportThumbnailRequest; +import edu.unc.lib.boxc.operations.jms.thumbnails.ImportThumbnailRequestSerializationHelper; import edu.unc.lib.boxc.operations.jms.thumbnails.ThumbnailRequest; import edu.unc.lib.boxc.operations.jms.thumbnails.ThumbnailRequestSerializationHelper; +import edu.unc.lib.boxc.services.camel.TestHelper; import org.apache.camel.BeanInject; +import org.apache.camel.Exchange; import org.apache.camel.Produce; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.AdviceWith; @@ -27,10 +30,14 @@ public class ThumbnailRouterTest extends CamelSpringTestSupport { protected ProducerTemplate template; @BeanInject(value = "thumbnailRequestProcessor") private ThumbnailRequestProcessor processor; + + @BeanInject(value = "importThumbnailRequestProcessor") + private ImportThumbnailRequestProcessor importProcessor; @Override protected AbstractApplicationContext createApplicationContext() { return new ClassPathXmlApplicationContext("/service-context.xml", "/thumbnails-context.xml"); } + @Test public void requestSentTest() throws Exception { createContext("DcrThumbnails"); @@ -45,6 +52,28 @@ public void requestSentTest() throws Exception { verify(processor).process(any()); } + @Test + public void importRequestSentTest() throws Exception { + createContext("DcrImportThumbnails"); + var pid = TestHelper.makePid(); + + var request = new ImportThumbnailRequest(); + request.setAgent(agent); + request.setPidString(pid.toString()); + + var body = ImportThumbnailRequestSerializationHelper.toJson(request); + var solrEndpoint = getMockEndpoint("mock:direct:solrIndexing"); + solrEndpoint.expectedMessageCount(1); + var imageAccessCopyEndpoint = getMockEndpoint("mock:direct:process.enhancement.imageAccessCopy"); + imageAccessCopyEndpoint.expectedMessageCount(1); + template.sendBody(body); + + verify(importProcessor).process(any()); + verify(importProcessor).cleanupTempThumbnailFile(any(Exchange.class)); + solrEndpoint.assertIsSatisfied(); + imageAccessCopyEndpoint.assertIsSatisfied(); + } + private void createContext(String routeName) throws Exception { AdviceWith.adviceWith(context, routeName, a -> { a.replaceFromWith("direct:start"); diff --git a/services-camel-app/src/test/resources/cdr-event-routing-it-config.properties b/services-camel-app/src/test/resources/cdr-event-routing-it-config.properties index 7737d0e7a8..01383a5409 100644 --- a/services-camel-app/src/test/resources/cdr-event-routing-it-config.properties +++ b/services-camel-app/src/test/resources/cdr-event-routing-it-config.properties @@ -7,8 +7,6 @@ fcrepo.authUsername= fcrepo.authPassword= fcrepo.authHost= -cdr.enhancement.thumbnail.fileExtension=PNG -cdr.enhancement.thumbnail.mimetype=image/png cdr.enhancement.fulltext.fileName=full_text.txt cdr.enhancement.jp2.fileExtension=JP2 cdr.enhancement.jp2.mimetype=image/jp2 diff --git a/services-camel-app/src/test/resources/config.properties b/services-camel-app/src/test/resources/config.properties index ddb0602c3d..6ddf93df0c 100644 --- a/services-camel-app/src/test/resources/config.properties +++ b/services-camel-app/src/test/resources/config.properties @@ -7,8 +7,6 @@ fcrepo.authUsername= fcrepo.authPassword= fcrepo.authHost= -cdr.enhancement.thumbnail.fileExtension=PNG -cdr.enhancement.thumbnail.mimetype=image/png cdr.enhancement.jp2.fileExtension=JP2 cdr.enhancement.jp2.mimetype=image/jp2 cdr.enhancement.postIndexingDelay=500 diff --git a/services-camel-app/src/test/resources/destroy-derivatives-router-it-config.properties b/services-camel-app/src/test/resources/destroy-derivatives-router-it-config.properties index b28f70bb5b..8f3127b07a 100644 --- a/services-camel-app/src/test/resources/destroy-derivatives-router-it-config.properties +++ b/services-camel-app/src/test/resources/destroy-derivatives-router-it-config.properties @@ -3,8 +3,6 @@ error.retryDelay=0 error.maxRedeliveries=2 error.backOffMultiplier=1 -sourceImages.dir=target - cdr.stream=activemq:queue:repository.events cdr.stream.camel=activemq://activemq:queue:repository.events diff --git a/services-camel-app/src/test/resources/destroy-derivatives-router-it-context.xml b/services-camel-app/src/test/resources/destroy-derivatives-router-it-context.xml index 8c5bd78312..cd2f874f77 100644 --- a/services-camel-app/src/test/resources/destroy-derivatives-router-it-context.xml +++ b/services-camel-app/src/test/resources/destroy-derivatives-router-it-context.xml @@ -22,19 +22,6 @@ - - - - - - - - - - - - - diff --git a/services-camel-app/src/test/resources/enhancement-router-it-config.properties b/services-camel-app/src/test/resources/enhancement-router-it-config.properties index e9e082a55f..ac5fb6c6d6 100644 --- a/services-camel-app/src/test/resources/enhancement-router-it-config.properties +++ b/services-camel-app/src/test/resources/enhancement-router-it-config.properties @@ -5,8 +5,6 @@ fcrepo.authUsername= fcrepo.authPassword= fcrepo.authHost= -cdr.enhancement.thumbnail.fileExtension=PNG -cdr.enhancement.thumbnail.mimetype=image/png cdr.enhancement.fulltext.fileName=full_text.txt cdr.enhancement.jp2.fileExtension=JP2 cdr.enhancement.jp2.mimetype=image/jp2 diff --git a/services-camel-app/src/test/resources/enhancement-router-it-context.xml b/services-camel-app/src/test/resources/enhancement-router-it-context.xml index b290474ac4..f0550dff49 100644 --- a/services-camel-app/src/test/resources/enhancement-router-it-context.xml +++ b/services-camel-app/src/test/resources/enhancement-router-it-context.xml @@ -28,14 +28,6 @@ - - - - - - - - @@ -53,9 +45,6 @@ - - - diff --git a/services-camel-app/src/test/resources/images-context.xml b/services-camel-app/src/test/resources/images-context.xml index 8acfba3584..8d86ef9f60 100644 --- a/services-camel-app/src/test/resources/images-context.xml +++ b/services-camel-app/src/test/resources/images-context.xml @@ -13,14 +13,6 @@ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> - - - - - - - - diff --git a/services-camel-app/src/test/resources/metaservices-context.xml b/services-camel-app/src/test/resources/metaservices-context.xml index 5afcb06891..a7fb4b4e2a 100644 --- a/services-camel-app/src/test/resources/metaservices-context.xml +++ b/services-camel-app/src/test/resources/metaservices-context.xml @@ -28,10 +28,6 @@ - - - - diff --git a/services-camel-app/src/test/resources/thumbnails-config.properties b/services-camel-app/src/test/resources/thumbnails-config.properties index 6a2ea9b4c3..c95155de67 100644 --- a/services-camel-app/src/test/resources/thumbnails-config.properties +++ b/services-camel-app/src/test/resources/thumbnails-config.properties @@ -1,2 +1,5 @@ -cdr.thumbnails.stream=direct:start -cdr.thumbnails.stream.camel=direct:start \ No newline at end of file +cdr.thumbnails.stream=direct:startThumbnail +cdr.thumbnails.stream.camel=direct:startThumbnail + +cdr.import.thumbnails.stream=direct:startImport +cdr.import.thumbnails.stream.camel=direct:startImport \ No newline at end of file diff --git a/services-camel-app/src/test/resources/thumbnails-context.xml b/services-camel-app/src/test/resources/thumbnails-context.xml index a8d16b021d..f7390dbcdc 100644 --- a/services-camel-app/src/test/resources/thumbnails-context.xml +++ b/services-camel-app/src/test/resources/thumbnails-context.xml @@ -11,6 +11,10 @@ + + + + diff --git a/static/css/admin/cdradmin.css b/static/css/admin/cdradmin.css index 8c62f6057d..c32a737a95 100644 --- a/static/css/admin/cdradmin.css +++ b/static/css/admin/cdradmin.css @@ -658,4 +658,52 @@ div.in-admin-iframe, #streaming_url { min-width: 400px; +} + +#chompb-projects_filter, +#vue-cdr-admin-app .dataTables_filter { + text-align: right; +} + +#chompb-projects_filter input, +#vue-cdr-admin-app .dataTables_filter input { + max-width: 250px; +} + +#chompb-preingest-ui table td a { + padding-right: 10px; + text-decoration: underline; +} + +#chompb-preingest-ui table td:last-child { + padding-right: 0; +} +#chompb-projects_wrapper .is-half, +#vue-cdr-admin-app .dataTables_wrapper .is-half { + margin: 25px auto; +} + +#chompb-projects_length label, +#vue-cdr-admin-app .dataTables_length label { + vertical-align: middle; +} + +#chompb-projects_paginate .pagination-list, +#vue-cdr-admin-app .pagination-list { + justify-content: flex-end; +} + +#vue-cdr-admin-app { + margin: 15px 20px; +} + +@media (max-width: 768px) { + #chompb-projects_filter { + text-align: left; + } + + #chompb-projects_paginate .pagination, + #chompb-projects_paginate .pagination-list { + justify-content: flex-start; + } } \ No newline at end of file diff --git a/static/css/admin/performance_visualizations.css b/static/css/admin/performance_visualizations.css deleted file mode 100644 index 13e35a98a5..0000000000 --- a/static/css/admin/performance_visualizations.css +++ /dev/null @@ -1,148 +0,0 @@ -/*! - * Bootstrap v3.3.5 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ - -/*! - * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=cbceccffe1cdf35233f54f998df5b04c) - * Config saved to config.json and https://gist.github.com/cbceccffe1cdf35233f54f998df5b04c - *//*! - * Bootstrap v3.3.6 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:hover,a:focus{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover,a.text-primary:focus{color:#286090}.text-success{color:#3c763d}a.text-success:hover,a.text-success:focus{color:#2b542c}.text-info{color:#31708f}a.text-info:hover,a.text-info:focus{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover,a.text-warning:focus{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover,a.text-danger:focus{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover,a.bg-primary:focus{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover,a.bg-info:focus{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover,a.bg-warning:focus{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover,a.bg-danger:focus{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:focus,.btn-default.focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#fff;background-color:#398439;border-color:#255625}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#337ab7;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}} - -.col-md-12 { - padding: 0; -} -#loader { - margin-top: 45px; - font-size: 4em; -} - -.dim { - opacity: 0; -} - -.axis path, -.axis line { - fill: none; - padding: 5px; - shape-rendering: crispEdges; - stroke: gray; -} - -text { - fill: gray; -} - -text.label { - font-size: 85%; -} - -div.tooltip { - position: absolute; - text-align: left; - width: 275px; - height: auto; - padding: 15px 12px 5px 12px; - fill: black; - background: rgba(0, 0, 0, 0.9); - border: 0px; - border-radius: 8px; - pointer-events: none; - line-height: 1; - font-weight: bold; - color:white; -} - -.smaller, -.smaller li { - font-weight: normal; -} - -h5.smaller { - margin-top: -5px; -} - -circle, -#throughput-date-line { - stroke: orange; - fill: none; - pointer-events: all; -} - -#throughput-date-trend-line { - pointer-events: none; -} - -#files-by-day circle, -#files-by-ingest circle, -#files-by-day-line { - stroke: #175455; -} - - -#duration-date circle, -#duration-total-date circle, -#duration-total-date-line { - stroke: #e7298a; -} - -#total-deposits-date-line { - stroke: #000; -} - -#moves-date circle, -#moves-date-line { - stroke: #0570b0; -} - -#enh-date circle, -#enh-date-line { - stroke: #238b45; -} - -#failed-enh-date circle, -#failed-deposits-date circle, -#failed-enh-date-line, -#failed-deposits-date-line{ - stroke: #de2d26; -} - -.clicked { - color: #333; - border-color: #adadad; - background-color: #e6e6e6; -} - -ul.columns { - -webkit-columns: 50px 2; /* Chrome, Safari, Opera */ - -moz-columns: 50px 2; /* Firefox */ - columns: 50px 2; -} - -.heading { - font-weight: bolder; - font-size: 14px; -} - -/* Overlay */ -.overlay { - fill: none; - stroke: none; - pointer-events: all; -} - -.focus line { - stroke: slategray; - stroke-width: 2.5; -} - -/* Brushing */ -.brush .extent { - stroke: #fff; - fill-opacity: .125; - shape-rendering: crispEdges; -} \ No newline at end of file diff --git a/static/css/sass/cdr_ui_styles.scss b/static/css/sass/cdr_ui_styles.scss index 37b01f44bf..6dc0e5c752 100644 --- a/static/css/sass/cdr_ui_styles.scss +++ b/static/css/sass/cdr_ui_styles.scss @@ -832,37 +832,6 @@ table.dataTable { color: white; } -/* UV image viewer */ -.uv { - .footer { - background-color: white; - padding: 0; - } - - .search { - a { - margin-left: 0; - } - } - - .tabs { - margin-bottom: 0; - - .tab.on { - display: inherit !important; - } - } - - .title { - color: white; - font-size: inherit; - } - - li { - text-indent: 0; - } -} - /* MODs display for work and file pages, plus modalMetadata.vue component */ #mods_data_display { margin: auto; @@ -1171,6 +1140,17 @@ iframe { margin: 25px auto; } +.clover-viewer { + margin: auto; + width: 90%; +} + +#information-toggle { + &:focus { + background-color: hsl(209, 100%, 38.2%); + } +} + /*! @creativebulma/bulma-tooltip v1.2.0 | (c) 2020 Gaetan | MIT License | https://github.com/CreativeBulma/bulma-tooltip */ [data-tooltip]:not(.is-disabled),[data-tooltip]:not(.is-loading),[data-tooltip]:not([disabled]){cursor:pointer;overflow:visible;position:relative}[data-tooltip]:not(.is-disabled):before,[data-tooltip]:not(.is-loading):before,[data-tooltip]:not([disabled]):before{background:rgba(74,74,74,.9);border-radius:2px;content:attr(data-tooltip);padding:.5rem 1rem;text-overflow:ellipsis;white-space:pre;right:auto;bottom:auto;left:50%;top:0;margin-top:-5px;margin-bottom:auto;transform:translate(-50%,-100%)}[data-tooltip]:not(.is-disabled).has-tooltip-arrow:after,[data-tooltip]:not(.is-disabled):before,[data-tooltip]:not(.is-loading).has-tooltip-arrow:after,[data-tooltip]:not(.is-loading):before,[data-tooltip]:not([disabled]).has-tooltip-arrow:after,[data-tooltip]:not([disabled]):before{box-sizing:border-box;color:#fff;display:inline-block;font-family:BlinkMacSystemFont,-apple-system,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,Helvetica,Arial,sans-serif;font-size:.75rem;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;opacity:0;overflow:hidden;pointer-events:none;position:absolute;visibility:hidden;z-index:1}[data-tooltip]:not(.is-disabled).has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-arrow:after{content:"";border-style:solid;border-width:6px;border-color:rgba(74,74,74,.9) transparent transparent;margin-bottom:-5px}[data-tooltip]:not(.is-disabled).has-tooltip-arrow.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-arrow.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-arrow.has-tooltip-arrow:after{top:0;right:auto;bottom:auto;left:50%;margin:-5px auto auto -5px;border-color:rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-bottom.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-bottom.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-bottom.has-tooltip-arrow:after{top:auto;right:auto;bottom:-1px;left:50%;margin:auto auto -5px -5px;border-color:transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-bottom:before,[data-tooltip]:not(.is-loading).has-tooltip-bottom:before,[data-tooltip]:not([disabled]).has-tooltip-bottom:before{top:auto;right:auto;bottom:0;left:50%;margin-top:auto;margin-bottom:-5px;transform:translate(-50%,100%)}[data-tooltip]:not(.is-disabled).has-tooltip-left.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-left.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-left.has-tooltip-arrow:after{top:auto;right:auto;bottom:50%;left:0;margin:auto auto -6px -5px;border-color:transparent transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-left:before,[data-tooltip]:not(.is-loading).has-tooltip-left:before,[data-tooltip]:not([disabled]).has-tooltip-left:before{top:auto;right:auto;bottom:50%;left:-5px;transform:translate(-100%,50%)}[data-tooltip]:not(.is-disabled).has-tooltip-right.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-right.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-right.has-tooltip-arrow:after{top:auto;right:0;bottom:50%;left:auto;margin:auto -6px -6px auto;border-color:transparent rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-right:before,[data-tooltip]:not(.is-loading).has-tooltip-right:before,[data-tooltip]:not([disabled]).has-tooltip-right:before{top:auto;right:-5px;bottom:50%;left:auto;margin-top:auto;transform:translate(100%,50%)}[data-tooltip]:not(.is-disabled).has-tooltip-multiline:before,[data-tooltip]:not(.is-loading).has-tooltip-multiline:before,[data-tooltip]:not([disabled]).has-tooltip-multiline:before{height:auto;width:15rem;max-width:15rem;text-overflow:clip;white-space:normal;word-break:keep-all}[data-tooltip]:not(.is-disabled).has-tooltip-text-left:before,[data-tooltip]:not(.is-loading).has-tooltip-text-left:before,[data-tooltip]:not([disabled]).has-tooltip-text-left:before{text-align:left}[data-tooltip]:not(.is-disabled).has-tooltip-text-centered:before,[data-tooltip]:not(.is-loading).has-tooltip-text-centered:before,[data-tooltip]:not([disabled]).has-tooltip-text-centered:before{text-align:center}[data-tooltip]:not(.is-disabled).has-tooltip-text-right:before,[data-tooltip]:not(.is-loading).has-tooltip-text-right:before,[data-tooltip]:not([disabled]).has-tooltip-text-right:before{text-align:right}[data-tooltip]:not(.is-disabled).has-tooltip-white:after,[data-tooltip]:not(.is-loading).has-tooltip-white:after,[data-tooltip]:not([disabled]).has-tooltip-white:after{border-color:hsla(0,0%,100%,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-white.has-tooltip-bottom:after,[data-tooltip]:not(.is-loading).has-tooltip-white.has-tooltip-bottom:after,[data-tooltip]:not([disabled]).has-tooltip-white.has-tooltip-bottom:after{border-color:transparent transparent hsla(0,0%,100%,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-white.has-tooltip-left:after,[data-tooltip]:not(.is-loading).has-tooltip-white.has-tooltip-left:after,[data-tooltip]:not([disabled]).has-tooltip-white.has-tooltip-left:after{border-color:transparent transparent transparent hsla(0,0%,100%,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-white.has-tooltip-right:after,[data-tooltip]:not(.is-loading).has-tooltip-white.has-tooltip-right:after,[data-tooltip]:not([disabled]).has-tooltip-white.has-tooltip-right:after{border-color:transparent hsla(0,0%,100%,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-white:before,[data-tooltip]:not(.is-loading).has-tooltip-white:before,[data-tooltip]:not([disabled]).has-tooltip-white:before{background-color:hsla(0,0%,100%,.9);color:#0a0a0a}[data-tooltip]:not(.is-disabled).has-tooltip-black:after,[data-tooltip]:not(.is-loading).has-tooltip-black:after,[data-tooltip]:not([disabled]).has-tooltip-black:after{border-color:hsla(0,0%,4%,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-black.has-tooltip-bottom:after,[data-tooltip]:not(.is-loading).has-tooltip-black.has-tooltip-bottom:after,[data-tooltip]:not([disabled]).has-tooltip-black.has-tooltip-bottom:after{border-color:transparent transparent hsla(0,0%,4%,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-black.has-tooltip-left:after,[data-tooltip]:not(.is-loading).has-tooltip-black.has-tooltip-left:after,[data-tooltip]:not([disabled]).has-tooltip-black.has-tooltip-left:after{border-color:transparent transparent transparent hsla(0,0%,4%,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-black.has-tooltip-right:after,[data-tooltip]:not(.is-loading).has-tooltip-black.has-tooltip-right:after,[data-tooltip]:not([disabled]).has-tooltip-black.has-tooltip-right:after{border-color:transparent hsla(0,0%,4%,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-black:before,[data-tooltip]:not(.is-loading).has-tooltip-black:before,[data-tooltip]:not([disabled]).has-tooltip-black:before{background-color:hsla(0,0%,4%,.9);color:#fff}[data-tooltip]:not(.is-disabled).has-tooltip-light:after,[data-tooltip]:not(.is-loading).has-tooltip-light:after,[data-tooltip]:not([disabled]).has-tooltip-light:after{border-color:hsla(0,0%,96%,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-light.has-tooltip-bottom:after,[data-tooltip]:not(.is-loading).has-tooltip-light.has-tooltip-bottom:after,[data-tooltip]:not([disabled]).has-tooltip-light.has-tooltip-bottom:after{border-color:transparent transparent hsla(0,0%,96%,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-light.has-tooltip-left:after,[data-tooltip]:not(.is-loading).has-tooltip-light.has-tooltip-left:after,[data-tooltip]:not([disabled]).has-tooltip-light.has-tooltip-left:after{border-color:transparent transparent transparent hsla(0,0%,96%,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-light.has-tooltip-right:after,[data-tooltip]:not(.is-loading).has-tooltip-light.has-tooltip-right:after,[data-tooltip]:not([disabled]).has-tooltip-light.has-tooltip-right:after{border-color:transparent hsla(0,0%,96%,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-light:before,[data-tooltip]:not(.is-loading).has-tooltip-light:before,[data-tooltip]:not([disabled]).has-tooltip-light:before{background-color:hsla(0,0%,96%,.9);color:rgba(0,0,0,.7)}[data-tooltip]:not(.is-disabled).has-tooltip-dark:after,[data-tooltip]:not(.is-loading).has-tooltip-dark:after,[data-tooltip]:not([disabled]).has-tooltip-dark:after{border-color:rgba(54,54,54,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-dark.has-tooltip-bottom:after,[data-tooltip]:not(.is-loading).has-tooltip-dark.has-tooltip-bottom:after,[data-tooltip]:not([disabled]).has-tooltip-dark.has-tooltip-bottom:after{border-color:transparent transparent rgba(54,54,54,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-dark.has-tooltip-left:after,[data-tooltip]:not(.is-loading).has-tooltip-dark.has-tooltip-left:after,[data-tooltip]:not([disabled]).has-tooltip-dark.has-tooltip-left:after{border-color:transparent transparent transparent rgba(54,54,54,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-dark.has-tooltip-right:after,[data-tooltip]:not(.is-loading).has-tooltip-dark.has-tooltip-right:after,[data-tooltip]:not([disabled]).has-tooltip-dark.has-tooltip-right:after{border-color:transparent rgba(54,54,54,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-dark:before,[data-tooltip]:not(.is-loading).has-tooltip-dark:before,[data-tooltip]:not([disabled]).has-tooltip-dark:before{background-color:rgba(54,54,54,.9);color:#fff}[data-tooltip]:not(.is-disabled).has-tooltip-primary:after,[data-tooltip]:not(.is-loading).has-tooltip-primary:after,[data-tooltip]:not([disabled]).has-tooltip-primary:after{border-color:rgba(0,209,178,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-primary.has-tooltip-bottom:after,[data-tooltip]:not(.is-loading).has-tooltip-primary.has-tooltip-bottom:after,[data-tooltip]:not([disabled]).has-tooltip-primary.has-tooltip-bottom:after{border-color:transparent transparent rgba(0,209,178,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-primary.has-tooltip-left:after,[data-tooltip]:not(.is-loading).has-tooltip-primary.has-tooltip-left:after,[data-tooltip]:not([disabled]).has-tooltip-primary.has-tooltip-left:after{border-color:transparent transparent transparent rgba(0,209,178,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-primary.has-tooltip-right:after,[data-tooltip]:not(.is-loading).has-tooltip-primary.has-tooltip-right:after,[data-tooltip]:not([disabled]).has-tooltip-primary.has-tooltip-right:after{border-color:transparent rgba(0,209,178,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-primary:before,[data-tooltip]:not(.is-loading).has-tooltip-primary:before,[data-tooltip]:not([disabled]).has-tooltip-primary:before{background-color:rgba(0,209,178,.9);color:#fff}[data-tooltip]:not(.is-disabled).has-tooltip-link:after,[data-tooltip]:not(.is-loading).has-tooltip-link:after,[data-tooltip]:not([disabled]).has-tooltip-link:after{border-color:rgba(50,115,220,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-link.has-tooltip-bottom:after,[data-tooltip]:not(.is-loading).has-tooltip-link.has-tooltip-bottom:after,[data-tooltip]:not([disabled]).has-tooltip-link.has-tooltip-bottom:after{border-color:transparent transparent rgba(50,115,220,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-link.has-tooltip-left:after,[data-tooltip]:not(.is-loading).has-tooltip-link.has-tooltip-left:after,[data-tooltip]:not([disabled]).has-tooltip-link.has-tooltip-left:after{border-color:transparent transparent transparent rgba(50,115,220,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-link.has-tooltip-right:after,[data-tooltip]:not(.is-loading).has-tooltip-link.has-tooltip-right:after,[data-tooltip]:not([disabled]).has-tooltip-link.has-tooltip-right:after{border-color:transparent rgba(50,115,220,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-link:before,[data-tooltip]:not(.is-loading).has-tooltip-link:before,[data-tooltip]:not([disabled]).has-tooltip-link:before{background-color:rgba(50,115,220,.9);color:#fff}[data-tooltip]:not(.is-disabled).has-tooltip-info:after,[data-tooltip]:not(.is-loading).has-tooltip-info:after,[data-tooltip]:not([disabled]).has-tooltip-info:after{border-color:rgba(50,152,220,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-info.has-tooltip-bottom:after,[data-tooltip]:not(.is-loading).has-tooltip-info.has-tooltip-bottom:after,[data-tooltip]:not([disabled]).has-tooltip-info.has-tooltip-bottom:after{border-color:transparent transparent rgba(50,152,220,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-info.has-tooltip-left:after,[data-tooltip]:not(.is-loading).has-tooltip-info.has-tooltip-left:after,[data-tooltip]:not([disabled]).has-tooltip-info.has-tooltip-left:after{border-color:transparent transparent transparent rgba(50,152,220,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-info.has-tooltip-right:after,[data-tooltip]:not(.is-loading).has-tooltip-info.has-tooltip-right:after,[data-tooltip]:not([disabled]).has-tooltip-info.has-tooltip-right:after{border-color:transparent rgba(50,152,220,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-info:before,[data-tooltip]:not(.is-loading).has-tooltip-info:before,[data-tooltip]:not([disabled]).has-tooltip-info:before{background-color:rgba(50,152,220,.9);color:#fff}[data-tooltip]:not(.is-disabled).has-tooltip-success:after,[data-tooltip]:not(.is-loading).has-tooltip-success:after,[data-tooltip]:not([disabled]).has-tooltip-success:after{border-color:rgba(72,199,116,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-success.has-tooltip-bottom:after,[data-tooltip]:not(.is-loading).has-tooltip-success.has-tooltip-bottom:after,[data-tooltip]:not([disabled]).has-tooltip-success.has-tooltip-bottom:after{border-color:transparent transparent rgba(72,199,116,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-success.has-tooltip-left:after,[data-tooltip]:not(.is-loading).has-tooltip-success.has-tooltip-left:after,[data-tooltip]:not([disabled]).has-tooltip-success.has-tooltip-left:after{border-color:transparent transparent transparent rgba(72,199,116,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-success.has-tooltip-right:after,[data-tooltip]:not(.is-loading).has-tooltip-success.has-tooltip-right:after,[data-tooltip]:not([disabled]).has-tooltip-success.has-tooltip-right:after{border-color:transparent rgba(72,199,116,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-success:before,[data-tooltip]:not(.is-loading).has-tooltip-success:before,[data-tooltip]:not([disabled]).has-tooltip-success:before{background-color:rgba(72,199,116,.9);color:#fff}[data-tooltip]:not(.is-disabled).has-tooltip-warning:after,[data-tooltip]:not(.is-loading).has-tooltip-warning:after,[data-tooltip]:not([disabled]).has-tooltip-warning:after{border-color:rgba(255,221,87,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-warning.has-tooltip-bottom:after,[data-tooltip]:not(.is-loading).has-tooltip-warning.has-tooltip-bottom:after,[data-tooltip]:not([disabled]).has-tooltip-warning.has-tooltip-bottom:after{border-color:transparent transparent rgba(255,221,87,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-warning.has-tooltip-left:after,[data-tooltip]:not(.is-loading).has-tooltip-warning.has-tooltip-left:after,[data-tooltip]:not([disabled]).has-tooltip-warning.has-tooltip-left:after{border-color:transparent transparent transparent rgba(255,221,87,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-warning.has-tooltip-right:after,[data-tooltip]:not(.is-loading).has-tooltip-warning.has-tooltip-right:after,[data-tooltip]:not([disabled]).has-tooltip-warning.has-tooltip-right:after{border-color:transparent rgba(255,221,87,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-warning:before,[data-tooltip]:not(.is-loading).has-tooltip-warning:before,[data-tooltip]:not([disabled]).has-tooltip-warning:before{background-color:rgba(255,221,87,.9);color:rgba(0,0,0,.7)}[data-tooltip]:not(.is-disabled).has-tooltip-danger:after,[data-tooltip]:not(.is-loading).has-tooltip-danger:after,[data-tooltip]:not([disabled]).has-tooltip-danger:after{border-color:rgba(241,70,104,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-danger.has-tooltip-bottom:after,[data-tooltip]:not(.is-loading).has-tooltip-danger.has-tooltip-bottom:after,[data-tooltip]:not([disabled]).has-tooltip-danger.has-tooltip-bottom:after{border-color:transparent transparent rgba(241,70,104,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-danger.has-tooltip-left:after,[data-tooltip]:not(.is-loading).has-tooltip-danger.has-tooltip-left:after,[data-tooltip]:not([disabled]).has-tooltip-danger.has-tooltip-left:after{border-color:transparent transparent transparent rgba(241,70,104,.9)!important}[data-tooltip]:not(.is-disabled).has-tooltip-danger.has-tooltip-right:after,[data-tooltip]:not(.is-loading).has-tooltip-danger.has-tooltip-right:after,[data-tooltip]:not([disabled]).has-tooltip-danger.has-tooltip-right:after{border-color:transparent rgba(241,70,104,.9) transparent transparent!important}[data-tooltip]:not(.is-disabled).has-tooltip-danger:before,[data-tooltip]:not(.is-loading).has-tooltip-danger:before,[data-tooltip]:not([disabled]).has-tooltip-danger:before{background-color:rgba(241,70,104,.9);color:#fff}[data-tooltip]:not(.is-disabled).has-tooltip-active:after,[data-tooltip]:not(.is-disabled).has-tooltip-active:before,[data-tooltip]:not(.is-disabled):hover:after,[data-tooltip]:not(.is-disabled):hover:before,[data-tooltip]:not(.is-loading).has-tooltip-active:after,[data-tooltip]:not(.is-loading).has-tooltip-active:before,[data-tooltip]:not(.is-loading):hover:after,[data-tooltip]:not(.is-loading):hover:before,[data-tooltip]:not([disabled]).has-tooltip-active:after,[data-tooltip]:not([disabled]).has-tooltip-active:before,[data-tooltip]:not([disabled]):hover:after,[data-tooltip]:not([disabled]):hover:before{opacity:1;visibility:visible}[data-tooltip]:not(.is-disabled).has-tooltip-fade:after,[data-tooltip]:not(.is-disabled).has-tooltip-fade:before,[data-tooltip]:not(.is-loading).has-tooltip-fade:after,[data-tooltip]:not(.is-loading).has-tooltip-fade:before,[data-tooltip]:not([disabled]).has-tooltip-fade:after,[data-tooltip]:not([disabled]).has-tooltip-fade:before{transition:opacity .3s linear,visibility .3s linear}@media screen and (max-width:768px){[data-tooltip]:not(.is-disabled).has-tooltip-top-mobile.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-top-mobile.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-top-mobile.has-tooltip-arrow:after{top:0;right:auto;bottom:auto;left:50%;margin:-5px auto auto -5px;border-color:rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-top-mobile:before,[data-tooltip]:not(.is-loading).has-tooltip-top-mobile:before,[data-tooltip]:not([disabled]).has-tooltip-top-mobile:before{right:auto;bottom:auto;left:50%;top:0;margin-top:-5px;margin-bottom:auto;transform:translate(-50%,-100%)}}@media print,screen and (min-width:769px){[data-tooltip]:not(.is-disabled).has-tooltip-top-tablet.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-top-tablet.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-top-tablet.has-tooltip-arrow:after{top:0;right:auto;bottom:auto;left:50%;margin:-5px auto auto -5px;border-color:rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-top-tablet:before,[data-tooltip]:not(.is-loading).has-tooltip-top-tablet:before,[data-tooltip]:not([disabled]).has-tooltip-top-tablet:before{right:auto;bottom:auto;left:50%;top:0;margin-top:-5px;margin-bottom:auto;transform:translate(-50%,-100%)}}@media screen and (min-width:769px) and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-top-tablet-only.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-top-tablet-only.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-top-tablet-only.has-tooltip-arrow:after{top:0;right:auto;bottom:auto;left:50%;margin:-5px auto auto -5px;border-color:rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-top-tablet-only:before,[data-tooltip]:not(.is-loading).has-tooltip-top-tablet-only:before,[data-tooltip]:not([disabled]).has-tooltip-top-tablet-only:before{right:auto;bottom:auto;left:50%;top:0;margin-top:-5px;margin-bottom:auto;transform:translate(-50%,-100%)}}@media screen and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-top-touch.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-top-touch.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-top-touch.has-tooltip-arrow:after{top:0;right:auto;bottom:auto;left:50%;margin:-5px auto auto -5px;border-color:rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-top-touch:before,[data-tooltip]:not(.is-loading).has-tooltip-top-touch:before,[data-tooltip]:not([disabled]).has-tooltip-top-touch:before{right:auto;bottom:auto;left:50%;top:0;margin-top:-5px;margin-bottom:auto;transform:translate(-50%,-100%)}}@media screen and (min-width:1024px){[data-tooltip]:not(.is-disabled).has-tooltip-top-desktop.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-top-desktop.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-top-desktop.has-tooltip-arrow:after{top:0;right:auto;bottom:auto;left:50%;margin:-5px auto auto -5px;border-color:rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-top-desktop:before,[data-tooltip]:not(.is-loading).has-tooltip-top-desktop:before,[data-tooltip]:not([disabled]).has-tooltip-top-desktop:before{right:auto;bottom:auto;left:50%;top:0;margin-top:-5px;margin-bottom:auto;transform:translate(-50%,-100%)}}@media screen and (min-width:1024px) and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-top-desktop-only.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-top-desktop-only.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-top-desktop-only.has-tooltip-arrow:after{top:0;right:auto;bottom:auto;left:50%;margin:-5px auto auto -5px;border-color:rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-top-desktop-only:before,[data-tooltip]:not(.is-loading).has-tooltip-top-desktop-only:before,[data-tooltip]:not([disabled]).has-tooltip-top-desktop-only:before{right:auto;bottom:auto;left:50%;top:0;margin-top:-5px;margin-bottom:auto;transform:translate(-50%,-100%)}}@media screen and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-top-until-widescreen.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-top-until-widescreen.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-top-until-widescreen.has-tooltip-arrow:after{top:0;right:auto;bottom:auto;left:50%;margin:-5px auto auto -5px;border-color:rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-top-until-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-top-until-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-top-until-widescreen:before{right:auto;bottom:auto;left:50%;top:0;margin-top:-5px;margin-bottom:auto;transform:translate(-50%,-100%)}}@media screen and (min-width:1216px){[data-tooltip]:not(.is-disabled).has-tooltip-top-widescreen.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-top-widescreen.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-top-widescreen.has-tooltip-arrow:after{top:0;right:auto;bottom:auto;left:50%;margin:-5px auto auto -5px;border-color:rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-top-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-top-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-top-widescreen:before{right:auto;bottom:auto;left:50%;top:0;margin-top:-5px;margin-bottom:auto;transform:translate(-50%,-100%)}}@media screen and (min-width:1216px) and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-top-widescreen-only.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-top-widescreen-only.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-top-widescreen-only.has-tooltip-arrow:after{top:0;right:auto;bottom:auto;left:50%;margin:-5px auto auto -5px;border-color:rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-top-widescreen-only:before,[data-tooltip]:not(.is-loading).has-tooltip-top-widescreen-only:before,[data-tooltip]:not([disabled]).has-tooltip-top-widescreen-only:before{right:auto;bottom:auto;left:50%;top:0;margin-top:-5px;margin-bottom:auto;transform:translate(-50%,-100%)}}@media screen and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-top-until-fullhd.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-top-until-fullhd.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-top-until-fullhd.has-tooltip-arrow:after{top:0;right:auto;bottom:auto;left:50%;margin:-5px auto auto -5px;border-color:rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-top-until-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-top-until-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-top-until-fullhd:before{right:auto;bottom:auto;left:50%;top:0;margin-top:-5px;margin-bottom:auto;transform:translate(-50%,-100%)}}@media screen and (min-width:1408px){[data-tooltip]:not(.is-disabled).has-tooltip-top-fullhd.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-top-fullhd.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-top-fullhd.has-tooltip-arrow:after{top:0;right:auto;bottom:auto;left:50%;margin:-5px auto auto -5px;border-color:rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-top-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-top-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-top-fullhd:before{right:auto;bottom:auto;left:50%;top:0;margin-top:-5px;margin-bottom:auto;transform:translate(-50%,-100%)}}@media screen and (max-width:768px){[data-tooltip]:not(.is-disabled).has-tooltip-right-mobile.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-right-mobile.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-right-mobile.has-tooltip-arrow:after{top:auto;right:0;bottom:50%;left:auto;margin:auto -6px -6px auto;border-color:transparent rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-right-mobile:before,[data-tooltip]:not(.is-loading).has-tooltip-right-mobile:before,[data-tooltip]:not([disabled]).has-tooltip-right-mobile:before{top:auto;right:-5px;bottom:50%;left:auto;margin-top:auto;transform:translate(100%,50%)}}@media print,screen and (min-width:769px){[data-tooltip]:not(.is-disabled).has-tooltip-right-tablet.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-right-tablet.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-right-tablet.has-tooltip-arrow:after{top:auto;right:0;bottom:50%;left:auto;margin:auto -6px -6px auto;border-color:transparent rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-right-tablet:before,[data-tooltip]:not(.is-loading).has-tooltip-right-tablet:before,[data-tooltip]:not([disabled]).has-tooltip-right-tablet:before{top:auto;right:-5px;bottom:50%;left:auto;margin-top:auto;transform:translate(100%,50%)}}@media screen and (min-width:769px) and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-right-tablet-only.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-right-tablet-only.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-right-tablet-only.has-tooltip-arrow:after{top:auto;right:0;bottom:50%;left:auto;margin:auto -6px -6px auto;border-color:transparent rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-right-tablet-only:before,[data-tooltip]:not(.is-loading).has-tooltip-right-tablet-only:before,[data-tooltip]:not([disabled]).has-tooltip-right-tablet-only:before{top:auto;right:-5px;bottom:50%;left:auto;margin-top:auto;transform:translate(100%,50%)}}@media screen and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-right-touch.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-right-touch.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-right-touch.has-tooltip-arrow:after{top:auto;right:0;bottom:50%;left:auto;margin:auto -6px -6px auto;border-color:transparent rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-right-touch:before,[data-tooltip]:not(.is-loading).has-tooltip-right-touch:before,[data-tooltip]:not([disabled]).has-tooltip-right-touch:before{top:auto;right:-5px;bottom:50%;left:auto;margin-top:auto;transform:translate(100%,50%)}}@media screen and (min-width:1024px){[data-tooltip]:not(.is-disabled).has-tooltip-right-desktop.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-right-desktop.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-right-desktop.has-tooltip-arrow:after{top:auto;right:0;bottom:50%;left:auto;margin:auto -6px -6px auto;border-color:transparent rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-right-desktop:before,[data-tooltip]:not(.is-loading).has-tooltip-right-desktop:before,[data-tooltip]:not([disabled]).has-tooltip-right-desktop:before{top:auto;right:-5px;bottom:50%;left:auto;margin-top:auto;transform:translate(100%,50%)}}@media screen and (min-width:1024px) and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-right-desktop-only.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-right-desktop-only.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-right-desktop-only.has-tooltip-arrow:after{top:auto;right:0;bottom:50%;left:auto;margin:auto -6px -6px auto;border-color:transparent rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-right-desktop-only:before,[data-tooltip]:not(.is-loading).has-tooltip-right-desktop-only:before,[data-tooltip]:not([disabled]).has-tooltip-right-desktop-only:before{top:auto;right:-5px;bottom:50%;left:auto;margin-top:auto;transform:translate(100%,50%)}}@media screen and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-right-until-widescreen.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-right-until-widescreen.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-right-until-widescreen.has-tooltip-arrow:after{top:auto;right:0;bottom:50%;left:auto;margin:auto -6px -6px auto;border-color:transparent rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-right-until-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-right-until-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-right-until-widescreen:before{top:auto;right:-5px;bottom:50%;left:auto;margin-top:auto;transform:translate(100%,50%)}}@media screen and (min-width:1216px){[data-tooltip]:not(.is-disabled).has-tooltip-right-widescreen.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-right-widescreen.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-right-widescreen.has-tooltip-arrow:after{top:auto;right:0;bottom:50%;left:auto;margin:auto -6px -6px auto;border-color:transparent rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-right-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-right-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-right-widescreen:before{top:auto;right:-5px;bottom:50%;left:auto;margin-top:auto;transform:translate(100%,50%)}}@media screen and (min-width:1216px) and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-right-widescreen-only.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-right-widescreen-only.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-right-widescreen-only.has-tooltip-arrow:after{top:auto;right:0;bottom:50%;left:auto;margin:auto -6px -6px auto;border-color:transparent rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-right-widescreen-only:before,[data-tooltip]:not(.is-loading).has-tooltip-right-widescreen-only:before,[data-tooltip]:not([disabled]).has-tooltip-right-widescreen-only:before{top:auto;right:-5px;bottom:50%;left:auto;margin-top:auto;transform:translate(100%,50%)}}@media screen and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-right-until-fullhd.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-right-until-fullhd.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-right-until-fullhd.has-tooltip-arrow:after{top:auto;right:0;bottom:50%;left:auto;margin:auto -6px -6px auto;border-color:transparent rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-right-until-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-right-until-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-right-until-fullhd:before{top:auto;right:-5px;bottom:50%;left:auto;margin-top:auto;transform:translate(100%,50%)}}@media screen and (min-width:1408px){[data-tooltip]:not(.is-disabled).has-tooltip-right-fullhd.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-right-fullhd.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-right-fullhd.has-tooltip-arrow:after{top:auto;right:0;bottom:50%;left:auto;margin:auto -6px -6px auto;border-color:transparent rgba(74,74,74,.9) transparent transparent}[data-tooltip]:not(.is-disabled).has-tooltip-right-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-right-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-right-fullhd:before{top:auto;right:-5px;bottom:50%;left:auto;margin-top:auto;transform:translate(100%,50%)}}@media screen and (max-width:768px){[data-tooltip]:not(.is-disabled).has-tooltip-bottom-mobile.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-bottom-mobile.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-bottom-mobile.has-tooltip-arrow:after{top:auto;right:auto;bottom:-1px;left:50%;margin:auto auto -5px -5px;border-color:transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-bottom-mobile:before,[data-tooltip]:not(.is-loading).has-tooltip-bottom-mobile:before,[data-tooltip]:not([disabled]).has-tooltip-bottom-mobile:before{top:auto;right:auto;bottom:0;left:50%;margin-top:auto;margin-bottom:-5px;transform:translate(-50%,100%)}}@media print,screen and (min-width:769px){[data-tooltip]:not(.is-disabled).has-tooltip-bottom-tablet.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-bottom-tablet.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-bottom-tablet.has-tooltip-arrow:after{top:auto;right:auto;bottom:-1px;left:50%;margin:auto auto -5px -5px;border-color:transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-bottom-tablet:before,[data-tooltip]:not(.is-loading).has-tooltip-bottom-tablet:before,[data-tooltip]:not([disabled]).has-tooltip-bottom-tablet:before{top:auto;right:auto;bottom:0;left:50%;margin-top:auto;margin-bottom:-5px;transform:translate(-50%,100%)}}@media screen and (min-width:769px) and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-bottom-tablet-only.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-bottom-tablet-only.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-bottom-tablet-only.has-tooltip-arrow:after{top:auto;right:auto;bottom:-1px;left:50%;margin:auto auto -5px -5px;border-color:transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-bottom-tablet-only:before,[data-tooltip]:not(.is-loading).has-tooltip-bottom-tablet-only:before,[data-tooltip]:not([disabled]).has-tooltip-bottom-tablet-only:before{top:auto;right:auto;bottom:0;left:50%;margin-top:auto;margin-bottom:-5px;transform:translate(-50%,100%)}}@media screen and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-bottom-touch.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-bottom-touch.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-bottom-touch.has-tooltip-arrow:after{top:auto;right:auto;bottom:-1px;left:50%;margin:auto auto -5px -5px;border-color:transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-bottom-touch:before,[data-tooltip]:not(.is-loading).has-tooltip-bottom-touch:before,[data-tooltip]:not([disabled]).has-tooltip-bottom-touch:before{top:auto;right:auto;bottom:0;left:50%;margin-top:auto;margin-bottom:-5px;transform:translate(-50%,100%)}}@media screen and (min-width:1024px){[data-tooltip]:not(.is-disabled).has-tooltip-bottom-desktop.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-bottom-desktop.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-bottom-desktop.has-tooltip-arrow:after{top:auto;right:auto;bottom:-1px;left:50%;margin:auto auto -5px -5px;border-color:transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-bottom-desktop:before,[data-tooltip]:not(.is-loading).has-tooltip-bottom-desktop:before,[data-tooltip]:not([disabled]).has-tooltip-bottom-desktop:before{top:auto;right:auto;bottom:0;left:50%;margin-top:auto;margin-bottom:-5px;transform:translate(-50%,100%)}}@media screen and (min-width:1024px) and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-bottom-desktop-only.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-bottom-desktop-only.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-bottom-desktop-only.has-tooltip-arrow:after{top:auto;right:auto;bottom:-1px;left:50%;margin:auto auto -5px -5px;border-color:transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-bottom-desktop-only:before,[data-tooltip]:not(.is-loading).has-tooltip-bottom-desktop-only:before,[data-tooltip]:not([disabled]).has-tooltip-bottom-desktop-only:before{top:auto;right:auto;bottom:0;left:50%;margin-top:auto;margin-bottom:-5px;transform:translate(-50%,100%)}}@media screen and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-bottom-until-widescreen.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-bottom-until-widescreen.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-bottom-until-widescreen.has-tooltip-arrow:after{top:auto;right:auto;bottom:-1px;left:50%;margin:auto auto -5px -5px;border-color:transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-bottom-until-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-bottom-until-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-bottom-until-widescreen:before{top:auto;right:auto;bottom:0;left:50%;margin-top:auto;margin-bottom:-5px;transform:translate(-50%,100%)}}@media screen and (min-width:1216px){[data-tooltip]:not(.is-disabled).has-tooltip-bottom-widescreen.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-bottom-widescreen.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-bottom-widescreen.has-tooltip-arrow:after{top:auto;right:auto;bottom:-1px;left:50%;margin:auto auto -5px -5px;border-color:transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-bottom-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-bottom-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-bottom-widescreen:before{top:auto;right:auto;bottom:0;left:50%;margin-top:auto;margin-bottom:-5px;transform:translate(-50%,100%)}}@media screen and (min-width:1216px) and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-bottom-widescreen-only.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-bottom-widescreen-only.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-bottom-widescreen-only.has-tooltip-arrow:after{top:auto;right:auto;bottom:-1px;left:50%;margin:auto auto -5px -5px;border-color:transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-bottom-widescreen-only:before,[data-tooltip]:not(.is-loading).has-tooltip-bottom-widescreen-only:before,[data-tooltip]:not([disabled]).has-tooltip-bottom-widescreen-only:before{top:auto;right:auto;bottom:0;left:50%;margin-top:auto;margin-bottom:-5px;transform:translate(-50%,100%)}}@media screen and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-bottom-until-fullhd.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-bottom-until-fullhd.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-bottom-until-fullhd.has-tooltip-arrow:after{top:auto;right:auto;bottom:-1px;left:50%;margin:auto auto -5px -5px;border-color:transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-bottom-until-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-bottom-until-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-bottom-until-fullhd:before{top:auto;right:auto;bottom:0;left:50%;margin-top:auto;margin-bottom:-5px;transform:translate(-50%,100%)}}@media screen and (min-width:1408px){[data-tooltip]:not(.is-disabled).has-tooltip-bottom-fullhd.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-bottom-fullhd.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-bottom-fullhd.has-tooltip-arrow:after{top:auto;right:auto;bottom:-1px;left:50%;margin:auto auto -5px -5px;border-color:transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-bottom-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-bottom-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-bottom-fullhd:before{top:auto;right:auto;bottom:0;left:50%;margin-top:auto;margin-bottom:-5px;transform:translate(-50%,100%)}}@media screen and (max-width:768px){[data-tooltip]:not(.is-disabled).has-tooltip-left-mobile.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-left-mobile.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-left-mobile.has-tooltip-arrow:after{top:auto;right:auto;bottom:50%;left:0;margin:auto auto -6px -5px;border-color:transparent transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-left-mobile:before,[data-tooltip]:not(.is-loading).has-tooltip-left-mobile:before,[data-tooltip]:not([disabled]).has-tooltip-left-mobile:before{top:auto;right:auto;bottom:50%;left:-5px;transform:translate(-100%,50%)}}@media print,screen and (min-width:769px){[data-tooltip]:not(.is-disabled).has-tooltip-left-tablet.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-left-tablet.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-left-tablet.has-tooltip-arrow:after{top:auto;right:auto;bottom:50%;left:0;margin:auto auto -6px -5px;border-color:transparent transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-left-tablet:before,[data-tooltip]:not(.is-loading).has-tooltip-left-tablet:before,[data-tooltip]:not([disabled]).has-tooltip-left-tablet:before{top:auto;right:auto;bottom:50%;left:-5px;transform:translate(-100%,50%)}}@media screen and (min-width:769px) and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-left-tablet-only.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-left-tablet-only.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-left-tablet-only.has-tooltip-arrow:after{top:auto;right:auto;bottom:50%;left:0;margin:auto auto -6px -5px;border-color:transparent transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-left-tablet-only:before,[data-tooltip]:not(.is-loading).has-tooltip-left-tablet-only:before,[data-tooltip]:not([disabled]).has-tooltip-left-tablet-only:before{top:auto;right:auto;bottom:50%;left:-5px;transform:translate(-100%,50%)}}@media screen and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-left-touch.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-left-touch.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-left-touch.has-tooltip-arrow:after{top:auto;right:auto;bottom:50%;left:0;margin:auto auto -6px -5px;border-color:transparent transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-left-touch:before,[data-tooltip]:not(.is-loading).has-tooltip-left-touch:before,[data-tooltip]:not([disabled]).has-tooltip-left-touch:before{top:auto;right:auto;bottom:50%;left:-5px;transform:translate(-100%,50%)}}@media screen and (min-width:1024px){[data-tooltip]:not(.is-disabled).has-tooltip-left-desktop.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-left-desktop.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-left-desktop.has-tooltip-arrow:after{top:auto;right:auto;bottom:50%;left:0;margin:auto auto -6px -5px;border-color:transparent transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-left-desktop:before,[data-tooltip]:not(.is-loading).has-tooltip-left-desktop:before,[data-tooltip]:not([disabled]).has-tooltip-left-desktop:before{top:auto;right:auto;bottom:50%;left:-5px;transform:translate(-100%,50%)}}@media screen and (min-width:1024px) and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-left-desktop-only.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-left-desktop-only.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-left-desktop-only.has-tooltip-arrow:after{top:auto;right:auto;bottom:50%;left:0;margin:auto auto -6px -5px;border-color:transparent transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-left-desktop-only:before,[data-tooltip]:not(.is-loading).has-tooltip-left-desktop-only:before,[data-tooltip]:not([disabled]).has-tooltip-left-desktop-only:before{top:auto;right:auto;bottom:50%;left:-5px;transform:translate(-100%,50%)}}@media screen and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-left-until-widescreen.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-left-until-widescreen.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-left-until-widescreen.has-tooltip-arrow:after{top:auto;right:auto;bottom:50%;left:0;margin:auto auto -6px -5px;border-color:transparent transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-left-until-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-left-until-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-left-until-widescreen:before{top:auto;right:auto;bottom:50%;left:-5px;transform:translate(-100%,50%)}}@media screen and (min-width:1216px){[data-tooltip]:not(.is-disabled).has-tooltip-left-widescreen.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-left-widescreen.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-left-widescreen.has-tooltip-arrow:after{top:auto;right:auto;bottom:50%;left:0;margin:auto auto -6px -5px;border-color:transparent transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-left-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-left-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-left-widescreen:before{top:auto;right:auto;bottom:50%;left:-5px;transform:translate(-100%,50%)}}@media screen and (min-width:1216px) and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-left-widescreen-only.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-left-widescreen-only.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-left-widescreen-only.has-tooltip-arrow:after{top:auto;right:auto;bottom:50%;left:0;margin:auto auto -6px -5px;border-color:transparent transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-left-widescreen-only:before,[data-tooltip]:not(.is-loading).has-tooltip-left-widescreen-only:before,[data-tooltip]:not([disabled]).has-tooltip-left-widescreen-only:before{top:auto;right:auto;bottom:50%;left:-5px;transform:translate(-100%,50%)}}@media screen and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-left-until-fullhd.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-left-until-fullhd.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-left-until-fullhd.has-tooltip-arrow:after{top:auto;right:auto;bottom:50%;left:0;margin:auto auto -6px -5px;border-color:transparent transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-left-until-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-left-until-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-left-until-fullhd:before{top:auto;right:auto;bottom:50%;left:-5px;transform:translate(-100%,50%)}}@media screen and (min-width:1408px){[data-tooltip]:not(.is-disabled).has-tooltip-left-fullhd.has-tooltip-arrow:after,[data-tooltip]:not(.is-loading).has-tooltip-left-fullhd.has-tooltip-arrow:after,[data-tooltip]:not([disabled]).has-tooltip-left-fullhd.has-tooltip-arrow:after{top:auto;right:auto;bottom:50%;left:0;margin:auto auto -6px -5px;border-color:transparent transparent transparent rgba(74,74,74,.9)}[data-tooltip]:not(.is-disabled).has-tooltip-left-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-left-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-left-fullhd:before{top:auto;right:auto;bottom:50%;left:-5px;transform:translate(-100%,50%)}}@media screen and (max-width:768px){[data-tooltip]:not(.is-disabled).has-tooltip-hidden-mobile:after,[data-tooltip]:not(.is-disabled).has-tooltip-hidden-mobile:before,[data-tooltip]:not(.is-loading).has-tooltip-hidden-mobile:after,[data-tooltip]:not(.is-loading).has-tooltip-hidden-mobile:before,[data-tooltip]:not([disabled]).has-tooltip-hidden-mobile:after,[data-tooltip]:not([disabled]).has-tooltip-hidden-mobile:before{opacity:0!important;display:none!important}}@media print,screen and (min-width:769px){[data-tooltip]:not(.is-disabled).has-tooltip-hidden-tablet:after,[data-tooltip]:not(.is-disabled).has-tooltip-hidden-tablet:before,[data-tooltip]:not(.is-loading).has-tooltip-hidden-tablet:after,[data-tooltip]:not(.is-loading).has-tooltip-hidden-tablet:before,[data-tooltip]:not([disabled]).has-tooltip-hidden-tablet:after,[data-tooltip]:not([disabled]).has-tooltip-hidden-tablet:before{opacity:0!important;display:none!important}}@media screen and (min-width:769px) and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-hidden-tablet-only:after,[data-tooltip]:not(.is-disabled).has-tooltip-hidden-tablet-only:before,[data-tooltip]:not(.is-loading).has-tooltip-hidden-tablet-only:after,[data-tooltip]:not(.is-loading).has-tooltip-hidden-tablet-only:before,[data-tooltip]:not([disabled]).has-tooltip-hidden-tablet-only:after,[data-tooltip]:not([disabled]).has-tooltip-hidden-tablet-only:before{opacity:0!important;display:none!important}}@media screen and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-hidden-touch:after,[data-tooltip]:not(.is-disabled).has-tooltip-hidden-touch:before,[data-tooltip]:not(.is-loading).has-tooltip-hidden-touch:after,[data-tooltip]:not(.is-loading).has-tooltip-hidden-touch:before,[data-tooltip]:not([disabled]).has-tooltip-hidden-touch:after,[data-tooltip]:not([disabled]).has-tooltip-hidden-touch:before{opacity:0!important;display:none!important}}@media screen and (min-width:1024px){[data-tooltip]:not(.is-disabled).has-tooltip-hidden-desktop:after,[data-tooltip]:not(.is-disabled).has-tooltip-hidden-desktop:before,[data-tooltip]:not(.is-loading).has-tooltip-hidden-desktop:after,[data-tooltip]:not(.is-loading).has-tooltip-hidden-desktop:before,[data-tooltip]:not([disabled]).has-tooltip-hidden-desktop:after,[data-tooltip]:not([disabled]).has-tooltip-hidden-desktop:before{opacity:0!important;display:none!important}}@media screen and (min-width:1024px) and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-hidden-desktop-only:after,[data-tooltip]:not(.is-disabled).has-tooltip-hidden-desktop-only:before,[data-tooltip]:not(.is-loading).has-tooltip-hidden-desktop-only:after,[data-tooltip]:not(.is-loading).has-tooltip-hidden-desktop-only:before,[data-tooltip]:not([disabled]).has-tooltip-hidden-desktop-only:after,[data-tooltip]:not([disabled]).has-tooltip-hidden-desktop-only:before{opacity:0!important;display:none!important}}@media screen and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-hidden-until-widescreen:after,[data-tooltip]:not(.is-disabled).has-tooltip-hidden-until-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-hidden-until-widescreen:after,[data-tooltip]:not(.is-loading).has-tooltip-hidden-until-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-hidden-until-widescreen:after,[data-tooltip]:not([disabled]).has-tooltip-hidden-until-widescreen:before{opacity:0!important;display:none!important}}@media screen and (min-width:1216px){[data-tooltip]:not(.is-disabled).has-tooltip-hidden-widescreen:after,[data-tooltip]:not(.is-disabled).has-tooltip-hidden-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-hidden-widescreen:after,[data-tooltip]:not(.is-loading).has-tooltip-hidden-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-hidden-widescreen:after,[data-tooltip]:not([disabled]).has-tooltip-hidden-widescreen:before{opacity:0!important;display:none!important}}@media screen and (min-width:1216px) and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-hidden-widescreen-only:after,[data-tooltip]:not(.is-disabled).has-tooltip-hidden-widescreen-only:before,[data-tooltip]:not(.is-loading).has-tooltip-hidden-widescreen-only:after,[data-tooltip]:not(.is-loading).has-tooltip-hidden-widescreen-only:before,[data-tooltip]:not([disabled]).has-tooltip-hidden-widescreen-only:after,[data-tooltip]:not([disabled]).has-tooltip-hidden-widescreen-only:before{opacity:0!important;display:none!important}}@media screen and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-hidden-until-fullhd:after,[data-tooltip]:not(.is-disabled).has-tooltip-hidden-until-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-hidden-until-fullhd:after,[data-tooltip]:not(.is-loading).has-tooltip-hidden-until-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-hidden-until-fullhd:after,[data-tooltip]:not([disabled]).has-tooltip-hidden-until-fullhd:before{opacity:0!important;display:none!important}}@media screen and (min-width:1408px){[data-tooltip]:not(.is-disabled).has-tooltip-hidden-fullhd:after,[data-tooltip]:not(.is-disabled).has-tooltip-hidden-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-hidden-fullhd:after,[data-tooltip]:not(.is-loading).has-tooltip-hidden-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-hidden-fullhd:after,[data-tooltip]:not([disabled]).has-tooltip-hidden-fullhd:before{opacity:0!important;display:none!important}}@media screen and (max-width:768px){[data-tooltip]:not(.is-disabled).has-tooltip-text-left-mobile:before,[data-tooltip]:not(.is-loading).has-tooltip-text-left-mobile:before,[data-tooltip]:not([disabled]).has-tooltip-text-left-mobile:before{text-align:left}}@media print,screen and (min-width:769px){[data-tooltip]:not(.is-disabled).has-tooltip-text-left-tablet:before,[data-tooltip]:not(.is-loading).has-tooltip-text-left-tablet:before,[data-tooltip]:not([disabled]).has-tooltip-text-left-tablet:before{text-align:left}}@media screen and (min-width:769px) and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-text-left-tablet-only:before,[data-tooltip]:not(.is-loading).has-tooltip-text-left-tablet-only:before,[data-tooltip]:not([disabled]).has-tooltip-text-left-tablet-only:before{text-align:left}}@media screen and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-text-left-touch:before,[data-tooltip]:not(.is-loading).has-tooltip-text-left-touch:before,[data-tooltip]:not([disabled]).has-tooltip-text-left-touch:before{text-align:left}}@media screen and (min-width:1024px){[data-tooltip]:not(.is-disabled).has-tooltip-text-left-desktop:before,[data-tooltip]:not(.is-loading).has-tooltip-text-left-desktop:before,[data-tooltip]:not([disabled]).has-tooltip-text-left-desktop:before{text-align:left}}@media screen and (min-width:1024px) and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-text-left-desktop-only:before,[data-tooltip]:not(.is-loading).has-tooltip-text-left-desktop-only:before,[data-tooltip]:not([disabled]).has-tooltip-text-left-desktop-only:before{text-align:left}}@media screen and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-text-left-until-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-text-left-until-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-text-left-until-widescreen:before{text-align:left}}@media screen and (min-width:1216px){[data-tooltip]:not(.is-disabled).has-tooltip-text-left-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-text-left-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-text-left-widescreen:before{text-align:left}}@media screen and (min-width:1216px) and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-text-left-widescreen-only:before,[data-tooltip]:not(.is-loading).has-tooltip-text-left-widescreen-only:before,[data-tooltip]:not([disabled]).has-tooltip-text-left-widescreen-only:before{text-align:left}}@media screen and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-text-left-until-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-text-left-until-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-text-left-until-fullhd:before{text-align:left}}@media screen and (min-width:1408px){[data-tooltip]:not(.is-disabled).has-tooltip-text-left-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-text-left-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-text-left-fullhd:before{text-align:left}}@media screen and (max-width:768px){[data-tooltip]:not(.is-disabled).has-tooltip-text-centered-mobile:before,[data-tooltip]:not(.is-loading).has-tooltip-text-centered-mobile:before,[data-tooltip]:not([disabled]).has-tooltip-text-centered-mobile:before{text-align:center}}@media print,screen and (min-width:769px){[data-tooltip]:not(.is-disabled).has-tooltip-text-centered-tablet:before,[data-tooltip]:not(.is-loading).has-tooltip-text-centered-tablet:before,[data-tooltip]:not([disabled]).has-tooltip-text-centered-tablet:before{text-align:center}}@media screen and (min-width:769px) and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-text-centered-tablet-only:before,[data-tooltip]:not(.is-loading).has-tooltip-text-centered-tablet-only:before,[data-tooltip]:not([disabled]).has-tooltip-text-centered-tablet-only:before{text-align:center}}@media screen and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-text-centered-touch:before,[data-tooltip]:not(.is-loading).has-tooltip-text-centered-touch:before,[data-tooltip]:not([disabled]).has-tooltip-text-centered-touch:before{text-align:center}}@media screen and (min-width:1024px){[data-tooltip]:not(.is-disabled).has-tooltip-text-centered-desktop:before,[data-tooltip]:not(.is-loading).has-tooltip-text-centered-desktop:before,[data-tooltip]:not([disabled]).has-tooltip-text-centered-desktop:before{text-align:center}}@media screen and (min-width:1024px) and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-text-centered-desktop-only:before,[data-tooltip]:not(.is-loading).has-tooltip-text-centered-desktop-only:before,[data-tooltip]:not([disabled]).has-tooltip-text-centered-desktop-only:before{text-align:center}}@media screen and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-text-centered-until-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-text-centered-until-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-text-centered-until-widescreen:before{text-align:center}}@media screen and (min-width:1216px){[data-tooltip]:not(.is-disabled).has-tooltip-text-centered-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-text-centered-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-text-centered-widescreen:before{text-align:center}}@media screen and (min-width:1216px) and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-text-centered-widescreen-only:before,[data-tooltip]:not(.is-loading).has-tooltip-text-centered-widescreen-only:before,[data-tooltip]:not([disabled]).has-tooltip-text-centered-widescreen-only:before{text-align:center}}@media screen and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-text-centered-until-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-text-centered-until-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-text-centered-until-fullhd:before{text-align:center}}@media screen and (min-width:1408px){[data-tooltip]:not(.is-disabled).has-tooltip-text-centered-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-text-centered-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-text-centered-fullhd:before{text-align:center}}@media screen and (max-width:768px){[data-tooltip]:not(.is-disabled).has-tooltip-text-right-mobile:before,[data-tooltip]:not(.is-loading).has-tooltip-text-right-mobile:before,[data-tooltip]:not([disabled]).has-tooltip-text-right-mobile:before{text-align:right}}@media print,screen and (min-width:769px){[data-tooltip]:not(.is-disabled).has-tooltip-text-right-tablet:before,[data-tooltip]:not(.is-loading).has-tooltip-text-right-tablet:before,[data-tooltip]:not([disabled]).has-tooltip-text-right-tablet:before{text-align:right}}@media screen and (min-width:769px) and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-text-right-tablet-only:before,[data-tooltip]:not(.is-loading).has-tooltip-text-right-tablet-only:before,[data-tooltip]:not([disabled]).has-tooltip-text-right-tablet-only:before{text-align:right}}@media screen and (max-width:1023px){[data-tooltip]:not(.is-disabled).has-tooltip-text-right-touch:before,[data-tooltip]:not(.is-loading).has-tooltip-text-right-touch:before,[data-tooltip]:not([disabled]).has-tooltip-text-right-touch:before{text-align:right}}@media screen and (min-width:1024px){[data-tooltip]:not(.is-disabled).has-tooltip-text-right-desktop:before,[data-tooltip]:not(.is-loading).has-tooltip-text-right-desktop:before,[data-tooltip]:not([disabled]).has-tooltip-text-right-desktop:before{text-align:right}}@media screen and (min-width:1024px) and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-text-right-desktop-only:before,[data-tooltip]:not(.is-loading).has-tooltip-text-right-desktop-only:before,[data-tooltip]:not([disabled]).has-tooltip-text-right-desktop-only:before{text-align:right}}@media screen and (max-width:1215px){[data-tooltip]:not(.is-disabled).has-tooltip-text-right-until-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-text-right-until-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-text-right-until-widescreen:before{text-align:right}}@media screen and (min-width:1216px){[data-tooltip]:not(.is-disabled).has-tooltip-text-right-widescreen:before,[data-tooltip]:not(.is-loading).has-tooltip-text-right-widescreen:before,[data-tooltip]:not([disabled]).has-tooltip-text-right-widescreen:before{text-align:right}}@media screen and (min-width:1216px) and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-text-right-widescreen-only:before,[data-tooltip]:not(.is-loading).has-tooltip-text-right-widescreen-only:before,[data-tooltip]:not([disabled]).has-tooltip-text-right-widescreen-only:before{text-align:right}}@media screen and (max-width:1407px){[data-tooltip]:not(.is-disabled).has-tooltip-text-right-until-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-text-right-until-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-text-right-until-fullhd:before{text-align:right}}@media screen and (min-width:1408px){[data-tooltip]:not(.is-disabled).has-tooltip-text-right-fullhd:before,[data-tooltip]:not(.is-loading).has-tooltip-text-right-fullhd:before,[data-tooltip]:not([disabled]).has-tooltip-text-right-fullhd:before{text-align:right}}span[data-tooltip]{border-bottom:1px dashed #dbdbdb}span[data-tooltip].has-tooltip-white{border-bottom-color:#fff}span[data-tooltip].has-tooltip-black{border-bottom-color:#171717}span[data-tooltip].has-tooltip-light{border-bottom-color:#fff}span[data-tooltip].has-tooltip-dark{border-bottom-color:#424242}span[data-tooltip].has-tooltip-primary{border-bottom-color:#00ebc7}span[data-tooltip].has-tooltip-link{border-bottom-color:#4882e0}span[data-tooltip].has-tooltip-info{border-bottom-color:#48a3e0}span[data-tooltip].has-tooltip-success{border-bottom-color:#5bcd83}span[data-tooltip].has-tooltip-warning{border-bottom-color:#ffe270}span[data-tooltip].has-tooltip-danger{border-bottom-color:#f35e7c}.control span[data-tooltip]{border-bottom:none} diff --git a/static/js/admin/src/action/RunEnhancementsBatchAction.js b/static/js/admin/src/action/RunEnhancementsBatchAction.js index 73fd29d075..9140bcdcc6 100644 --- a/static/js/admin/src/action/RunEnhancementsBatchAction.js +++ b/static/js/admin/src/action/RunEnhancementsBatchAction.js @@ -30,8 +30,12 @@ define('RunEnhancementsBatchAction', [ 'jquery', 'AbstractBatchAction', "tpl!../ } else { title = "Run enhancements on " + this.targets.length + " objects"; } - - var form = runEnhancementsTemplate(); + + var targetIds = ""; + for (var index in this.targets) { + targetIds += this.targets[index].getPid() + "\n"; + } + var form = runEnhancementsTemplate({ targetIds : targetIds }); this.dialog = $("
" + form + "
"); this.dialog.dialog({ autoOpen: true, @@ -44,12 +48,11 @@ define('RunEnhancementsBatchAction', [ 'jquery', 'AbstractBatchAction', "tpl!../ this.$form.submit(function(e){ var force = document.getElementById('run_enhancements_force').checked; + var recursive = document.getElementById('run_enhancements_recursive').checked; + var targetIdsString = document.getElementById('run_enhancements_ids').value; + + var pids = targetIdsString.split("\n").map((id) => id.trim()).filter((id) => id.length > 0); - var pids = []; - for (var index in self.targets) { - pids.push(self.targets[index].getPid()); - } - $.ajax({ url : "/services/api/runEnhancements", type : "POST", @@ -57,11 +60,12 @@ define('RunEnhancementsBatchAction', [ 'jquery', 'AbstractBatchAction', "tpl!../ dataType: "json", data : JSON.stringify({ force : force, - pids : pids + pids : pids, + recursive : recursive }) }).done(function(response) { self.context.view.$alertHandler.alertHandler("message", response.message); - self.dialog.remove(); + self.dialog.dialog("destroy"); }).fail(function() { self.context.view.$alertHandler.alertHandler("error", "Failed to run enhancements for " + self.targets.length + " objects"); }); diff --git a/static/js/admin/vue-permissions-editor/.browserslistrc b/static/js/admin/vue-cdr-admin/.browserslistrc similarity index 100% rename from static/js/admin/vue-permissions-editor/.browserslistrc rename to static/js/admin/vue-cdr-admin/.browserslistrc diff --git a/static/js/admin/vue-permissions-editor/.gitignore b/static/js/admin/vue-cdr-admin/.gitignore similarity index 100% rename from static/js/admin/vue-permissions-editor/.gitignore rename to static/js/admin/vue-cdr-admin/.gitignore diff --git a/static/js/admin/vue-permissions-editor/babel.config.js b/static/js/admin/vue-cdr-admin/babel.config.js similarity index 100% rename from static/js/admin/vue-permissions-editor/babel.config.js rename to static/js/admin/vue-cdr-admin/babel.config.js diff --git a/static/js/admin/vue-permissions-editor/index.html b/static/js/admin/vue-cdr-admin/index.html similarity index 100% rename from static/js/admin/vue-permissions-editor/index.html rename to static/js/admin/vue-cdr-admin/index.html diff --git a/static/js/admin/vue-permissions-editor/jest.config.js b/static/js/admin/vue-cdr-admin/jest.config.js similarity index 100% rename from static/js/admin/vue-permissions-editor/jest.config.js rename to static/js/admin/vue-cdr-admin/jest.config.js diff --git a/static/js/admin/vue-permissions-editor/package-lock.json b/static/js/admin/vue-cdr-admin/package-lock.json similarity index 87% rename from static/js/admin/vue-permissions-editor/package-lock.json rename to static/js/admin/vue-cdr-admin/package-lock.json index 3c150e22dd..0c0694a4c7 100644 --- a/static/js/admin/vue-permissions-editor/package-lock.json +++ b/static/js/admin/vue-cdr-admin/package-lock.json @@ -8,56 +8,61 @@ "name": "vue-permissions-editor", "version": "0.1.0", "dependencies": { - "axios": "^1.6.4", - "date-fns": "^3.0.6", + "axios": "^1.7.7", + "datatables.net": "^2.1.6", + "datatables.net-bm": "^2.1.6", + "datatables.net-searchpanes-bm": "^2.3.2", + "datatables.net-select-bm": "^2.1.0", + "datatables.net-vue3": "^3.0.2", + "date-fns": "^3.6.0", "lodash.clonedeep": "^4.5.0", "lodash.findindex": "^4.6.0", "lodash.isempty": "^4.4.0", - "pinia": "^2.1.7", - "vue": "^3.4.5", - "vue-router": "^4.2.5" + "pinia": "^2.2.2", + "vue": "^3.5.6", + "vue-router": "^4.4.5" }, "devDependencies": { - "@babel/plugin-transform-runtime": "^7.23.7", - "@babel/preset-env": "^7.23.7", - "@pinia/testing": "0.1.3", - "@testing-library/jest-dom": "^6.2.0", + "@babel/plugin-transform-runtime": "^7.24.7", + "@babel/preset-env": "^7.25.3", + "@pinia/testing": "0.1.5", + "@testing-library/jest-dom": "^6.4.8", "@vitejs/plugin-vue": "^4.6.2", - "@vue/compiler-sfc": "^3.4.5", - "@vue/test-utils": "2.4.3", + "@vue/compiler-sfc": "^3.5.6", + "@vue/test-utils": "2.4.6", "@vue/vue3-jest": "^29.2.6", "babel-jest": "^29.7.0", - "caniuse-lite": "^1.0.30001574", + "caniuse-lite": "^1.0.30001651", "jest": "29.7.0", "jest-environment-jsdom": "^29.7.0", "moxios": "^0.4.0", - "sass": "^1.69.7", - "vite": "4.5.3" + "sass": "^1.77.8", + "vite": "4.5.5" } }, "node_modules/@adobe/css-tools": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.2.tgz", - "integrity": "sha512-DA5a1C0gD/pLOvhv33YMrbf2FK3oUzwNl9oOJqE4XVjuEtt6XIakRcsd7eLiOSPkp1kTRQGICTA8cKra/vFbjw==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", "dev": true }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", + "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -94,14 +99,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", + "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", "dev": true, "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.25.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -109,38 +114,39 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", - "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", "dev": true, "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -164,19 +170,17 @@ "dev": true }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.7.tgz", - "integrity": "sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.0.tgz", + "integrity": "sha512-GYM6BxeQsETc9mnct+nIIpf63SAyzvyYN7UB/IlTyd+MBg06afFGp0mIeUqGyWgS2mxad6vqbMrHVlaL3m70sQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/traverse": "^7.25.0", "semver": "^6.3.1" }, "engines": { @@ -187,12 +191,12 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", - "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", + "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-annotate-as-pure": "^7.24.7", "regexpu-core": "^5.3.1", "semver": "^6.3.1" }, @@ -204,9 +208,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz", - "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", @@ -219,75 +223,42 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", "dev": true, "dependencies": { - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dev": true, "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" }, "engines": { "node": ">=6.9.0" @@ -297,35 +268,35 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", - "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", + "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-wrap-function": "^7.22.20" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-wrap-function": "^7.25.0", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -335,14 +306,14 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", + "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5" + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -352,77 +323,65 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true, + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", - "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", + "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", "dev": true, "dependencies": { - "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.15", - "@babel/types": "^7.22.19" + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -443,23 +402,27 @@ } }, "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", - "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", + "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", + "dependencies": { + "@babel/types": "^7.25.2" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -467,13 +430,44 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", + "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", + "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", - "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", + "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -483,14 +477,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", - "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.23.3" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -500,13 +494,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", - "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", + "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -603,12 +597,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", - "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", + "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -618,12 +612,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", - "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -805,12 +799,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", - "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -820,15 +814,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.7.tgz", - "integrity": "sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.0.tgz", + "integrity": "sha512-uaIi2FdqzjpAMvVqvB51S42oC2JEVgh0LDsGfZVDysWE8LrJtQC2jvKmOqEYThKyB7bDEb7BP1GYWDm7tABA0Q==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.20", - "@babel/plugin-syntax-async-generators": "^7.8.4" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -838,14 +832,14 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", - "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.20" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -855,12 +849,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", - "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -870,12 +864,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", - "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", + "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -885,13 +879,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", - "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", + "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -901,13 +895,13 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", - "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { @@ -918,19 +912,16 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.5.tgz", - "integrity": "sha512-jvOTR4nicqYC9yzOHIhXG5emiFEOpappSJAl73SDSEDcybD+Puuze8Tnpb9p9qEyYup24tq891gkaygIFvWDqg==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.0.tgz", + "integrity": "sha512-xyi6qjr/fYU304fiRwFbekzkqVJZ6A7hOjWZd+89FVcBqPV3S9Wuozz82xdpLspckeaafntbzglaW4pqpzvtSw==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/traverse": "^7.25.0", "globals": "^11.1.0" }, "engines": { @@ -941,13 +932,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", - "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.15" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -957,12 +948,12 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", - "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -972,13 +963,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", - "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -988,12 +979,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", - "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1002,13 +993,29 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", + "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", - "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { @@ -1019,13 +1026,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", - "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", "dev": true, "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1035,12 +1042,12 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", - "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { @@ -1051,13 +1058,13 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", - "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1067,14 +1074,14 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", - "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", + "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.1" }, "engines": { "node": ">=6.9.0" @@ -1084,12 +1091,12 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", - "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { @@ -1100,12 +1107,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", - "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", + "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1115,12 +1122,12 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", - "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { @@ -1131,12 +1138,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", - "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1146,13 +1153,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", - "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1162,14 +1169,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", - "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1179,15 +1186,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz", - "integrity": "sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", + "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", "dev": true, "dependencies": { - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-transforms": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -1197,13 +1204,13 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", - "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1213,13 +1220,13 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", - "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1229,12 +1236,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", - "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1244,12 +1251,12 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", - "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { @@ -1260,12 +1267,12 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", - "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { @@ -1276,16 +1283,15 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", - "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.23.3", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.23.3" + "@babel/plugin-transform-parameters": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1295,13 +1301,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", - "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1311,12 +1317,12 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", - "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { @@ -1327,13 +1333,13 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", - "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { @@ -1344,12 +1350,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", - "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1359,13 +1365,13 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", - "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", + "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1375,14 +1381,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", - "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -1393,12 +1399,12 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", - "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1408,12 +1414,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", - "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "regenerator-transform": "^0.15.2" }, "engines": { @@ -1424,12 +1430,12 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", - "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1439,16 +1445,16 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.7.tgz", - "integrity": "sha512-fa0hnfmiXc9fq/weK34MUV0drz2pOL/vfKWvN7Qw127hiUPabFCUMgAbYWcchRzMJit4o5ARsK/s+5h0249pLw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz", + "integrity": "sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "babel-plugin-polyfill-corejs2": "^0.4.7", - "babel-plugin-polyfill-corejs3": "^0.8.7", - "babel-plugin-polyfill-regenerator": "^0.5.4", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-regenerator": "^0.6.1", "semver": "^6.3.1" }, "engines": { @@ -1459,12 +1465,12 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", - "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1474,13 +1480,13 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", - "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1490,12 +1496,12 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", - "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1505,12 +1511,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", - "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1520,12 +1526,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", - "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1535,12 +1541,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", - "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1550,13 +1556,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", - "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1566,13 +1572,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", - "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1582,13 +1588,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", - "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", + "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1598,26 +1604,28 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.7.tgz", - "integrity": "sha512-SY27X/GtTz/L4UryMNJ6p4fH4nsgWbz84y9FE0bQeWJP6O5BhgVCt53CotQKHCOeXJel8VyhlhujhlltKms/CA==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.3.tgz", + "integrity": "sha512-QsYW7UeAaXvLPX9tdVliMJE7MD7M6MLYVTovRTIwhoYQVFHR1rM4wO8wqAezYi3/BpSD+NzVCZ69R6smWiIi8g==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.25.2", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.23.3", - "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", @@ -1629,59 +1637,60 @@ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.23.3", - "@babel/plugin-transform-async-generator-functions": "^7.23.7", - "@babel/plugin-transform-async-to-generator": "^7.23.3", - "@babel/plugin-transform-block-scoped-functions": "^7.23.3", - "@babel/plugin-transform-block-scoping": "^7.23.4", - "@babel/plugin-transform-class-properties": "^7.23.3", - "@babel/plugin-transform-class-static-block": "^7.23.4", - "@babel/plugin-transform-classes": "^7.23.5", - "@babel/plugin-transform-computed-properties": "^7.23.3", - "@babel/plugin-transform-destructuring": "^7.23.3", - "@babel/plugin-transform-dotall-regex": "^7.23.3", - "@babel/plugin-transform-duplicate-keys": "^7.23.3", - "@babel/plugin-transform-dynamic-import": "^7.23.4", - "@babel/plugin-transform-exponentiation-operator": "^7.23.3", - "@babel/plugin-transform-export-namespace-from": "^7.23.4", - "@babel/plugin-transform-for-of": "^7.23.6", - "@babel/plugin-transform-function-name": "^7.23.3", - "@babel/plugin-transform-json-strings": "^7.23.4", - "@babel/plugin-transform-literals": "^7.23.3", - "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", - "@babel/plugin-transform-member-expression-literals": "^7.23.3", - "@babel/plugin-transform-modules-amd": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-modules-systemjs": "^7.23.3", - "@babel/plugin-transform-modules-umd": "^7.23.3", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.23.3", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", - "@babel/plugin-transform-numeric-separator": "^7.23.4", - "@babel/plugin-transform-object-rest-spread": "^7.23.4", - "@babel/plugin-transform-object-super": "^7.23.3", - "@babel/plugin-transform-optional-catch-binding": "^7.23.4", - "@babel/plugin-transform-optional-chaining": "^7.23.4", - "@babel/plugin-transform-parameters": "^7.23.3", - "@babel/plugin-transform-private-methods": "^7.23.3", - "@babel/plugin-transform-private-property-in-object": "^7.23.4", - "@babel/plugin-transform-property-literals": "^7.23.3", - "@babel/plugin-transform-regenerator": "^7.23.3", - "@babel/plugin-transform-reserved-words": "^7.23.3", - "@babel/plugin-transform-shorthand-properties": "^7.23.3", - "@babel/plugin-transform-spread": "^7.23.3", - "@babel/plugin-transform-sticky-regex": "^7.23.3", - "@babel/plugin-transform-template-literals": "^7.23.3", - "@babel/plugin-transform-typeof-symbol": "^7.23.3", - "@babel/plugin-transform-unicode-escapes": "^7.23.3", - "@babel/plugin-transform-unicode-property-regex": "^7.23.3", - "@babel/plugin-transform-unicode-regex": "^7.23.3", - "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.0", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.25.0", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.25.0", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.7", - "babel-plugin-polyfill-corejs3": "^0.8.7", - "babel-plugin-polyfill-regenerator": "^0.5.4", - "core-js-compat": "^3.31.0", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", "semver": "^6.3.1" }, "engines": { @@ -1724,34 +1733,31 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz", + "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.3", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.2", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -1759,13 +1765,12 @@ } }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", + "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2593,14 +2598,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -2616,23 +2621,23 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2646,24 +2651,24 @@ "dev": true }, "node_modules/@pinia/testing": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@pinia/testing/-/testing-0.1.3.tgz", - "integrity": "sha512-D2Ds2s69kKFaRf2KCcP1NhNZEg5+we59aRyQalwRm7ygWfLM25nDH66267U3hNvRUOTx8ofL24GzodZkOmB5xw==", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@pinia/testing/-/testing-0.1.5.tgz", + "integrity": "sha512-AcGzuotkzhRoF00htuxLfIPBBHVE6HjjB3YC5Y3os8vRgKu6ipknK5GBQq9+pduwYQhZ+BcCZDC9TyLAUlUpoQ==", "dev": true, "dependencies": { - "vue-demi": ">=0.14.5" + "vue-demi": "^0.14.10" }, "funding": { "url": "https://github.com/sponsors/posva" }, "peerDependencies": { - "pinia": ">=2.1.5" + "pinia": ">=2.2.1" } }, "node_modules/@pinia/testing/node_modules/vue-demi": { - "version": "0.14.6", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", - "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", "dev": true, "hasInstallScript": true, "bin": { @@ -2721,44 +2726,24 @@ } }, "node_modules/@testing-library/jest-dom": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.2.0.tgz", - "integrity": "sha512-+BVQlJ9cmEn5RDMUS8c2+TU6giLvzaHZ8sU/x0Jj7fk+6/46wPdwlgOPcpxS17CjcanBi/3VmGMqVr2rmbUmNw==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.8.tgz", + "integrity": "sha512-JD0G+Zc38f5MBHA4NgxQMR5XtO5Jx9g86jqturNTt2WUfRmLDIY7iKkWHDCCTiDuFMre6nxAD5wHw9W5kI4rGw==", "dev": true, "dependencies": { - "@adobe/css-tools": "^4.3.2", + "@adobe/css-tools": "^4.4.0", "@babel/runtime": "^7.9.2", "aria-query": "^5.0.0", "chalk": "^3.0.0", "css.escape": "^1.5.1", "dom-accessibility-api": "^0.6.3", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "redent": "^3.0.0" }, "engines": { "node": ">=14", "npm": ">=6", "yarn": ">=1" - }, - "peerDependencies": { - "@jest/globals": ">= 28", - "@types/jest": ">= 28", - "jest": ">= 28", - "vitest": ">= 0.32" - }, - "peerDependenciesMeta": { - "@jest/globals": { - "optional": true - }, - "@types/jest": { - "optional": true - }, - "jest": { - "optional": true - }, - "vitest": { - "optional": true - } } }, "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { @@ -2981,117 +2966,109 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.5.tgz", - "integrity": "sha512-Daka7P1z2AgKjzuueWXhwzIsKu0NkLB6vGbNVEV2iJ8GJTrzraZo/Sk4GWCMRtd/qVi3zwnk+Owbd/xSZbwHtQ==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.6.tgz", + "integrity": "sha512-r+gNu6K4lrvaQLQGmf+1gc41p3FO2OUJyWmNqaIITaJU6YFiV5PtQSFZt8jfztYyARwqhoCayjprC7KMvT3nRA==", "dependencies": { - "@babel/parser": "^7.23.6", - "@vue/shared": "3.4.5", + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.6", "entities": "^4.5.0", "estree-walker": "^2.0.2", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" } }, "node_modules/@vue/compiler-dom": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.5.tgz", - "integrity": "sha512-J8YlxknJVd90SXFJ4HwGANSAXsx5I0lK30sO/zvYV7s5gXf7gZR7r/1BmZ2ju7RGH1lnc6bpBc6nL61yW+PsAQ==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.6.tgz", + "integrity": "sha512-xRXqxDrIqK8v8sSScpistyYH0qYqxakpsIvqMD2e5sV/PXQ1mTwtXp4k42yHK06KXxKSmitop9e45Ui/3BrTEw==", "dependencies": { - "@vue/compiler-core": "3.4.5", - "@vue/shared": "3.4.5" + "@vue/compiler-core": "3.5.6", + "@vue/shared": "3.5.6" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.5.tgz", - "integrity": "sha512-jauvkDuSSUbP0ebhfNqljhShA90YEfX/0wZ+w40oZF43IjGyWYjqYaJbvMJwGOd+9+vODW6eSvnk28f0SGV7OQ==", - "dependencies": { - "@babel/parser": "^7.23.6", - "@vue/compiler-core": "3.4.5", - "@vue/compiler-dom": "3.4.5", - "@vue/compiler-ssr": "3.4.5", - "@vue/shared": "3.4.5", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.6.tgz", + "integrity": "sha512-pjWJ8Kj9TDHlbF5LywjVso+BIxCY5wVOLhkEXRhuCHDxPFIeX1zaFefKs8RYoHvkSMqRWt93a0f2gNJVJixHwg==", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/compiler-core": "3.5.6", + "@vue/compiler-dom": "3.5.6", + "@vue/compiler-ssr": "3.5.6", + "@vue/shared": "3.5.6", "estree-walker": "^2.0.2", - "magic-string": "^0.30.5", - "postcss": "^8.4.32", - "source-map-js": "^1.0.2" + "magic-string": "^0.30.11", + "postcss": "^8.4.47", + "source-map-js": "^1.2.0" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.5.tgz", - "integrity": "sha512-DDdEcDzj2lWTMfUMMtEpLDhURai9LhM0zSZ219jCt7b2Vyl0/jy3keFgCPMitG0V1S1YG4Cmws3lWHWdxHQOpg==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.6.tgz", + "integrity": "sha512-VpWbaZrEOCqnmqjE83xdwegtr5qO/2OPUC6veWgvNqTJ3bYysz6vY3VqMuOijubuUYPRpG3OOKIh9TD0Stxb9A==", "dependencies": { - "@vue/compiler-dom": "3.4.5", - "@vue/shared": "3.4.5" + "@vue/compiler-dom": "3.5.6", + "@vue/shared": "3.5.6" } }, "node_modules/@vue/devtools-api": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.1.tgz", - "integrity": "sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==" + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==" }, "node_modules/@vue/reactivity": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.5.tgz", - "integrity": "sha512-BcWkKvjdvqJwb7BhhFkXPLDCecX4d4a6GATvCduJQDLv21PkPowAE5GKuIE5p6RC07/Lp9FMkkq4AYCTVF5KlQ==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.6.tgz", + "integrity": "sha512-shZ+KtBoHna5GyUxWfoFVBCVd7k56m6lGhk5e+J9AKjheHF6yob5eukssHRI+rzvHBiU1sWs/1ZhNbLExc5oYQ==", "dependencies": { - "@vue/shared": "3.4.5" + "@vue/shared": "3.5.6" } }, "node_modules/@vue/runtime-core": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.5.tgz", - "integrity": "sha512-wh9ELIOQKeWT9SaUPdLrsxRkZv14jp+SJm9aiQGWio+/MWNM3Lib0wE6CoKEqQ9+SCYyGjDBhTOTtO47kCgbkg==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.6.tgz", + "integrity": "sha512-FpFULR6+c2lI+m1fIGONLDqPQO34jxV8g6A4wBOgne8eSRHP6PQL27+kWFIx5wNhhjkO7B4rgtsHAmWv7qKvbg==", "dependencies": { - "@vue/reactivity": "3.4.5", - "@vue/shared": "3.4.5" + "@vue/reactivity": "3.5.6", + "@vue/shared": "3.5.6" } }, "node_modules/@vue/runtime-dom": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.5.tgz", - "integrity": "sha512-n5ewvOjyG3IEpqGBahdPXODFSpVlSz3H4LF76Sx0XAqpIOqyJ5bIb2PrdYuH2ogBMAQPh+o5tnoH4nJpBr8U0Q==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.6.tgz", + "integrity": "sha512-SDPseWre45G38ENH2zXRAHL1dw/rr5qp91lS4lt/nHvMr0MhsbCbihGAWLXNB/6VfFOJe2O+RBRkXU+CJF7/sw==", "dependencies": { - "@vue/runtime-core": "3.4.5", - "@vue/shared": "3.4.5", + "@vue/reactivity": "3.5.6", + "@vue/runtime-core": "3.5.6", + "@vue/shared": "3.5.6", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.5.tgz", - "integrity": "sha512-jOFc/VE87yvifQpNju12VcqimH8pBLxdcT+t3xMeiED1K6DfH9SORyhFEoZlW5TG2Vwfn3Ul5KE+1aC99xnSBg==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.6.tgz", + "integrity": "sha512-zivnxQnOnwEXVaT9CstJ64rZFXMS5ZkKxCjDQKiMSvUhXRzFLWZVbaBiNF4HGDqGNNsTgmjcCSmU6TB/0OOxLA==", "dependencies": { - "@vue/compiler-ssr": "3.4.5", - "@vue/shared": "3.4.5" + "@vue/compiler-ssr": "3.5.6", + "@vue/shared": "3.5.6" }, "peerDependencies": { - "vue": "3.4.5" + "vue": "3.5.6" } }, "node_modules/@vue/shared": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.5.tgz", - "integrity": "sha512-6XptuzlMvN4l4cDnDw36pdGEV+9njYkQ1ZE0Q6iZLwrKefKaOJyiFmcP3/KBDHbt72cJZGtllAc1GaHe6XGAyg==" + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.6.tgz", + "integrity": "sha512-eidH0HInnL39z6wAt6SFIwBrvGOpDWsDxlw3rCgo1B+CQ1781WzQUSU3YjxgdkcJo9Q8S6LmXTkvI+cLHGkQfA==" }, "node_modules/@vue/test-utils": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.3.tgz", - "integrity": "sha512-F4K7mF+ad++VlTrxMJVRnenKSJmO6fkQt2wpRDiKDesQMkfpniGWsqEi/JevxGBo2qEkwwjvTUAoiGJLNx++CA==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.6.tgz", + "integrity": "sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==", "dev": true, "dependencies": { "js-beautify": "^1.14.9", - "vue-component-type-helpers": "^1.8.21" - }, - "peerDependencies": { - "@vue/server-renderer": "^3.0.1", - "vue": "^3.0.1" - }, - "peerDependenciesMeta": { - "@vue/server-renderer": { - "optional": true - } + "vue-component-type-helpers": "^2.0.0" } }, "node_modules/@vue/vue3-jest": { @@ -3275,11 +3252,11 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.4.tgz", - "integrity": "sha512-heJnIs6N4aa1eSthhN9M5ioILu8Wi8vmQW9iHQ9NUvfkJb0lEEDUiIdQNAuBtfUt3FxReaKdpQA5DbmMOqzF/A==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -3407,13 +3384,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.7.tgz", - "integrity": "sha512-LidDk/tEGDfuHW2DWh/Hgo4rmnw3cduK6ZkOI1NPFceSK3n/yAGeOsNT7FLnSGHkXj3RHGSEVkN3FsCTY6w2CQ==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.4.4", + "@babel/helper-define-polyfill-provider": "^0.6.2", "semver": "^6.3.1" }, "peerDependencies": { @@ -3421,25 +3398,25 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz", - "integrity": "sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==", + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.4", - "core-js-compat": "^3.33.1" + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.4.tgz", - "integrity": "sha512-S/x2iOCvDaCASLYsOOgWOq4bCfKYVqvO/uxjkaYyZ3rVsVE3CeAI/c84NpyuBBymEgNvHgjEot3a9/Z/kXvqsg==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.4" + "@babel/helper-define-polyfill-provider": "^0.6.2" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -3528,9 +3505,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "dev": true, "funding": [ { @@ -3547,10 +3524,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -3593,9 +3570,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001574", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001574.tgz", - "integrity": "sha512-BtYEK4r/iHt/txm81KBudCUcTy7t+s9emrIaHqjYurQ10x71zJ5VQ9x1dYPcz/b+pKSp4y/v1xSI67A+LzpNyg==", + "version": "1.0.30001651", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", + "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", "dev": true, "funding": [ { @@ -3777,12 +3754,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.0.tgz", - "integrity": "sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw==", + "version": "3.38.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.0.tgz", + "integrity": "sha512-75LAicdLa4OJVwFxFbQR3NdnZjNgX6ILpVcVzcC4T2smerB5lELMrJQQQoWV6TiuC/vlaFqgU2tKQx9w5s0e0A==", "dev": true, "dependencies": { - "browserslist": "^4.22.2" + "browserslist": "^4.23.3" }, "funding": { "type": "opencollective", @@ -3957,10 +3934,77 @@ "node": ">=12" } }, + "node_modules/datatables.net": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-2.1.6.tgz", + "integrity": "sha512-ziX0Wz91oDJ4o7gQNuGxQiVK91OUu/bRcXyxa6EZtDwLObmaGKpkCNS59QpzrGtIytQIVFtLfF1EDdYid5RVog==", + "dependencies": { + "jquery": ">=1.7" + } + }, + "node_modules/datatables.net-bm": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/datatables.net-bm/-/datatables.net-bm-2.1.6.tgz", + "integrity": "sha512-JOrDvPQ1/j6z1cO8QFMISbQSIoO4nJOQn56oCn/a187ZR3Hv5DT59tMcEcF88obYcokmVKPIOmsQ7hqo6HcQ+g==", + "dependencies": { + "datatables.net": "2.1.6", + "jquery": ">=1.7" + } + }, + "node_modules/datatables.net-searchpanes": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/datatables.net-searchpanes/-/datatables.net-searchpanes-2.3.2.tgz", + "integrity": "sha512-I1sgKL3JiXtQhGJT3sbIpkN+czCjAox+gmyV6UBgHFQcAyspHhl1KnPdm/nWmABhPAIIM2RLotyh4U+A/0Z4hQ==", + "dependencies": { + "datatables.net": "^2", + "jquery": ">=1.7" + } + }, + "node_modules/datatables.net-searchpanes-bm": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/datatables.net-searchpanes-bm/-/datatables.net-searchpanes-bm-2.3.2.tgz", + "integrity": "sha512-O4iPgdICaOKzSast8YLcHy9cMmgKtpqvDsuFHwXArvfRmKA6Jdl6viPHCyjer8FAWBKWQCvoyKETTBnLV2UoXA==", + "dependencies": { + "datatables.net-bm": "^2", + "datatables.net-searchpanes": "2.3.2", + "jquery": ">=1.7" + } + }, + "node_modules/datatables.net-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/datatables.net-select/-/datatables.net-select-2.1.0.tgz", + "integrity": "sha512-6B1sI5pfvBen+8kySl1T0hkGoUmrw+5YGqaW4NCg+1srMw+48YV5SdWPiyCQDoev2ajBdKzHuG/wzD2INMbmJw==", + "dependencies": { + "datatables.net": "^2", + "jquery": ">=1.7" + } + }, + "node_modules/datatables.net-select-bm": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/datatables.net-select-bm/-/datatables.net-select-bm-2.1.0.tgz", + "integrity": "sha512-75Maykp2FfuCC4g9B2blQ2t7llNpS7BsdyKbuctvjdAVJdZ6kJX5PQo44nGzSW+ZAgC5/FKEfsekOiImMiC+ew==", + "dependencies": { + "datatables.net-bm": "^2", + "datatables.net-select": "2.1.0", + "jquery": ">=1.7" + } + }, + "node_modules/datatables.net-vue3": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/datatables.net-vue3/-/datatables.net-vue3-3.0.2.tgz", + "integrity": "sha512-UJs3IrKS+gsaPSy3CeL5ny/hGWm8xs77DZLYSW8QXPpDhMS7ZZfC4AGKNvXa2C9J1OllWhiR20dScpi0lKdCvQ==", + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "datatables.net": "^2", + "vue": "^3.0.5" + } + }, "node_modules/date-fns": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.0.6.tgz", - "integrity": "sha512-W+G99rycpKMMF2/YD064b2lE7jJGUe+EjOES7Q8BIGY8sbNdbgcs9XFTZwvzc9Jx1f3k7LB7gZaZa7f8Agzljg==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", "funding": { "type": "github", "url": "https://github.com/sponsors/kossnocorp" @@ -4138,9 +4182,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.621", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.621.tgz", - "integrity": "sha512-MGJM6S0MuF/wTzM9NoItWXN56J1kolrHS/vzl/KlhXAbVkogTy0wzKYliQDJgNypxSCFjxdRhHYS3bffyYUGEw==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.9.tgz", + "integrity": "sha512-HfkT8ndXR0SEkU8gBQQM3rz035bpE/hxkZ1YIt4KJPEFES68HfIU6LzKukH0H794Lm83WJtkSAMfEToxCs15VA==", "dev": true }, "node_modules/emittery": { @@ -4219,9 +4263,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" @@ -6548,6 +6592,11 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==" + }, "node_modules/js-beautify": { "version": "1.14.11", "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.11.tgz", @@ -6786,14 +6835,11 @@ "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=" }, "node_modules/magic-string": { - "version": "0.30.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", - "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "engines": { - "node": ">=12" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/make-dir": { @@ -6860,12 +6906,12 @@ "dev": true }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -6975,9 +7021,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true }, "node_modules/nopt": { @@ -7203,9 +7249,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -7220,12 +7266,12 @@ } }, "node_modules/pinia": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz", - "integrity": "sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.2.2.tgz", + "integrity": "sha512-ja2XqFWZC36mupU4z1ZzxeTApV7DOw44cV4dhQ9sGwun+N89v/XP7+j7q6TanS1u1tdbK4r+1BUx7heMaIdagA==", "dependencies": { - "@vue/devtools-api": "^6.5.0", - "vue-demi": ">=0.14.5" + "@vue/devtools-api": "^6.6.3", + "vue-demi": "^0.14.10" }, "funding": { "url": "https://github.com/sponsors/posva" @@ -7245,9 +7291,9 @@ } }, "node_modules/pinia/node_modules/vue-demi": { - "version": "0.14.6", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", - "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", "hasInstallScript": true, "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", @@ -7291,9 +7337,9 @@ } }, "node_modules/postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "funding": [ { "type": "opencollective", @@ -7310,8 +7356,8 @@ ], "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -7578,9 +7624,9 @@ } }, "node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "version": "3.29.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", + "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -7606,9 +7652,9 @@ "dev": true }, "node_modules/sass": { - "version": "1.69.7", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.7.tgz", - "integrity": "sha512-rzj2soDeZ8wtE2egyLXgOOHQvaC2iosZrkF6v3EUG+tBwEvhqUCzm0VP3k9gHF9LXbSrRhT5SksoI56Iw8NPnQ==", + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", + "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -7695,9 +7741,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "engines": { "node": ">=0.10.0" } @@ -7908,7 +7954,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, "engines": { "node": ">=4" } @@ -8047,9 +8092,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "dev": true, "funding": [ { @@ -8066,8 +8111,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -8107,9 +8152,9 @@ "dev": true }, "node_modules/vite": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", - "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.5.tgz", + "integrity": "sha512-ifW3Lb2sMdX+WU91s3R0FyQlAyLxOzCSCP37ujw0+r5POeHPwe6udWVIElKQq8gk3t7b8rkmvqC6IHBpCff4GQ==", "dev": true, "dependencies": { "esbuild": "^0.18.10", @@ -8162,15 +8207,15 @@ } }, "node_modules/vue": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.5.tgz", - "integrity": "sha512-VH6nHFhLPjgu2oh5vEBXoNZxsGHuZNr3qf4PHClwJWw6IDqw6B3x+4J+ABdoZ0aJuT8Zi0zf3GpGlLQCrGWHrw==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.6.tgz", + "integrity": "sha512-zv+20E2VIYbcJOzJPUWp03NOGFhMmpCKOfSxVTmCYyYFFko48H9tmuQFzYj7tu4qX1AeXlp9DmhIP89/sSxxhw==", "dependencies": { - "@vue/compiler-dom": "3.4.5", - "@vue/compiler-sfc": "3.4.5", - "@vue/runtime-dom": "3.4.5", - "@vue/server-renderer": "3.4.5", - "@vue/shared": "3.4.5" + "@vue/compiler-dom": "3.5.6", + "@vue/compiler-sfc": "3.5.6", + "@vue/runtime-dom": "3.5.6", + "@vue/server-renderer": "3.5.6", + "@vue/shared": "3.5.6" }, "peerDependencies": { "typescript": "*" @@ -8182,17 +8227,17 @@ } }, "node_modules/vue-component-type-helpers": { - "version": "1.8.27", - "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-1.8.27.tgz", - "integrity": "sha512-0vOfAtI67UjeO1G6UiX5Kd76CqaQ67wrRZiOe7UAb9Jm6GzlUr/fC7CV90XfwapJRjpCMaZFhv1V0ajWRmE9Dg==", + "version": "2.0.29", + "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-2.0.29.tgz", + "integrity": "sha512-58i+ZhUAUpwQ+9h5Hck0D+jr1qbYl4voRt5KffBx8qzELViQ4XdT/Tuo+mzq8u63teAG8K0lLaOiL5ofqW38rg==", "dev": true }, "node_modules/vue-router": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.2.5.tgz", - "integrity": "sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.5.tgz", + "integrity": "sha512-4fKZygS8cH1yCyuabAXGUAsyi1b2/o/OKgu/RUb+znIYOxPRxdkytJEx+0wGcpBE1pX6vUgh5jwWOKRGvuA/7Q==", "dependencies": { - "@vue/devtools-api": "^6.5.0" + "@vue/devtools-api": "^6.6.4" }, "funding": { "url": "https://github.com/sponsors/posva" diff --git a/static/js/admin/vue-cdr-admin/package.json b/static/js/admin/vue-cdr-admin/package.json new file mode 100644 index 0000000000..6964a60d8d --- /dev/null +++ b/static/js/admin/vue-cdr-admin/package.json @@ -0,0 +1,43 @@ +{ + "name": "vue-permissions-editor", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "vite", + "serve": "vite preview", + "build": "vite build", + "test": "jest" + }, + "dependencies": { + "axios": "^1.7.7", + "datatables.net": "^2.1.6", + "datatables.net-bm": "^2.1.6", + "datatables.net-searchpanes-bm": "^2.3.2", + "datatables.net-select-bm": "^2.1.0", + "datatables.net-vue3": "^3.0.2", + "date-fns": "^3.6.0", + "lodash.clonedeep": "^4.5.0", + "lodash.findindex": "^4.6.0", + "lodash.isempty": "^4.4.0", + "pinia": "^2.2.2", + "vue": "^3.5.6", + "vue-router": "^4.4.5" + }, + "devDependencies": { + "@babel/plugin-transform-runtime": "^7.24.7", + "@babel/preset-env": "^7.25.3", + "@pinia/testing": "0.1.5", + "@testing-library/jest-dom": "^6.4.8", + "@vitejs/plugin-vue": "^4.6.2", + "@vue/compiler-sfc": "^3.5.6", + "@vue/test-utils": "2.4.6", + "@vue/vue3-jest": "^29.2.6", + "babel-jest": "^29.7.0", + "caniuse-lite": "^1.0.30001651", + "jest": "29.7.0", + "jest-environment-jsdom": "^29.7.0", + "moxios": "^0.4.0", + "sass": "^1.77.8", + "vite": "4.5.5" + } +} diff --git a/static/js/admin/vue-permissions-editor/src/App.vue b/static/js/admin/vue-cdr-admin/src/App.vue similarity index 62% rename from static/js/admin/vue-permissions-editor/src/App.vue rename to static/js/admin/vue-cdr-admin/src/App.vue index 9cee4d7ded..224acbcc88 100644 --- a/static/js/admin/vue-permissions-editor/src/App.vue +++ b/static/js/admin/vue-cdr-admin/src/App.vue @@ -1,5 +1,5 @@ \ No newline at end of file diff --git a/static/js/admin/vue-permissions-editor/src/assets/common-styles.css b/static/js/admin/vue-cdr-admin/src/assets/common-styles.css similarity index 98% rename from static/js/admin/vue-permissions-editor/src/assets/common-styles.css rename to static/js/admin/vue-cdr-admin/src/assets/common-styles.css index fb4f220ae3..42a50a2c73 100644 --- a/static/js/admin/vue-permissions-editor/src/assets/common-styles.css +++ b/static/js/admin/vue-cdr-admin/src/assets/common-styles.css @@ -215,4 +215,10 @@ .slide-enter, .slide-leave-to { max-height: 0 +} + +.pull-right, +.buttons.pull-right { + display: flex; + justify-content: flex-end; } \ No newline at end of file diff --git a/static/js/admin/vue-cdr-admin/src/components/chompb/preIngest.vue b/static/js/admin/vue-cdr-admin/src/components/chompb/preIngest.vue new file mode 100644 index 0000000000..c408ea4065 --- /dev/null +++ b/static/js/admin/vue-cdr-admin/src/components/chompb/preIngest.vue @@ -0,0 +1,157 @@ + + + + + + \ No newline at end of file diff --git a/static/js/admin/vue-cdr-admin/src/components/chompb/velocicroptorReport.vue b/static/js/admin/vue-cdr-admin/src/components/chompb/velocicroptorReport.vue new file mode 100644 index 0000000000..962663f874 --- /dev/null +++ b/static/js/admin/vue-cdr-admin/src/components/chompb/velocicroptorReport.vue @@ -0,0 +1,212 @@ + + + + + + \ No newline at end of file diff --git a/static/js/admin/vue-permissions-editor/src/components/embargo.vue b/static/js/admin/vue-cdr-admin/src/components/permissions-editor/embargo.vue similarity index 99% rename from static/js/admin/vue-permissions-editor/src/components/embargo.vue rename to static/js/admin/vue-cdr-admin/src/components/permissions-editor/embargo.vue index 4713363750..12efabaf7d 100644 --- a/static/js/admin/vue-permissions-editor/src/components/embargo.vue +++ b/static/js/admin/vue-cdr-admin/src/components/permissions-editor/embargo.vue @@ -46,7 +46,7 @@ - - \ No newline at end of file diff --git a/static/js/vue-cdr-access/src/components/full_record/fileRecord.vue b/static/js/vue-cdr-access/src/components/full_record/fileRecord.vue index e3c39508ca..e579805647 100644 --- a/static/js/vue-cdr-access/src/components/full_record/fileRecord.vue +++ b/static/js/vue-cdr-access/src/components/full_record/fileRecord.vue @@ -35,16 +35,6 @@ {{ $t('full_record.creator') }}: {{ recordData.briefObject.creator.join('; ') }} -
  • {{ $t('full_record.date_created') }}: {{ formatDate(recordData.briefObject.created) }} diff --git a/static/js/vue-cdr-access/src/components/full_record/player.vue b/static/js/vue-cdr-access/src/components/full_record/player.vue index c0ebbb762a..3bd63bfc63 100644 --- a/static/js/vue-cdr-access/src/components/full_record/player.vue +++ b/static/js/vue-cdr-access/src/components/full_record/player.vue @@ -1,20 +1,20 @@